2011-03-28 54 views
7

如何获取ActiveRecord属性方法功能?我有这个类:ActiveModel属性

class PurchaseForm 
    include ActiveModel::Validations 
    include ActiveModel::Conversion 
    extend ActiveModel::Naming 

    attr_accessor :name, 
       :surname, 
       :email 

    validates_presence_of :name 

    validates_format_of :email, :with => /^[-a-z0-9_+\.]+\@([-a-z0-9]+\.)+[a-z0-9]{2,4}$/i 

    def initialize(attributes = {}, shop_name) 
    if not attributes.nil? 
     attributes.each do |name, value| 
     send("#{name}=", value) 
    end 
    end 

    def persisted? 
    false 
    end 
end 

我需要做什么,有一个属性方法列出来自PurchaseForm对象的所有名称和值?

+0

鉴于哈克现有的答案,正确的答案似乎是“没有Rails的模块那”。就个人而言,我会避免模仿属性API。 – vemv 2016-10-17 15:47:08

回答

6

我已经设法解决问题与此代码:

class PurchaseForm 
    include ActiveModel::Validations 
    include ActiveModel::Conversion 
    extend ActiveModel::Naming 

    attr_accessor :attributes, 
       :name, 
       :surname, 
       :email 

    validates_presence_of :name 

    validates_format_of :email, :with => /^[-a-z0-9_+\.]+\@([-a-z0-9]+\.)+[a-z0-9]{2,4}$/i 

    def initialize(attributes = {}) 
    @attributes = attributes 
    end 

    def persisted? 
    false 
    end 
end 
+0

为什么添加:attr_accessor调用的属性? – Craig 2011-03-28 18:12:08

+0

所以我可以从视图中调用属性方法...我几乎是Rails新手,所以如果你有更好的解决方案,请分享:) – zigomir 2011-03-29 07:22:21

+0

这个解决方案有缺点。如果您不会将所有属性传递给'.new',那么'.attributes'只会返回具有指定属性的错误散列。第二,如果你尝试在初始化后改变实例,比如说'@purchase_form.name ='其他名称',然后调用'@ purchase_form.attributes',哈希将包含提供给'.new'的旧':name'。 – 2015-08-28 21:35:11

-3

岂不是更好地使用

include ActiveModel::Serialization 

def attributes 
    JSON.parse(self.to_json) 
end 
9

这里是重构变种:

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 = '[email protected]' 
=> "[email protected]" 
irb(main):004:0> a 
=> #<PurchaseForm:0x00000002606b50 @name="Name", @email="[email protected]"> 
irb(main):005:0> a.to_hash 
=> {:name=>"Name", :surname=>nil, :email=>"[email protected]"} 

更有甚者,如果你想使这种行为可重复使用,考虑.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 
6

#instance_values可以做的工作:

class PurchaseForm 
    attr_accessor :name, :email 

    def attributes 
    instance_values 
    end 
end 

输出样本:

purchase.attributes #=> {"name"=>"John", "email"=>"[email protected]"} 
相关问题