我对rails非常陌生,使用适用于用户的Profile模型的Rails 3应用程序。
在配置文件模型中,我希望有一个“名称”条目,我希望能够使用简单的语法访问它的逻辑变体:
user.profile.name = "John Doe"
user.profile.name.first = "John"
user.profile.name.last = "Doe"
这可能,或者我是否需要坚持使用“first_name”和“last_name”作为此模型中的字段?
答案 0 :(得分:16)
这是可能的,但我不推荐它。
如果我是你并且添加方法first_name
,我会坚持last_name
和fullname
:
def fullname
"#{first_name} #{last_name}"
end
如果确实需要 user.profile.name
,您可以创建一个Name
模型,如下所示:
class Name < ActiveRecord::Base
belongs_to :profile
def to_s
"#{first} #{last}"
end
end
这允许你这样做:
user.profile.name.to_s # John Doe
user.profile.name.first # John
user.profile.name.last # Doe
答案 1 :(得分:8)
其他答案都是正确的,因为他们忽略了#composed_of聚合器:
class Name
attr_reader :first, :last
def initialize(first_name, last_name)
@first, @last = first_name, last_name
end
def full_name
[@first, @last].reject(&:blank?).join(" ")
end
def to_s
full_name
end
end
class Profile < ActiveRecord::Base
composed_of :name, :mapping => %w(first_name last_name)
end
# Rails console prompt
> profile = Profile.new(:name => Name.new("Francois", "Beausoleil"))
> profile.save!
> profile = Profile.find_by_first_name("Francois")
> profile.name.first
"Francois"
如#composed_of页面所述,您必须分配聚合器的新实例:您不能只替换聚合器中的值。聚合器类充当值,就像一个简单的字符串或数字。
昨天我也发了一个回复,回答非常相似:How best to associate an Address to multiple models in rails?
答案 2 :(得分:3)
正如东京上尉所说,这是一个可怕的想法但是你会怎么做:
rails g model User full_name:hash
然后你会像这样存储数据:
user = User.new
user.full_name = {:first => "Forrest", :last => "Gump"}
现在你的问题开始了。
要搜索该字段,需要同时使用这两个名称,并且您无法进行部分搜索,例如搜索具有相同姓氏的所有人。最糟糕的是,你可以在现场存储任何东西!所以想象一下,另一个程序员错误地输入了一个字段名称,所以一周你就有{:fist =&gt; “姓名”,:last =&gt; “Last”}被插入数据库! Noooooooooooooooooo!
如果您使用了正确的字段名称,则可以执行此操作:
user = User.new(:first_name => "First", :last_name => "Last")
易于阅读,无需哈希。现在您知道如何以错误的方式做到这一点,以正确的方式做到这一点。 :)
答案 3 :(得分:2)
仅供参考(假设您有一个字段fullname
。即您的profile.name = "John Doe"
)
class Profile
def name
@splited_name ||= fullname.split # @splited_name would cache the result so that no need to split the fullname every time
end
end
现在,您可以这样做:
user.profile.fullname # "John Doe"
user.profile.name.first # "John"
user.profile.name.last # "Doe"
请注意以下情况:
user.profile.fullname = "John Ronald Doe"
user.profile.name.first # "John"
user.profile.name.second # "Ronald"
user.profile.name.last # "Doe"
我同意captaintokyo。你不会错过中间名。 此方法也假设没有输入中文,日文名称。这是因为这些名称通常在名字和姓氏之间不包含空格。