I have this model that holds search parameters accross pages: class Search < User attr_reader :min_age, :max_age end for a form: ... <% age_list = (0..99).collect {|x| [x,(Date.today.year-x)]} %> <%= select ''search'',''min_age'', age_list %><br> <%= select ''search'',''max_age'', age_list.reverse %><br><br> .... then in the search controller I have: class SearchController < ApplicationController def simple if params[:search] @search = Search.new(params[:search]) session[:search] = @search else @search = session[:search] end @results = User.find(:all, :conditions => [":min_age < year(birthday) < :max_age", {:min_age => min_age, :max_age => max_age}]) .... end for some reason I''m getting "NoMethodError in Search#simple undefined method `min_age='' for #<Search:0x23da2cc>" as if min_age weren''t defined... what could be causing this? thanks Oliver
Oliver, I think you''re okay up to the point where you do> {:min_age => min_age, :max_age => max_age}])Because you''re doing assignments, :min_age and :max_age need to be writable. attr_reader does not generate an assignment method of the form described in the NoMethodError message. If you''ll look closely at the method name referenced there, you''ll see the "=" appended to "min_age". Long story short -- change your "attr_reader" declaration to use "attr_writer" and your code should work as you expect. Regards, David On Nov 27, 2005, at 1:29 PM, Oliver Barnes wrote:> I have this model that holds search parameters accross pages: > > class Search < User > attr_reader :min_age, :max_age > end > > for a form: > ... > <% age_list = (0..99).collect {|x| [x,(Date.today.year-x)]} %> > <%= select ''search'',''min_age'', age_list %><br> > <%= select ''search'',''max_age'', age_list.reverse %><br><br> > .... > > then in the search controller I have: > > class SearchController < ApplicationController > > def simple > if params[:search] > @search = Search.new(params[:search]) > session[:search] = @search > else > @search = session[:search] > end > > @results = User.find(:all, > :conditions => [":min_age < year(birthday) < :max_age", > {:min_age => min_age, :max_age => max_age}]) > .... > end > > for some reason I''m getting > > "NoMethodError in Search#simple > > undefined method `min_age='' for #<Search:0x23da2cc>" > > as if min_age weren''t defined... what could be causing this? > > thanks > Oliver > _______________________________________________ > Rails mailing list > Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org > http://lists.rubyonrails.org/mailman/listinfo/rails
Oliver, After further review, I wanted to correct and clarify a couple of things. The problem is related to the the writability of your attributes, but it''s not in the line I cited. That line is just setting the values of the parameters used in the SQL query that does your find(). It''s when you call Search.new(params[:search]) that you''re getting the complaint about the undefined method. This form of new() is a shortcut for assigning values to all attributes that have corresponding parameters in the inbound request. You can still change the declaration of your attributes, but you probably want to change them (in the simplest case) to "attr_accessor", instead of "attr_reader" or "attr_writer". attr_accessor generates both read and write methods. If you change them to attr_writer, you''ll be able to write to the attributes but not read from them (the converse of the problem you''re having now). Keep in mind that there are some implications for the security of your data when you use the shortcut method for assigning attributes from request parameters. http://manuals.rubyonrails.com/export/html/8 has some good information on this topic. David On Nov 28, 2005, at 9:52 AM, David Rupp wrote:> Oliver, > > I think you''re okay up to the point where you do > >> {:min_age => min_age, :max_age => max_age}]) > > Because you''re doing assignments, :min_age and :max_age need to be > writable. attr_reader does not generate an assignment method of the > form described in the NoMethodError message. If you''ll look closely > at the method name referenced there, you''ll see the "=" appended to > "min_age". > > Long story short -- change your "attr_reader" declaration to use > "attr_writer" and your code should work as you expect. > > Regards, > David > > On Nov 27, 2005, at 1:29 PM, Oliver Barnes wrote: > >> I have this model that holds search parameters accross pages: >> >> class Search < User >> attr_reader :min_age, :max_age >> end >> >> for a form: >> ... >> <% age_list = (0..99).collect {|x| [x,(Date.today.year-x)]} %> >> <%= select ''search'',''min_age'', age_list %><br> >> <%= select ''search'',''max_age'', age_list.reverse %><br><br> >> .... >> >> then in the search controller I have: >> >> class SearchController < ApplicationController >> >> def simple >> if params[:search] >> @search = Search.new(params[:search]) >> session[:search] = @search >> else >> @search = session[:search] >> end >> >> @results = User.find(:all, >> :conditions => [":min_age < year(birthday) < :max_age", >> {:min_age => min_age, :max_age => max_age}]) >> .... >> end >> >> for some reason I''m getting >> >> "NoMethodError in Search#simple >> >> undefined method `min_age='' for #<Search:0x23da2cc>" >> >> as if min_age weren''t defined... what could be causing this? >> >> thanks >> Oliver >> _______________________________________________ >> Rails mailing list >> Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org >> http://lists.rubyonrails.org/mailman/listinfo/rails > > _______________________________________________ > Rails mailing list > Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org > http://lists.rubyonrails.org/mailman/listinfo/rails
David, many thanks for the thorough explanation. using attr_accessor did the trick, and I understand better how these attribute setters work. I''ve read up on the article you sent, and am now using ''attr_accessible'' for the attributes being searched for, from what I understood this would be the most secure way correct? 2005/11/28, David Rupp <rails-T+GAArMh60A/u7dgPfZd+NBPR1lH4CV8@public.gmane.org>:> Oliver, > > After further review, I wanted to correct and clarify a couple of > things. The problem is related to the the writability of your > attributes, but it''s not in the line I cited. That line is just > setting the values of the parameters used in the SQL query that does > your find(). It''s when you call Search.new(params[:search]) that > you''re getting the complaint about the undefined method. This form of > new() is a shortcut for assigning values to all attributes that have > corresponding parameters in the inbound request. You can still change > the declaration of your attributes, but you probably want to change > them (in the simplest case) to "attr_accessor", instead of > "attr_reader" or "attr_writer". attr_accessor generates both read and > write methods. If you change them to attr_writer, you''ll be able to > write to the attributes but not read from them (the converse of the > problem you''re having now). > > Keep in mind that there are some implications for the security of > your data when you use the shortcut method for assigning attributes > from request parameters. http://manuals.rubyonrails.com/export/html/8 > has some good information on this topic. > > David > > On Nov 28, 2005, at 9:52 AM, David Rupp wrote: > > > Oliver, > > > > I think you''re okay up to the point where you do > > > >> {:min_age => min_age, :max_age => max_age}]) > > > > Because you''re doing assignments, :min_age and :max_age need to be > > writable. attr_reader does not generate an assignment method of the > > form described in the NoMethodError message. If you''ll look closely > > at the method name referenced there, you''ll see the "=" appended to > > "min_age". > > > > Long story short -- change your "attr_reader" declaration to use > > "attr_writer" and your code should work as you expect. > > > > Regards, > > David > > > > On Nov 27, 2005, at 1:29 PM, Oliver Barnes wrote: > > > >> I have this model that holds search parameters accross pages: > >> > >> class Search < User > >> attr_reader :min_age, :max_age > >> end > >> > >> for a form: > >> ... > >> <% age_list = (0..99).collect {|x| [x,(Date.today.year-x)]} %> > >> <%= select ''search'',''min_age'', age_list %><br> > >> <%= select ''search'',''max_age'', age_list.reverse %><br><br> > >> .... > >> > >> then in the search controller I have: > >> > >> class SearchController < ApplicationController > >> > >> def simple > >> if params[:search] > >> @search = Search.new(params[:search]) > >> session[:search] = @search > >> else > >> @search = session[:search] > >> end > >> > >> @results = User.find(:all, > >> :conditions => [":min_age < year(birthday) < :max_age", > >> {:min_age => min_age, :max_age => max_age}]) > >> .... > >> end > >> > >> for some reason I''m getting > >> > >> "NoMethodError in Search#simple > >> > >> undefined method `min_age='' for #<Search:0x23da2cc>" > >> > >> as if min_age weren''t defined... what could be causing this? > >> > >> thanks > >> Oliver > >> _______________________________________________ > >> Rails mailing list > >> Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org > >> http://lists.rubyonrails.org/mailman/listinfo/rails > > > > _______________________________________________ > > Rails mailing list > > Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org > > http://lists.rubyonrails.org/mailman/listinfo/rails > > _______________________________________________ > Rails mailing list > Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org > http://lists.rubyonrails.org/mailman/listinfo/rails >
It''s more secure, in the sense that it gives you explicit control over which attributes can be set automatically from forms. Any attributes declared as attr_accessible are still subject to the same kinds of attacks described in that article. If your app needs more security, you''ll need to take even more control and set attributes by calling the setter methods directly (say, after you do your own validation), rather than letting them be set automatically by the new / initialize methods. Glad I could help. :-) On Nov 28, 2005, at 1:03 PM, Oliver Barnes wrote:> David, many thanks for the thorough explanation. using attr_accessor > did the trick, and I understand better how these attribute setters > work. > > I''ve read up on the article you sent, and am now using > ''attr_accessible'' for the attributes being searched for, from what I > understood this would be the most secure way correct? > > > 2005/11/28, David Rupp <rails-T+GAArMh60A/u7dgPfZd+NBPR1lH4CV8@public.gmane.org>: >> Oliver, >> >> After further review, I wanted to correct and clarify a couple of >> things. The problem is related to the the writability of your >> attributes, but it''s not in the line I cited. That line is just >> setting the values of the parameters used in the SQL query that does >> your find(). It''s when you call Search.new(params[:search]) that >> you''re getting the complaint about the undefined method. This form of >> new() is a shortcut for assigning values to all attributes that have >> corresponding parameters in the inbound request. You can still change >> the declaration of your attributes, but you probably want to change >> them (in the simplest case) to "attr_accessor", instead of >> "attr_reader" or "attr_writer". attr_accessor generates both read and >> write methods. If you change them to attr_writer, you''ll be able to >> write to the attributes but not read from them (the converse of the >> problem you''re having now). >> >> Keep in mind that there are some implications for the security of >> your data when you use the shortcut method for assigning attributes >> from request parameters. http://manuals.rubyonrails.com/export/html/8 >> has some good information on this topic. >> >> David >> >> On Nov 28, 2005, at 9:52 AM, David Rupp wrote: >> >>> Oliver, >>> >>> I think you''re okay up to the point where you do >>> >>>> {:min_age => min_age, :max_age => max_age}]) >>> >>> Because you''re doing assignments, :min_age and :max_age need to be >>> writable. attr_reader does not generate an assignment method of the >>> form described in the NoMethodError message. If you''ll look closely >>> at the method name referenced there, you''ll see the "=" appended to >>> "min_age". >>> >>> Long story short -- change your "attr_reader" declaration to use >>> "attr_writer" and your code should work as you expect. >>> >>> Regards, >>> David >>> >>> On Nov 27, 2005, at 1:29 PM, Oliver Barnes wrote: >>> >>>> I have this model that holds search parameters accross pages: >>>> >>>> class Search < User >>>> attr_reader :min_age, :max_age >>>> end >>>> >>>> for a form: >>>> ... >>>> <% age_list = (0..99).collect {|x| [x,(Date.today.year-x)]} %> >>>> <%= select ''search'',''min_age'', age_list %><br> >>>> <%= select ''search'',''max_age'', age_list.reverse %><br><br> >>>> .... >>>> >>>> then in the search controller I have: >>>> >>>> class SearchController < ApplicationController >>>> >>>> def simple >>>> if params[:search] >>>> @search = Search.new(params[:search]) >>>> session[:search] = @search >>>> else >>>> @search = session[:search] >>>> end >>>> >>>> @results = User.find(:all, >>>> :conditions => [":min_age < year >>>> (birthday) < :max_age", >>>> {:min_age => min_age, :max_age => max_age}]) >>>> .... >>>> end >>>> >>>> for some reason I''m getting >>>> >>>> "NoMethodError in Search#simple >>>> >>>> undefined method `min_age='' for #<Search:0x23da2cc>" >>>> >>>> as if min_age weren''t defined... what could be causing this? >>>> >>>> thanks >>>> Oliver >>>> _______________________________________________ >>>> Rails mailing list >>>> Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org >>>> http://lists.rubyonrails.org/mailman/listinfo/rails >>> >>> _______________________________________________ >>> Rails mailing list >>> Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org >>> http://lists.rubyonrails.org/mailman/listinfo/rails >> >> _______________________________________________ >> Rails mailing list >> Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org >> http://lists.rubyonrails.org/mailman/listinfo/rails >> > _______________________________________________ > Rails mailing list > Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org > http://lists.rubyonrails.org/mailman/listinfo/rails