如何合并rails表中的列?

时间:2013-03-08 05:24:34

标签: ruby-on-rails merge

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

5 个答案:

答案 0 :(得分: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

答案 1 :(得分:3)

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

  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

答案 2 :(得分:0)

创建迁移以添加新字段:

rails g migration AddNameToTableName name

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

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

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

答案 3 :(得分: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的情况下插入杂散空格,并且还可以更有效地将全名拆分为名字和姓氏;具体来说,通过拆分名称中的 last 空格,因为“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"

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

答案 4 :(得分: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方法将考虑具有多个空格的名称。