Ruby on Rails:从虚拟属性中组合模型的属性

时间:2010-07-26 19:27:49

标签: ruby-on-rails ruby-on-rails-3

我有模型Person的名称属性。

我想在字段中使用html-form: first_name 姓氏

<%= f.text_field first_name%>
<%= f.text_field surname%>

我想将这些虚拟属性组合成模型属性名称

最好的方法是什么?

我尝试使用composed_of,但失败了......

class Person < ActiveRecord::Base
  composed_of :name, :class_name => 'Name', :mapping => %w(name output_name)
end

class Name
  attr_reader :output_name
  def initialize(first_name, surname)
    @output_name = first_name + surname
  end
end

@person.attributes= {"name(1s)" => 'Alex', "name(2s)" => 'Bolduin' }
@person.name.should == 'Alex Bolduin'

expected: "Alex Bolduin",
got: #<Name:0x000000049d4c08 @output_name="Alex Bolduin"> (using ==)

我使用Ruby on Rails 3,但我认为Rails 3和Rails 2.3的解决方案类似

1 个答案:

答案 0 :(得分:7)

你应该能够在模型中做一个伪装列做这样的事情:

class Person < ActiveRecord::Base
    def name
      "#{self.first_name} #{self.surname}"
    end

    def name=(fullname)
      first,last = fullname.split(' ')  # or some smarter way to split
      self.first_name = first
      self.surname = last
    end
end

应该可以像访问任何其他列一样访问它,当您尝试设置name时,它只会调用first_namesurname的setter方法。


如果你想做相反的事情,你仍然可以使用相同的技巧:

class Person < ActiveRecord::Base
    def first_name
      name.split(' ')[0]
    end

    def surname
      name.split(' ')[1]
    end

    def first_name=(first)
      name = [first, name.split(' ')[1]].join(' ')
    end

    def surname=(sname)
      name = [name.split(' ')[0], sname].join(' ')
    end

end

唯一可能不好的是每次读取时字符串操作发生一次,每次写入发生两次。您也可以通过在@person.save

之前添加类似这样的内容来创建/更新控制器中的内容
@person.name = [first_name, surname].join(' ')