rails scope无法生成正确的sql

时间:2014-07-01 08:44:22

标签: ruby-on-rails ruby ruby-on-rails-4

我在config / application.rb中添加了一个变量:

config.available_account_types = %w(SystemAccount CashAccount DemandAccount LiabilityAccount CreditCardAccount)

并在模型account.rb中生成了一些范围:

for t in Mypurse::Application.config.available_account_types
  scope t.underscore.pluralize.to_sym, -> {where(type: t)}
end

但是当我尝试所有这些,Account.system_accounts,Account.cash_accounts等时,我为每种帐户类型都获得了这个sql:

where type = 'CreditCardAccount'

也就是说,所有生成的范围都指向{where(type: 'CreditCardACcount')}

我不知道为什么。

这是源文件: https://github.com/chylli/mypurse/blob/add_cash_demand_liability_credit_card/config/application.rb

https://github.com/chylli/mypurse/blob/add_cash_demand_liability_credit_card/app/models/account.rb

2 个答案:

答案 0 :(得分:1)

我认为这是因为范围被赋予Proc只会在被调用时执行,因此t将始终是循环的最后一个元素。

解决方案是定义方法而不是范围(完全相同):

MyPurs::Application.config.available_account_types.each do |account_type| 
  define_singleton_method(account_type.underscore.pluralize.to_sym) do 
    where(type: "#{account_type}")
  end
end

但由于这不会声明proc,因此应该按预期工作。 此外for .. in很少用于红宝石,我个人更喜欢使用更惯用的.each(但当然你可以自由使用你想要的任何东西,程序员的幸福是红宝石的关键:) :) / p>

现在除此之外,虽然元编程真的很酷,但你应该问自己是否只是列出范围更具可读性。我理解:元编程更干,但就个人而言,在我这样做的大多数情况下,由于可读性,我恢复了明确的定义。

答案 1 :(得分:0)

我不确定您为何定义了' config.available_account_types',因为这是业务逻辑。这应该属于Account模态。所以我会做这样的事情

class Account < ActiveRecord::Base
  ACCOUNT_TYPES = %w(SystemAccount CashAccount DemandAccount LiabilityAccount CreditCardAccount)
  ACCOUNT_TYPES.each do |acccount_type|
    define_singleton_method(account_type.underscore.pluralize.to_sym) do 
    where(type: "#{account_type}")
  end
end
end