I have a class similar to the following:
class FruitKinds < ActiveRecord::Base
Apple = FruitKinds.find(:all).find { |fk|
fk.fruit_name == :apple.to_s
}
# ... other fruits
# no methods
end
Apple and other specific Fruits are commonly used as default values elsewhere in my application, so I want a handy means to refer to them in an enumerable, static-ish way.
However, there's a problem. There is a database migration to create the FruitKinds
table and populate it with the special Fruits
like Apple
. When the database migration runs to initialize FruitKinds, rake
fails to start because it first loads FruitKinds
, which then makes a call to the database, which of course fails since the FruitKinds table is not yet there.
The workaround is to comment out the FruitKinds::* fields while the migration runs, but that is awful and hacky. What's the best way to do this?
That's a pretty common gotcha, to the point that I now consider any database access at the class definition level an antipattern. The alternative is to make it a lazy property. The simplest way to do this is simply to make it a class-level method instead of a constant. Note that you can have capitalised methods in Ruby, so you can make it look like a constant if you want:
class FruitKinds < ActiveRecord::Base
def self.Apple
@apple ||= FruitKinds.find(:all).find { |fk|
fk.fruit_name == :apple.to_s
}
end
# ... other fruits
# no methods
end
Or if you want to get fancy you can use const_missing
to dynamically create the constant the first time it is accessed.
As a side note, that's about the most inefficient way possible to find a record by name ;-)
As Avdi mentioned, you'll want to avoid interacting with the database when the class is loaded. If you're wanting to cache database records in local memory, I recommend using the Memoization feature added in Rails 2.2. See my post here for details.
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.