2016-07-14 3 views
1

新しいオブジェクトが存在しない場合は作成します。または、データベースに既に存在する場合は、その電子メールを更新してください。 CSVファイルからデータをインポートします。テーブル内にオブジェクトを作成または更新する

私はfind_or_create_byメソッドを使用しようとしましたが、すでにオブジェクトが存在するときにデータベース内のオブジェクトを複製しました。単に更新するだけではありません。

Person.rb

class Person < ActiveRecord::Base 
    validates :email, uniqueness: true 
    require 'csv' 

    def self.import_data 
    filename = File.join Rails.root, '/vendor/people.csv' 

    CSV.foreach(filename, headers: true, col_sep: ',') do |row| 
     firstname, lastname, home_phone_number, mobile_phone_number, email, address = row 
     Person.find_or_create_by(firstname: row['firstname'], lastname: row['lastname'], home_phone_number: row['home_phone_number'], mobile_phone_number: row['mobile_phone_number'], email: row['email'], address: row['address']) 
    end 
    end 
end 

あなたは間違って何をやっていたこの

Person.find_or_create_by(email: row['email']) do |person| 
    person.update_attributes(firstname: row['firstname'], lastname: row['lastname'], home_phone_number: row['home_phone_number'], mobile_phone_number: row['mobile_phone_number'], address: row['address']) 
end 

を行う必要がありschema.rb

create_table "people", force: :cascade do |t| 
t.string "email" 
t.string "home_phone_number" 
t.string "mobile_phone_number" 
t.string "firstname" 
t.string "lastname" 
t.string "address" 
t.datetime "created_at",   null: false 
t.datetime "updated_at",   null: false 
end 

答えて

2

これが解決策です:

person = Person.find_or_create_by(firstname: row["firstname"]) 
person.update_attributes({firstname: row['firstname'], lastname: row['lastname'], home_phone_number: row['home_phone_number'], mobile_phone_number: row['mobile_phone_number'], address: row['address'], email: row['email']}) 

このソリューションは、あなたが私に提案したものを仕事とされていない理由を私は説明できません。 あなたの助けを借りて@sohail_khalilと@abhilashに感謝!

1

あなたが複数の列にfind_or_create_by適用されます。それを1つだけに適用します。

私はこれがあなたを助け、あなたの問題を解決することを望みます。

+0

私はまた、あなたの方法を試してみましたが、私は同じエラーを取得します。 \t 電子メールは変更可能な属性であるため、firstnameとlastnameで 'find_or_create'メソッドを作成しました。しかし、ファーストネームとラストネームが既に存在するので、電子メールを更新するためにループに入ることはありません。ただし、オブジェクトが存在せず、作成されている場合は正常に動作します。 – Orsay

+0

firstnameとlastnameには検証がありません。あなたはファーストネームとラストネームで正確なレコードをどのように取得するのですか?あなたは正確なレコードを取得し、電子メールを更新する他の独自のフィールドを見つけます。唯一の電子メールはユニークな属性です。 –

+0

申し訳ありませんが、わからないことがあります。電子メールフィールドは、ユーザーによって更新される唯一のフィールドです。だから、電子メールで 'find_or_create'を実行すると、それは新しい電子メールであるため、対応するオブジェクトを見つけることができないので、新しいオブジェクトを作成します。そしてfirstnameで 'find_or_create'を実行した場合、firstnameは既に存在し、ループには入っていないので更新しません...私は少し失われてしまいました! – Orsay

1

@sohailに何が追加されたかを説明します。複数のパラメータを使用してレコードを見つけて更新または作成するには、

Person.where(<conditions>).first_or_initialize do |person| 
    <initialize code> 
end 

これが適切です。

+0

電子メールは変更可能な属性なので、 'firstname'と' lastname'に 'where'メソッドを作成しました。 しかし、ファーストネームとラストネームはすでに存在しているので、電子メールを更新するためにループに入りません。 ただし、オブジェクトが存在せず、作成されている場合は正常に動作します。 – Orsay

0

あなたがRailsの3.2以上を持っている場合は、交換してください:

Person.find_or_create_by(firstname: row['firstname'], lastname: row['lastname'], home_phone_number: row['home_phone_number'], mobile_phone_number: row['mobile_phone_number'], email: row['email'], address: row['address']) 

をして:

Person.where(:email => row['email']).first_or_create(:firstname => row['firstname'], :lastname => row['lastname'], :home_phone_number => row['home_phone_number'], :mobile_phone_number => row['mobile_phone_number'], :email => row['email'], :address => row['address']) 
関連する問題