ユーザーの Rails テーブルがあり、列 first_name や last_name などがあります。これら 2 つをマージするにはどうすればよいですか? または、name という名前の新しい列を作成し、これら 2 つの列からデータを追加するにはどうすればよいですか? 基本的に、first_name と last_name を連結した name という列が必要です。
5 に答える
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_name
ですlast_name
新しいフィールドを追加する移行を作成します。
rails g migration AddNameToTableName name
結合を行うための rake タスクを作成できます。
TableName.all.each do { |row| row.update_attributes(name: "#{row.first_name} #{row.last_name}") }
これは Rails コンソールから実行できますが、私は反復可能なデータベース更新が好きなので、rake タスクを好みます。
上記の例のように \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
これにより、名前の 1 つが 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"
私の主な不満は、「王子」はおそらく姓ではなく名であるべきだということですが、データベースの制約によっては、とにかく last_name フィールドに入る必要があるかもしれません。