Вот переработанный вариант:
class PurchaseForm
include ActiveModel::Model
def self.attributes
[:name, :surname, :email]
end
attr_accessor *self.attributes
# your validations
def to_hash
self.class.attributes.inject({}) do |hash, key|
hash.merge({ key => self.send(key) })
end
end
end
Теперь вы можете легко работать с этим классом:
irb(main):001:0> a = PurchaseForm.new({ name: 'Name' })
=> #<PurchaseForm:0x00000002606b50 @name="Name">
irb(main):002:0> a.to_hash
=> {:name=>"Name", :surname=>nil, :email=>nil}
irb(main):003:0> a.email = 'user@example.com'
=> "user@example.com"
irb(main):004:0> a
=> #<PurchaseForm:0x00000002606b50 @name="Name", @email="user@example.com">
irb(main):005:0> a.to_hash
=> {:name=>"Name", :surname=>nil, :email=>"user@example.com"}
Более того, если вы хотите сделать это поведение многоразовым, рассмотрите возможность извлечения методов .attributes
и #to_hash
в отдельный модуль:
module AttributesHash
extend ActiveSupport::Concern
class_methods do
def attr_accessor(*args)
@attributes = args
super(*args)
end
def attributes
@attributes
end
end
included do
def to_hash
self.class.attributes.inject({}) do |hash, key|
hash.merge({ key => self.send(key) })
end
end
end
end
Теперь просто включите его в свою модель, и все готово:
class PurchaseForm
include ActiveModel::Model
include AttributesHash
attr_accessor :name, :surname, :email
# your validations
end