動機
也許有需要,也複習一下rails
||=
foo, bar = [], 1
foo ||= bar # foo = foo || bar
foo
這邊弔詭的是false value,也就是什麼value會被視為false
hash default value
default value不會自己被copy喔
還有後面看到的值寫不進去hash,應該牽涉到ruby處理method call的方式
a = hsh[:something]
a.send(:=, val)
hsh = Hash.new([])
hsh[:one] << 'one'
hsh[:two] << 'two'
hsh[:nonexistent]
# => ['one', 'two']
hsh
# => {}
hsh = Hash.new([])
hsh[:one] += ['one']
hsh[:two] += ['two']
# This is syntactic sugar for hsh[:two] = hsh[:two] + ['two']
hsh[:nonexistant]
# => []
hsh
# => { :one => ['one'], :two => ['two'] }
hsh = Hash.new { [] }
# This time, instead of a default *value*, we use a default *block*
hsh[:one] << 'one'
hsh[:two] << 'two'
hsh[:nonexistent]
# => []
# We *did* mutate the default value, but it was a fresh one every time.
hsh
# => {}
# But we never mutated the hash itself, therefore it is still empty!
hsh = Hash.new {|hsh, key| hsh[key] = [] }
hsh[:one] << 'one'
hsh[:two] << 'two'
hsh[:nonexistent]
# => []
# We *did* mutate the default value, but it was a fresh one every time.
hsh
# => { :one => ['one'], :two => ['two'], :nonexistent => [] }
proc & lambda & block
block沒有apply的一串代碼 lambda正常的lambda proc有點像macro(可以當成裡面的code複製貼上),但有自己的scope
def whowouldwin
mylambda = lambda {return "Freddy"}
mylambda.call
# mylambda gets called and returns "Freddy", and execution
# continues on the next line
return "Jason"
end
whowouldwin
#=> "Jason"
# Proc returns control not just from the proc, but also from the method enclosing the proc!
def whowouldwin2
myproc = Proc.new {return "Freddy"}
myproc.call
# myproc gets called and returns "Freddy",
# but also returns control from whowhouldwin2!
# The line below *never* gets executed.
return "Jason"
end
whowouldwin2
#=> "Freddy"
equal
- == : 值
- eql? : 值 & type
- equal? : 記憶體位置
- === : lhs.includes?(rhs)
p Fixnum === 1 # => true
p 1 === Fixnum # => false
p 100 == 100.0 # => true
p 100.eql? 100.0 # => false
tap
就是把instance丟到block中跑再丟回原本的instance
# x 就是物件,caller,或是receiver
(1..5).tap { |x| puts "element: #{x.inspect}" }.to_a
# => element: 1..5
.tap { |x| puts "array: #{x.inspect}" }
# => array: [1, 2, 3, 4, 5]
.select { |x| x%2 == 0 }
.tap{ |x| puts "evens: #{x.inspect}" }
# => evens: [2, 4]
.map{ |x| x*x }
.tap{ |x| puts "squares: #{x.inspect}" }
# => squares: [4, 16]
Present and exist
present: 看是不是false value
[ "", " ", false, nil, [], {} ].any?(&:present?)
# => false
用在orm上會悲劇
User.where(name: 'mike').present?
# User Load (8.1ms) SELECT "users".* FROM "users" WHERE "users"."name" = $1 ORDER BY users.id ASC [["name", 'mike']]
exist: 基本上是用在orm上,看有沒有row存在
User.exists?(name: 'mike')
# User Exists (2.4ms) SELECT 1 AS one FROM "users" WHERE "users"."name" = $1 ORDER BY users.id ASC LIMIT 1 [["name", 'mike']]
# 如果是any? 1 AS one的部分會變成COUNT(*)
freeze
freeze可以當成c++的const
所以會有
int*
- pointer to intint const *
- pointer to const intint * const
- const pointer to int
就是在Pointer上的const或是在pointer內容的const
N+1 query
class User < ActiveRecord::Base
has_many :clients
end
class Client < ActiveRecord::Base
has_many :contacts
belongs_to :user
end
class Contact < ActiveRecord::Base
belongs_to :client
end
@contacts = @user.clients.includes( :contact )
class Post < ActiveRecord::Base
has_many :comments
belongs_to :user
end
class Comment < ActiveRecord::Base
has_many :replies
belongs_to :user
end
class Reply < ActiveRecord::Base
belongs_to :user
end
class User < ActiveRecord::Base
has_many :posts
has_many :comments
has_many :replies
end
# 不包含user
Post.includes(:comments => [:replies])
# 包含user
Post.includes(:user, :comments= > [:user, {:replies => [:user]}])
如果是在別的table的東西就可以先用includes來preload
test data: fixture & factory bot
Rails內建有Fixture功能可以建立假資料,方法是為每個Model使用一份YAML資料。 Fixture的缺點是它是直接插入資料進資料庫而不使用ActiveRecord,對於複雜的Model資料建構或關連,會比較麻煩。
FactoryGirl這套工具,相較於Fixture的缺點是建構速度較慢。
order = FactoryBot.create(
:order,
line_items: [FactoryBot.create(:line_item, price_cents: 40000)],
payments: [FactoryBot.create(:payment, amount_cents: 40000)]
)
# orders.yml
payments_equal_line_item_total:
# no attributes needed
# line_items.yml
electric_dog_polisher:
order: payments_equal_line_item_total
name: 'Electric dog polisher'
price_cents: 40000
# payment_methods.yml
visa:
name: 'Visa'
# payments.yml
first:
order: payments_equal_line_item_total
payment_method: visa
amount_cents: 40000
# order = orders(:payments_equal_line_item_total)
RESTful & CURD
這裡可以看成對array操作 像
arr # events_path, GET
arr[i] # event_path(@event), GET
arr << "something" # events_path, POST
arr.delete(i) # event_path(@event), DELETE
arr.update(i, "something") # event_path(@event), PATCH/PUT
那為什麼需要
- edit_event_path(@event)
- new_event_path
- event_path(@event)
的GET
因為我們透過網頁與user互動,把input轉成資料再調用診真正的action
helper | GET | POST | PATCH/PUT | DELETE |
---|---|---|---|---|
event_path(@event) | /events/1 : show action | /events/1 : update action | /events/1 : destroy action | |
events_path | /events : index action | /events : create action | ||
edit_event_path(@event) | /events/1/edit : edit action | |||
new_event_path | /events/new : new action |
how to handle req & header
orm callback
Ref
菜鳥Rails工作面試初體驗 Jr. Ruby on Rails Engineer面試初體驗(上) See also: 我的中高階 Rails 工作面試心得分享 面試 interview Ruby 重要概念整理 Ruby hash default value behavior Ruby面試精選30題 - Day29 Ruby的tap method Ruby面試精選30題 - Day23 Ruby的’==’,’===’ ’eql?’ ’equal?’ When to use lambda, when to use Proc.new? Web, Rails, 用巢狀include和查表方式來避免 n+1 query A Visual Guide to Using :includes in Rails Ruby on Rails 實戰聖經 Factories and fixtures in Rails See also: Fast Ruby