Attr_reader not being read?

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 %>

<%= select ‘search’,‘max_age’, age_list.reverse %>


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

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 R. [email protected]:

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. Peak Obsession
has some good information on this topic.

David

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. :slight_smile: