From: Josh Cheek Date: 2010-09-30T03:24:59+09:00 Subject: Re: ActiveRecord Mixing Conditions + Better Way to Write This --001485f5cdf818a6bf04916a141c Content-Type: text/plain; charset=ISO-8859-1 On Wed, Sep 29, 2010 at 4:25 AM, Ken Ghosh wrote: > Is There A better Way to Write this > > I have A Condition which previous Look Very clean and easy to understand > like > > Account.first.websites.last.users.find(:all,:conditions => {:country => > "XYZ",:status => "Single",:admin => nil) > > Now the big problem is that user with admin = false is not picked up > > i.e i want all the users from a specific country,having status as > "Single" and admin is either "nil"(Null in database) or "false" > > I manage to get desired code but doesn't seem to be happy with clarity > of it > > Account.first.websites.last.users.find(:all,:conditions => ["country = ? > AND status = ? AND admin IS NULL OR admin = ?","XYZ","Single","false"]) > > Any Help would be appreciated > > thanks > -- > Posted via http://www.ruby-forum.com/. > > Hi, this is a Ruby list, so it would be best to ask questions like this on a Rails list (looks like you're posting from ruby-forum.com, you can access the Rails list from there too http://www.ruby-forum.com/forum/3) At http://apidock.com/rails/ActiveRecord/Base/find/class they suggest doing Project.all (:conditions => "archived IS NULL OR archived = 'f'") Which is pretty similar to what you're trying to do, but its biggest shortcoming is that it doesn't play well with other conditions. At one time I swore you could chain these together, but now they seem to return an Array instead of a lazy object (maybe I was thinking of DataMapper?) Anyway, to get around that issue, you can make it a named scope like this class User < ActiveRecord::Base named_scope :not_admin , lambda {{ :conditions => "admin IS NULL OR admin = 'f'" }} end This creates a method User.not_admin that will start building a query (and execute it if you call just like this) you can then append to that query your other conditions. The lambda is just like a do ... end block, except that it returns a reference to the object it creates, you can think of it exactly like a do end block, but you need to use curly braces on it because of how blocks bind of objects. So the first curly braces are for the block, the second are for the hash table we are returning. This then lets you make queries like so: User.not_admin User.not_admin.all( :conditions => { :country =>"XYZ" , :status => "Single" } ) As an alternative, you might set admin to be false by default (your migration would look like t.boolean :admin , :default => false ), and then validate that it is either true or false (in your class add validates_inclusion_of :admin, :in => [true, false]) Then you don't have to deal with having two kinds of falses. Note that this will prevent the record from saving if it gets set to nil (it will default to false, though, so this can only happen if something explicitly sets it to nil). --001485f5cdf818a6bf04916a141c--