4

Rails Web アプリケーションを開発していますが、モデルでルックアップ テーブルの値を使用する方法について混乱しています。これが私のアプリのモデルの例です:

table name: donations

id
amount
note
user_id
appeal_id
donation_status_id
donation_type_id
is_anonymous
created_at
updated_at

フィールド *donation_status_id* および *donation_type_id* はルックアップ テーブルを参照します。したがって、私のコードには、次のような呼び出しを行うランダムな場所がいくつかあります。

my_donation = Donation.find(params[:id])
if my_donation.donation_status_id == DonationStatus.find_by_name("completed").id
#do something
end

経験の浅い私の目には、DonationStatus テーブルへの 1 回限りのクエリは、ここでは信じられないほど無駄に思えますが、それを行うための他の良い方法は見当たりません。私が最初に思いついたアイデアは、アプリケーションの起動時にすべてのルックアップ テーブルをハッシュに読み込み、必要なときにそれに対してクエリを実行するというものでした。しかし、私がやろうとしていることを行うためのより良い方法はありますか? このようなクエリについて心配する必要はありませんか? ありがとう!

4

3 に答える 3

2

定数に入れてみませんか?たとえば、次のようなものです。

class DonationStatus < ActiveRecord::Base
  COMPLETED_DONATION_ID = DonationStatus.find_by_name("completed").id
  PENDING_DONATION_ID   = DonationStatus.find_by_name("pending").id
  # ...
end

class DonationsController < ApplicationController
  def some_action
    my_donation = Donation.find(params[:id])
    if my_donation.donation_status_id == DonationStatus::COMPLETED_DONATION_ID
    #do something
  end
end

このようにして、 DonationStatus.find_by_name("pending").id1つだけ実行されます。もちろん、このテーブルは頻繁には変更されないと思います。

ところで、私はダンチャクの本、エンタープライズレールでこのトリックを学びました。

編集:私は言及するのを忘れました:実際には、私はこのような定数を宣言します:

COMPLETED_DONATION_ID = DonationStatus.find_by_name("completed").id rescue "Can't find 'completed' in donation_statuses table"
于 2011-07-30T01:50:14.760 に答える
2

2つのモデルがあるため、モデルを構築するときにActiveRecordモデルの関連付けを使用する必要があります。

class Donation
  has_one :donation_status
end

class DonationStatus
 belongs_to :donation
end

その後、あなたがするとき

my_donation = Donation.find(params[:id])
if my_donation.donation_status.status_name == 'complete'
  #do something
end

詳細については、railsがモデルの関連付けをどのように行っているかを確認することをお勧めしますhttp://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.htmlパフォーマンスについて心配する必要はありません。あなたがそれがどのように行われるべきかに従うならばあなた

于 2011-07-30T01:54:51.983 に答える
1

あなたができることは、このメソッドをに追加することですDonation

# Donation.rb
def completed?
    self.donation_status.name == 'completed' ? true : false
end

そして、それを実行しますmy_donation.completed?。これが2回目に呼び出された場合、RailsはDBに移動する代わりに、キャッシュを探します。

必要に応じてmemcachedを追加するか、Railsのキャッシュをさらに使用して次の操作を行うことができます。

def completed?
    return Rails.cache.fetch("status_#{self.donation_status_id}_complete") do
        self.donation_status.name == 'completed' ? true : false
    end
end

これにより、(たとえば)「status_1_complete」というハッシュキーが作成され、最初に定義されていない場合は、ブロックが評価されて値が設定されます。それ以外の場合は、値を返すだけです。そうすれば、1,000,000,000の寄付があり、それぞれにdonation_status 1がある場合、それは直接キャッシュに送られます。memcachedは非常に高速で人気があります。

于 2011-07-30T01:44:12.633 に答える