I added a variable in config/application.rb:
config.available_account_types = %w(SystemAccount CashAccount DemandAccount LiabilityAccount CreditCardAccount)
And generated some scopes in model account.rb:
for t in Mypurse::Application.config.available_account_types
scope t.underscore.pluralize.to_sym, -> {where(type: t)}
end
But when I try all of them, Account.system_accounts, Account.cash_accounts, etc, I got this sql for every account type:
where type = 'CreditCardAccount'
That is, all of the generated scope are pointed to the {where(type: 'CreditCardACcount')}
I don't know why.
here is the source file: 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
I think this is caused because a scope is given a Proc
which is only executed when called, and so t
will always be the last element of the loop.
A solution is to define methods instead of scopes (which work exactly the same) :
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
But since this does not declare a proc, this should work as expected. Also the for .. in
is rarely used in ruby, I personally prefer to use the more idiomatic .each
(but of course you are free to use whatever you want, programmer happiness is key in ruby :) :)
Now as an aside, while meta-programming is really cool, you should really ask yourself if just listing the scopes is not way more readable. I understand: meta-programming is more DRY, but personally, in most cases where I did this, I reverted to the explicit definitions because of readability.
I am not sure why you have defined 'config.available_account_types', as this is business logic. this should belong to Account
modal. so I would do something like this
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
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.