Rails模型:名称--名字,姓氏

7

我是一个新手程序员,正在开发一个使用Rails 3框架的应用,该应用有一个名为"Profile"的用户模型。

在"Profile"模型中,我希望添加一个"name"字段,并且希望可以通过简单的语法访问其逻辑变量,例如:

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

这可行吗,还是我需要在这个模型中坚持使用“first_name”和“last_name”作为我的字段?
4个回答

16

这是可能的,但我不建议这样做。

如果我是你,我会坚持使用first_namelast_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

好的,建议已记录。为了我学习 Ruby,您介意展示一下“可能但不推荐”的方法是如何工作的吗? - Andrew
7
同意。我们花了近六个月的时间将一个名字拆分成多个字段,因为一些蠢货使用单个字段设计了该数据库。更糟糕的是,我们的客服代表也会将公司名称放入该字段中,因为没有专门的商业名称字段!我希望知道是谁设计了那个数据库,这样我就可以用报纸打他们的鼻子,说:“不行!糟糕的程序员!糟糕的!” - Mike Bethany
很棒,感谢大家提供的所有反馈和想法。我会坚持使用first_name和last_name,并使用fullname方法来给我所需的选项 :) - Andrew

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 页面中所述,您必须分配聚合器的新实例:您不能仅替换聚合器中的值。聚合器类就像简单的字符串或数字一样作为值。
我昨天也发送了一个非常相似的答案的响应:如何最好地将地址与Rails中的多个模型关联?

3
作为Capt. Tokyo所说,这是一个可怕的想法,但以下是如何实现它的方法:
rails g model User full_name:hash

然后,您可以像这样在其中存储数据:
user = User.new
user.full_name = {:first => "Forrest", :last => "Gump"}

现在你的问题开始了。
要搜索该字段,需要同时输入名字和姓氏,不能进行部分搜索,例如搜索所有姓相同的人。最糟糕的是,你可以将任何内容存储在该字段中!因此,想象一下另一个程序员误拼其中一个字段名称,那么在接下来的一周里,就会将{:fist => "Name", :last => "Last"}插入数据库中!不要啊!
如果使用正确的字段名称,您可以这样做:
user = User.new(:first_name => "First", :last_name => "Last")

易于阅读,无需哈希。现在您知道如何以错误的方式执行它,请以正确的方式执行它。:)


我会忘记如何做这个。我甚至不知道这是可能的。 - Jason Noble

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所说的。您不会错过中间名字。 此方法假设没有输入中文、日文名字。因为这些名字通常在名和姓之间不包含空格。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接