Forum: Ruby on Rails attr_reader not being read?

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
648d60296e65a1278017c0b9f960ec3a?d=identicon&s=25 ol1barn3s (Guest)
on 2005-11-27 21:30
(Received via mailing list)
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
Bfc3ae865ab5cb781b9d1d4b50ab132b?d=identicon&s=25 rails (Guest)
on 2005-11-28 17:55
(Received via mailing list)
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
Bfc3ae865ab5cb781b9d1d4b50ab132b?d=identicon&s=25 rails (Guest)
on 2005-11-28 19:28
(Received via mailing list)
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
648d60296e65a1278017c0b9f960ec3a?d=identicon&s=25 ol1barn3s (Guest)
on 2005-11-28 21:05
(Received via mailing list)
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@ruppconsulting.com>:
Bfc3ae865ab5cb781b9d1d4b50ab132b?d=identicon&s=25 rails (Guest)
on 2005-11-28 22:22
(Received via mailing list)
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. :-)
This topic is locked and can not be replied to.