Currently on save I am trying to check to see if a recorded falls into a particular 'scope'. This 'scope' really is just some saved arguments for a .where call. Also with this 'scope' I am only ever checking values of the object, not ever how it relates to other objects in the database, so querying the database will always be over kill if that makes sense.
I have only been able to come up with the below solution
begin
result = self.class.where(scope).find(self.id)
rescue
result = false
end
The issue with this is that I have to query the database even though I already have the record, and I have to run this not only before save but after save to check the values it was and the values it will be after save, because there is no way to query the database for the updated version if it hasn't been saved.
There can be a number of these checks so I would like to avoid having to do it twice, and also having to query the database that many times, even if ultimately I am just looking something up by id.
The only other solution I have been able to think of would be to have a method that some how translates the where call into a proc that return a boolean when passed an object. The only issue with that is translating it would some how have to work with the active record adapter being used, which seems like a whole project to its own. So does anyone know of some way to do this, or of a gem that would help?
PS I getting the 'scope' from cache so I can't save it as a proc because you can't put procs into the cache with Rails.
first you can improve your first solution a bit
result = self.class.where(scope).exists?(self.id)
if you don't want to check the database, why don't you just check if your object's attributes has the values of the scope? if your scope is
class.where(:attr1 => value1, :attr2 => value2, :attr3 => value3)
then you can do
result = self.attr1 == value1 and self.attr2 == value2 and self.attr3 == value3
If your scopes are simple, you probably want to avoid code duplication. My solution allows you to call model.active?
to know if an instance belongs to the scope, and Model.active
to find all records matching the scope. model.active?
doesn't involve any database queries.
consider adding this to config/initializers/scope_and_method.rb
:
require 'active_record/named_scope'
module ActiveRecord::NamedScope::ClassMethods
def scope_and_method field, *values
field = field.to_sym
values.each do |value|
named_scope value.to_sym, :conditions => {field => value}
define_method "#{value}?" do
send(field.to_sym) == value
end
end
end
end
Usage:
scope_and_method :state, 'active', 'inactive'
Works as if it was:
named_scope :active, :conditions => {:state => 'active'}
named_scope :inactive, :conditions => {:state => 'inactive'}
def active?
state == 'active'
end
def inactive?
state == 'inactive'
end
This is a solution for Rails 2.3. This needs a very small tuning for Rails 3 and 4. (named_scope
-> scope
) I will check it soon.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With