我想将我的数据库查找表映射到哈希,好主意?

时间:2011-07-30 01:23:51

标签: ruby-on-rails database-design lookup-tables

我正在开发一个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表的一次性查询在这里看起来非常浪费,但我没有看到任何其他好方法。我想到的第一个想法是在应用程序启动时将所有查找表读入哈希,然后在需要时查询。 但有没有更好的方法来做我想做的事情?我不应该担心这样的查询吗? 谢谢!

3 个答案:

答案 0 :(得分: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").id只执行一次。当然,我假设这张桌子不会经常改变。

顺便说一句,我在Dan Chak的书Enterprise Rails中学到了这个技巧。

编辑:我忘了提及:在实践中,我声明了这样的常量:

COMPLETED_DONATION_ID = DonationStatus.find_by_name("completed").id rescue "Can't find 'completed' in donation_statuses table"

答案 1 :(得分: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不要担心性能,如果您按照应该如何完成的方式,rails已经为您解决了这个问题

答案 2 :(得分:1)

您可以做的是将此方法添加到Donation

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

然后只做my_donation.completed?。如果这是第二次调用,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非常快速和受欢迎。