2010-11-03 78 views
0
class Song < ActiveRecord::Base 
    # Uses an integer of seconds to hold the length of the song 

    def length=(minutes) 
     write_attribute(:length, minutes.to_i * 60) 
    end 

    def length 
     read_attribute(:length)/60 
    end 
    end 

这是一个简单的例子,由rails api doc。覆盖导轨模型中的所有默认访问器

是否可以覆盖模型的所有属性而不覆盖每个属性?

回答

0

你是否在寻找类似的东西?不知道你为什么想这样做,但在这里你去:)

class Song < ActiveRecord::Base 

    self.columns_hash.keys.each do |name| 
    define_method :"#{name}=" do 
     # set 
    end 

    define_method :"#{name}" do 
     # get 
    end 

    # OR 

    class_eval(<<-METHOD, __FILE__, __LINE__ + 1) 
     def #{name}= 
     # set 
     end 

     def #{name} 
     # get 
     end 
    METHOD 

    end 

end 
+0

在这种情况下,我有存储国际化内容(标题,title_portuguse,title_english)字段的表,然后我想修改此方法的行为以根据语言显示数据而不修改视图。 – 2010-11-03 14:01:10

+1

你可以看看globalize2插件,它可以使用像content.title这样的本地化属性。 我不太喜欢他们的做法。他们实质上创建了一个content_translations表,其中所有已翻译的属性都是列,然后载入匹配I18n.locale的翻译记录。 'content.title'然后成为'content.translation(locale).title'的代理。 在我的下一个本地化应用程序中,我将跳过插件并手动创建这些表并创建ContentTranslation模型。这更清楚,你知道你在处理什么样的对象。 – balu 2010-11-03 14:10:33

0

我不确定这是一个好主意的用例。但是,所有的rails模型动态地赋予它们的属性(假设它不在类中)。答案部分在你的问题中。

您可以覆盖read_attribute()和write_attribute()方法。这会将您的转换应用于每个属性,无论它们是由访问者写入还是在控制器中批量填充。只要小心不要突变重要的属性,如'id'属性。

Ruby有一个快捷方式,在rails代码中使用一个公平的位,可以帮助你。这是%w关键字。 %w将根据圆括号内的符号创建一个单词数组。因为它是一个数组,你可以做有用的事情是这样的:

@excludes = %w(id, name) 

def read_attribute name 
    value = super 
    if(not @excludes.member? name) 
     value = value.to_i * 60 
    end 

    value 
end 

def write_attribute name, value 
    if(not @excludes.member? name) 
     value = value.to_i/60 
    end 

    super 
end 

应该让你开始那。还有更高级的构造,比如使用lambda等。请记住,你应该写一些彻底的单元测试,以确保你没有任何意想不到的后果。您可能必须在排除列表中包含更多属性名称。

编辑:(读|写)_attributes - >(读|写)_attribute

+0

我认为(读|写)_attribute被AR内部使用。覆盖访问器很常见,所以我认为这更安全。我有兴趣知道它是否有效。 – balu 2010-11-03 14:10:07

+0

它是唯一一个负责管理属性的所有路径的机制。即当您执行@post = Post.new(params [:post])时,直接编辑该属性或执行@ post.update_attributes(params [:post])。因为这个原因,它曾经是做这种事情的方式。不确定它在新版本中是否有变化。 – 2010-11-03 16:15:17