Rails模型:名称 - 第一,最后

时间:2010-10-14 05:10:38

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

我对rails非常陌生,使用适用于用户的Profile模型的Rails 3应用程序。

在配置文件模型中,我希望有一个“名称”条目,我希望能够使用简单的语法访问它的逻辑变体:

user.profile.name = "John Doe"
user.profile.name.first = "John"
user.profile.name.last = "Doe"

这可能,或者我是否需要坚持使用“first_name”和“last_name”作为此模型中的字段?

4 个答案:

答案 0 :(得分:16)

这是可能的,但我不推荐它。

如果我是你并且添加方法first_name,我会坚持last_namefullname

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。你不会错过中间名。 此方法也假设没有输入中文,日文名称。这是因为这些名称通常在名字和姓氏之间不包含空格。