iT邦幫忙

2022 iThome 鐵人賽

DAY 24
0
Software Development

Rails Active Model系列 第 24

D-24 從 attribute 導入自定義參數

  • 分享至 

  • xImage
  •  

attribute 這個 class method 其實有限定 options key word ,只能傳入

[:precision, :limit, :scale, :default]

那這個 options 定義背後會經過很多層的傳遞,其中,:default 會在途中被 delete 去掉。
最後,這包 options 會傳到繼承 ActiveModel::Type::Value 的一系列資料轉換器的 initialize
前述限定 key 的部分也是在這邊去限定的。

那根據前篇,如果我想要我的 active model class 可以在 attribute 導入自定義參數,
好讓我的 form builder 可以在 render_by_type 階段藉由讀取 type object 去讀到我的自定義參數,進而做一些進階的 render 判斷,我該怎麼做?

hack 掉 ActiveModel::Type::Value#initialize:

# in config/initializers
class ActiveModel::Type::Value
  # 把原生的 initialize 保留起來
  alias_method :regular_initialize, :initialize

  # 建立一個 options 作為儲存自訂參數的地方
  attr_reader :options

  def initialize(options = {})
    # hash.slice! 這方法除了會篩 hash 自身之外,還會額外 return 回被篩掉的部分,一個 method 兩個用途,很方便
    @options = options.slice!(:precision, :limit, :scale)
    regular_initialize(options)
  end
end

接著引用如前一篇的示例,我們加一點不一樣的參數在 attribute 裡面,看看 attribute_types 裡面的結構會變怎樣:

class MyCls
  include ActiveModel::Model
  include ActiveModel::Attributes

  attribute :name, :string, default: 'blabla', foo: 'bar'
  attribute :accept_privacy_policy, :boolean, default: false, may: 'day'
  attribute :age, :integer, default: 13
end

pp MyCls.attribute_types
{"name"=>
  #<ActiveModel::Type::String:0x00007f904332c550
   @limit=nil,
   @options={:foo=>"bar"},
   @precision=nil,
   @scale=nil>,
 "accept_privacy_policy"=>
  #<ActiveModel::Type::Boolean:0x00007f9043319ef0
   @limit=nil,
   @options={:may=>"day"},
   @precision=nil,
   @scale=nil>,
 "age"=>
  #<ActiveModel::Type::Integer:0x00007f9043333d78
   @limit=nil,
   @options={},
   @precision=nil,
   @range=-2147483648...2147483648,
   @scale=nil>}

# 自定義參數都被存在 @options 裡了!

這樣一來,就可以把您針對您的 attribute 內傳入的自訂參數給一起傳到 type object,再傳到 form builder 裡了!


上一篇
D-23 如何讀取我的 active model class 已經設定的 attributes ?
下一篇
D-25 該如何規劃 form object 的 life cycle ?
系列文
Rails Active Model28
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言