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

发布于 2024-11-26 20:19:24 字数 626 浏览 0 评论 0原文

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

I am developing a Rails web application and am confused about how to utilize the lookup table values in my models. Here is an example model from my app:

table name: donations

id
amount
note
user_id
appeal_id
donation_status_id
donation_type_id
is_anonymous
created_at
updated_at

The fields *donation_status_id* and *donation_type_id* refer to lookup tables. So in my code I have several random places where I make calls like this:

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

To my inexperienced eyes, a one-off query to the DonationStatus table seems incredibly wasteful here, but I don't see any other good way to do it. The first idea I thought of was to read all my lookup tables into a hash at application startup and then just query against that when I need to.
But is there a better way to do what I am trying to do? Should I not worry about queries like this?
Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

白鸥掠海 2024-12-03 20:19:24

由于您有两个模型,因此在构建模型时应使用 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 已经为您解决了这个问题应该怎样做

Since you have two models, you should use ActiveRecord Model Associations when building the models.

class Donation
  has_one :donation_status
end

class DonationStatus
 belongs_to :donation
end

Then when you do

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

For more information, you may want to read up how rails is doing the model associations http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html Don't worry about performance, rails has taken care of that for you if you follow how the way it should be done

情深如许 2024-12-03 20:19:24

把它放在一个常数中怎么样?例如,像这样:

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"

How about putting it in a constant? For example, something like this:

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

This way, DonationStatus.find_by_name("pending").id gets executed exactly one. I'm assuming, of course, that this table won't change often.

BTW, I learned this trick in Dan Chak's book, Enterprise Rails.

EDIT: I forgot to mention: in practice, I declare constants like this:

COMPLETED_DONATION_ID = DonationStatus.find_by_name("completed").id rescue "Can't find 'completed' in donation_statuses table"
岁月流歌 2024-12-03 20:19:24

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

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

然后只需执行my_donation.completed?。如果第二次调用,Rails 将查找缓存而不是访问数据库。

如果需要,您可以添加 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 笔捐款,并且每笔捐款的 grant_status 都是 1,那么它将直接进入缓存。 memcached 速度相当快并且很受欢迎。

What you could do is add this method to Donation:

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

And then just do my_donation.completed?. If this is called a second time, Rails will look to cache instead of going to the DB.

You could add memcached if you want, or use Rails' caching further, and do:

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

What that will do is make a hash key called (for example) "status_1_complete" and if it's not defined the first time, will evaluate the block and set the value. Otherwise, it will just return the value. That way, if you had 1,000,000,000 donations and each of them had donation_status 1, it would go directly to the cache. memcached is quite fast and popular.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文