2017-08-29 20 views
0

私のデータベースに、ユーザーの身長と体重がすでに入力されているユーザーモデルがあるとします。ここで、既存の各ユーザーの体重と身長から計算したBMI列をユーザー表に追加します。百万人のユーザーがいる場合、これを行う最も効率的な方法は何でしょうか?Rails Active Record - 他の列の値から列を作成する

P.S

私が呼ばれたときにローカルでスクリプトを実行し、レールのルートを追加しようとしたが、それは長いにかかることがわかりました。私は複雑な方法が必要なので、レールコンソールを使うことはできないと思います。

+0

マイグレーションされたデータの計算だけでデータベースの実際の列を使用したいのですか、またはモデルの読み取り専用属性を必要としますか? –

+0

[Railsでバッチでアップデートを実行するにはどうすればいいですか?](https://stackoverflow.com/questions/23252811/how-can-i-run-updates-in-batches-in-rails) – Ilya

+0

@Ilya間違いなく、バッチで更新を実行する方法について説明しています。他の列の値に基づいて列を作成する方法を知りたかったのです。 –

答えて

0

まずあなたが列を追加するには、移行が必要ですが、デフォルトを設定していない(あなたは、レコードのトンを持っている場合、デフォルトの設定は、長い時間がかかることが)

ADD_COLUMN:some_attribute、:文字列

列がある場合は、それをバックフィルする必要があります。

find_eachを使用してください。 1,000,000人のユーザーは、何をしていても処理に時間がかかるでしょう。 find_eachを使用すると、一度に1,000個しかインスタンス化されません。

User.find_each do |user| 
    num = user.height * user.width # or whatever you need to figure out here 
    user.update_attributes(some_attribute: num) 
end 

あなたはfind_eachオフを蹴るエンドポイントを設定することができ、本当に、あなたはコンソール経由でそれを実行している最高のオフです。私はscreenを使用します。これは、長時間実行されるプロセスになる可能性があるためです。

マイグレーションファイルにそのファイルを入れることはできますが、マイグレーション時にデータを操作するのがベストプラクティスであるかどうかについてはさまざまな意見があります。あなたがupdate_all使用することができます

1

、データベースを通じて、このアップデートでは、各既存のユーザーにBMIを追加したい場合はどこので、おそらく最良の方法は、rake taskを作成することですすべてのレコードを通じて api documentation for update_all

User.update_all('bmi = height * weight') 
-1

をループしませんその列を更新するロジックが追加されます。

namespace :user do 
    task :bmi_calculator => 'environment' do 
    User.find_each do |user| 
     bmi = user.height/user.weight (I'm not sure about computation) 
     user.update_attribute(bmi: bmi) 
    end 
    end 
end 

いつでも好きなときに、あなたは、このタスク(rake user:bmi_calculator)を実行することができます

あなたはすでに、あなたがrakeタスクを必要とし、整数であるユーザモデルに新しい列bmiを追加したと!また、私のアドバイスは、トラフィックがそれほど大きくない真夜中後に自動的に実行するために、この種のタスクにcronジョブを使用することです。

乾杯

関連する問題