In an app I''m working on, I want to have a filter in which you can specify certain attributes and click "filter" to activate an AJAX request and return a list of, say, machines that match with those attributes. No I''m not sure how to build the controller. If I would specify all the attributes, I would simply do: def filter @machines = Machine.find(:all, :conditions => { :attr_1 => params [:attr_1], :attr_2 ... } end But how would I do this if only some of the attributes are specified and the others are nil? Would I have to create @machines including all machines and have Rails do the rest of the work or is there a way to get find to do what I want?
Off the top of my head: class Machine < ActiveRecord::Base # Define a list of acceptable params for filtering FILTERS = [:name, :code] # Finds records by params def self.filter_by_params(params) conditions = params.select { |key,val| FILTERS.include?(key.to_sym) and val } all(:conditions => conditions) end end class MachinesController < ApplicationController def index # Where params is { :filter => { :name => ''Pat'', :code => ''123'' }} @machines = Machine.filter_by_params(params[:filter]) end end On Thu, Jul 2, 2009 at 5:42 PM, jhaagmans <jaap.haagmans-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> > In an app I''m working on, I want to have a filter in which you can > specify certain attributes and click "filter" to activate an AJAX > request and return a list of, say, machines that match with those > attributes. > > No I''m not sure how to build the controller. > > If I would specify all the attributes, I would simply do: > > def filter > @machines = Machine.find(:all, :conditions => { :attr_1 => params > [:attr_1], :attr_2 ... } > end > > But how would I do this if only some of the attributes are specified > and the others are nil? Would I have to create @machines including all > machines and have Rails do the rest of the work or is there a way to > get find to do what I want? > > >--~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
Could you explain why the first part would go entirely into the Machine model? On 2 jul, 23:56, Pat Nakajima <patnakaj...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> Off the top of my head: > class Machine < ActiveRecord::Base > # Define a list of acceptable params for filtering > FILTERS = [:name, :code] > > # Finds records by params > def self.filter_by_params(params) > conditions = params.select { |key,val| FILTERS.include?(key.to_sym) > and val } > all(:conditions => conditions) > end > end > > class MachinesController < ApplicationController > def index > # Where params is { :filter => { :name => ''Pat'', :code => ''123'' }} > @machines = Machine.filter_by_params(params[:filter]) > end > end > > On Thu, Jul 2, 2009 at 5:42 PM, jhaagmans <jaap.haagm...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > > > In an app I''m working on, I want to have a filter in which you can > > specify certain attributes and click "filter" to activate an AJAX > > request and return a list of, say, machines that match with those > > attributes. > > > No I''m not sure how to build the controller. > > > If I would specify all the attributes, I would simply do: > > > def filter > > @machines = Machine.find(:all, :conditions => { :attr_1 => params > > [:attr_1], :attr_2 ... } > > end > > > But how would I do this if only some of the attributes are specified > > and the others are nil? Would I have to create @machines including all > > machines and have Rails do the rest of the work or is there a way to > > get find to do what I want?
> > Could you explain why the first part would go entirely into theMachine model? Because it''s better to encapsulate model logic in the models (and custom finders are model logic). Controllers should only be responsible for receiving a request, calling the appropriate model methods, then returning a response. - Pat --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
You could try building up a chain of scopes - see this post: http://groups.google.com/group/rubyonrails-talk/browse_thread/thread/a7df6a8b9628bb4b/d6b738f83084ec91?lnk=gst&q=scoped#d6b738f83084ec91 As noted there, you can avoid cluttering up your model by using ''scoped'' to create anonymous scopes. So your example would look like: # in the controller action proxy = Machine [:attr1, :attr2, :attr3].each do { |k| proxy = proxy.scoped(:conditions => Hash[k, params[k]]) unless params [k].blank? } @machines = proxy.find(:all) That last find can also be a paginate, have limits, sorts, etc. --Matt Jones On Jul 2, 5:42 pm, jhaagmans <jaap.haagm...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> In an app I''m working on, I want to have a filter in which you can > specify certain attributes and click "filter" to activate an AJAX > request and return a list of, say, machines that match with those > attributes. > > No I''m not sure how to build the controller. > > If I would specify all the attributes, I would simply do: > > def filter > @machines = Machine.find(:all, :conditions => { :attr_1 => params > [:attr_1], :attr_2 ... } > end > > But how would I do this if only some of the attributes are specified > and the others are nil? Would I have to create @machines including all > machines and have Rails do the rest of the work or is there a way to > get find to do what I want?
That works, though it''s definitely a good idea to sanitize which params can be used in such a manner. Otherwise, someone could send params like { :destroy_all => true } or something, and then there goes your database. Pat On Sat, Jul 4, 2009 at 1:07 PM, Matt Jones <al2o3cr-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> > You could try building up a chain of scopes - see this post: > > > http://groups.google.com/group/rubyonrails-talk/browse_thread/thread/a7df6a8b9628bb4b/d6b738f83084ec91?lnk=gst&q=scoped#d6b738f83084ec91 > > As noted there, you can avoid cluttering up your model by using > ''scoped'' to create anonymous scopes. > > So your example would look like: > > # in the controller action > proxy = Machine > [:attr1, :attr2, :attr3].each do { |k| > proxy = proxy.scoped(:conditions => Hash[k, params[k]]) unless params > [k].blank? > } > @machines = proxy.find(:all) > > That last find can also be a paginate, have limits, sorts, etc. > > --Matt Jones > > On Jul 2, 5:42 pm, jhaagmans <jaap.haagm...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > > In an app I''m working on, I want to have a filter in which you can > > specify certain attributes and click "filter" to activate an AJAX > > request and return a list of, say, machines that match with those > > attributes. > > > > No I''m not sure how to build the controller. > > > > If I would specify all the attributes, I would simply do: > > > > def filter > > @machines = Machine.find(:all, :conditions => { :attr_1 => params > > [:attr_1], :attr_2 ... } > > end > > > > But how would I do this if only some of the attributes are specified > > and the others are nil? Would I have to create @machines including all > > machines and have Rails do the rest of the work or is there a way to > > get find to do what I want? > > >--~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
Now that I read again, scoped won''t allow destroy_all to get through, but I still stand by my point :) On Sun, Jul 5, 2009 at 5:14 AM, Pat Nakajima <patnakajima-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> That works, though it''s definitely a good idea to sanitize which params can > be used in such a manner. Otherwise, someone could send params like { > :destroy_all => true } or something, and then there goes your database. > Pat > > > On Sat, Jul 4, 2009 at 1:07 PM, Matt Jones <al2o3cr-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > >> >> You could try building up a chain of scopes - see this post: >> >> >> http://groups.google.com/group/rubyonrails-talk/browse_thread/thread/a7df6a8b9628bb4b/d6b738f83084ec91?lnk=gst&q=scoped#d6b738f83084ec91 >> >> As noted there, you can avoid cluttering up your model by using >> ''scoped'' to create anonymous scopes. >> >> So your example would look like: >> >> # in the controller action >> proxy = Machine >> [:attr1, :attr2, :attr3].each do { |k| >> proxy = proxy.scoped(:conditions => Hash[k, params[k]]) unless params >> [k].blank? >> } >> @machines = proxy.find(:all) >> >> That last find can also be a paginate, have limits, sorts, etc. >> >> --Matt Jones >> >> On Jul 2, 5:42 pm, jhaagmans <jaap.haagm...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: >> > In an app I''m working on, I want to have a filter in which you can >> > specify certain attributes and click "filter" to activate an AJAX >> > request and return a list of, say, machines that match with those >> > attributes. >> > >> > No I''m not sure how to build the controller. >> > >> > If I would specify all the attributes, I would simply do: >> > >> > def filter >> > @machines = Machine.find(:all, :conditions => { :attr_1 => params >> > [:attr_1], :attr_2 ... } >> > end >> > >> > But how would I do this if only some of the attributes are specified >> > and the others are nil? Would I have to create @machines including all >> > machines and have Rails do the rest of the work or is there a way to >> > get find to do what I want? >> >> >> >--~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
On 3 jul, 22:43, Pat Nakajima <patnakaj...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> > Could you explain why the first part would go entirely into the > > Machine model? > > Because it''s better to encapsulate > model logic in the models (and custom finders are model logic). > Controllers should only be responsible for receiving a request, > calling the appropriate model methods, > then returning a response. > > - PatThank you, that''s very clear! I''ve decided to try and go with this solution as this actually does what I inteded to do. I just had some trouble understanding why in most examples this piece of code is put into the controller and you don''t.