iT邦幫忙

2022 iThome 鐵人賽

DAY 2
0
Software Development

Rails Active Model系列 第 2

D-2 Active Model 本身有什麼功能? - assign_attributes

  • 分享至 

  • xImage
  •  

有使用過 Active Model 的朋友應該都知道,只要在 new 時傳入一包 params,他就會自動把每個 value 按照 key 塞進 object 裡。
For example:

class ArticleForm
  include ActiveModel::Model
  attr_accessor :title, :content
end

ArticleForm.new(title: '標題', content: '內容')

=> <ArticleForm:0x000000001260c608 @title="標題", @content="內容">
# 會得到擁有 @title="標題" 以及 @content="內容" 的 object

但你知道為什麼嗎?
這是因為,Active Model 本身的 initialize 會用到 assign_attributes 這個方法,把傳入的 params 一個個塞進去。
而這個功能其實是由 ActiveModel::AttributeAssignment 這包 module 提供的。

一般狀況下,如果我們的 initialize 想要做到一樣的效果,把 value 一個個傳進來,應該會寫成這樣:

class ArticleForm
  def initialize(params = {})
    @title = params[:title]
    @content = params[:content]
    .... # 有幾個 attribute ,就要寫多長
  end
end

通常的做法都是這樣,一個個 assign 為 instance variable。
但隨著你的 service 日後不斷擴充,增加更多的 attr,這個 initialize 只會越來越長越來越亂,很難看。
如果你想要有 Active Model 可以自動傳入 params 的功能,但又嫌這 module 太大包,很多功能用不到,那你可以試試看 ActiveModel::AttributeAssignment

class ArticleForm
  include ActiveModel::AttributeAssignment
  attr_accessor *%i(title content ...) # 日後擴充 attr 只需要加在這邊就好
  def initialize(params)
    assign_attributes(params)
  end
end

ArticleForm.new(title: '標題', content: '內容')

=> <ArticleForm:0x00007f987b08d890 @title="標題", @content="內容">
# 得到跟上面一樣的結果

甚至,如果你的 initialize 功能很單純只是要傳入的話,你甚至可以這樣,一行解決:

  alias_method :initialize, :assign_attributes

這樣你的 code 就可以免掉很多重複的 assignment ,還你乾淨漂亮簡潔的 class!


上一篇
D-1 序:為什麼要研究 Active Model
下一篇
D-3 Active Model 本身有什麼功能? - define_model_callbacks
系列文
Rails Active Model28
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言