5

我有一个 Rails 用户表,其中包含 first_name 和 last_name 列等。我如何将这两者合并在一起?或者我如何创建一个名为 name 的新列并从这两列添加数据?基本上我需要一个名为 name 的列,它是 first_name 和 last_name 的串联。

4

5 回答 5

6

正如 Richard Brown 所回答的那样,如果要将连接的字符串保存到数据库中,则应该创建一个迁移。

rails g migration add_fullname_to_users fullname

然后在生成的迁移中运行 sql 以更新所有记录

# mysql
User.update_all('fullname = CONCAT(first_name, " ", last_name)')

# postgre
User.update_all("fullname = (first_name || ' ' || last_name)")

但我建议您保留当前设置并在模型中创建一个名为 fullname 的方法

# user.rb
def fullname
  "{first_name} #{last_name}"
end

哪个更好,因为您可以访问first_namelast_name

于 2013-03-08T05:42:25.777 回答
4

如果要确保可以回滚,可以在迁移文件中执行类似的操作。

  def up
    add_column :your_table, :name, :string 

    YourClass.all.each do |person|
      person.update_attributes! :name => person.first_name + " " + person.last_name
    end

    remove_column :your_table, :first_name
    remove_column :your_table, :last_name  
  end

以及您的回滚方法:

  def down
    add_column :your_table, :first_name, :string
    add_column :your_table, :last_name, :string

    YourClass.all.each do |person|
      person.update_attributes! :first_name => person.name.match(/\w+/)[0]
      person.update_attributes! :last_name => person.name.match(/\w+/)[1]
    end

    remove_column :your_table, :name
  end
于 2013-05-12T06:02:24.227 回答
0

创建迁移以添加新字段:

rails g migration AddNameToTableName name

您可以编写一个 rake 任务来执行连接。

TableName.all.each do { |row| row.update_attributes(name: "#{row.first_name} #{row.last_name}") }

您可以从 rails 控制台执行该操作,但我喜欢可重复的数据库更新,因此我更喜欢 rake 任务。

于 2013-03-08T05:36:54.203 回答
0

上面示例中的 \w 正则表达式匹配器和与空格连接对我来说是有问题的,尽管我遇到了相反的问题,将名字分成名字和姓氏。相反,考虑使用我最终得到的东西。首先备份您的数据库,并在开发中进行测试!

  def up # Split name into first and last
    add_column :people, :first_name, :string
    add_column :people, :last_name, :string
    Person.all.each do |person|
      person.update_column(:first_name, person.attributes["name"].rpartition(" ").first)
      person.update_column(:last_name, person.attributes["name"].rpartition(" ").last)
      person.save(:validate => false)
    end
    remove_column :people, :name
  end

  def down # Merge first and last into name
    add_column :people, :name, :string
    Person.all.each do |person|
      person.update_column(:name, [person.attributes["first_name"].to_s, person.attributes["last_name"].to_s].reject(&:blank?).join(" "))
      person.save(:validate => false)
    end
    remove_column :people, :first_name
    remove_column :people, :last_name
  end

这样可以避免在其中一个名称为 nil 的情况下插入杂散空格,并且还可以更有效地将全名拆分为名字和姓氏;具体来说,通过拆分名称中的最后一个空格,因为“First Middle”“Last”比“First”“Middle Last”更像是人类兼容的拆分。查看示例:

# Before split
> puts p.name.inspect
"Prince"
"Test User"
"Jean Luc Picard"

# After split    
> puts p.first_name.inspect + " " + p.last_name.inspect
"" "Prince"
"Test" "User"
"Jean Luc" "Picard"

我的主要抱怨是“Prince”可能应该是名字而不是姓氏,但是根据您的数据库限制,它可能仍然需要进入 last_name 字段。

于 2013-09-20T23:54:59.297 回答
0

在我的带有用户模型的 rails 4 应用程序中,我生成了我的迁移文件

rails g migration RemoveFirstLastNameColumnsFromUser

然后我放入

class RemoveFirstLastNameColumnsFromUser < ActiveRecord::Migration
  def up
    add_column :users, :name, :string

    User.all.each do |u|
      u.update! name: "#{u.first_name} #{u.last_name}"
    end

    remove_column :users, :first_name
    remove_column :users, :last_name
  end

  def down
    add_column :users, :first_name, :string
    add_column :users, :last_name, :string

    User.all.each do |u|
      n = u.name
      u.update! last_name: n.slice!(/\w+\z/)
      u.update! first_name: n.strip
    end

    remove_column :users, :name, :string
  end
end

#down方法将解释具有多个空格的名称。

于 2016-08-12T04:36:03.480 回答