Forum: Ruby on Rails Another DRY question

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.
Vince W. (Guest)
on 2006-04-20 03:29
I have some code working that lists only items from a particular user.
The code in my list action finds the user and then conditionally lists
only his/her items:

  def list
  user = User.find(session[:user])
  user_id = user.id
  @product_pages, @products = paginate :products, :per_page => 10,
                                       :conditions =>['user_id = ?',
user.id]
  end

So far so good!

Now I'd like to create an object an automatically add the user's id to
the user_id field in the product table.  I don't want to keep typing the
user = User.find stuff over and over again so thought that I could
create a private method and have it work that way, but I'm having
trouble with.. syntax.

private
  def find_user
    user = Usr.find(session[:user])
    user_id = user.id
  end
end

And then changing my list to

  def list
    @user = find_user
    @product_pages, @products = paginate :products, :per_page => 10,
                                       :conditions =>['user_id = ?',
@user]
  end

Gives me an error about unknown method user.  Can somebody save me lots
of typing of the same thing over & over again?
Kevin O. (Guest)
on 2006-04-20 03:50
(Received via mailing list)
product belongs_to :user
user has_many :products

when saving a new product
@product.user = session[:user]

Then you can do things like...

user.products

you could also just store the entire user object in your session and use
it as needed.

On Thursday, April 20, 2006, at 1:29 AM, Vince W. wrote:
>  end
>  def find_user
>                                       :conditions =>['user_id = ?',
>removed_email_address@domain.invalid
>http://lists.rubyonrails.org/mailman/listinfo/rails


_Kevin
Vince W. (Guest)
on 2006-04-20 04:37
Kevin O. wrote:
> product belongs_to :user
> user has_many :products
>
> when saving a new product
> @product.user = session[:user]
>
> Then you can do things like...
>
> user.products
>

Ok, I added belongs_to :user  in my product.rb model and has_many
:products in my user.rb model.

Then I tried to rewrite my post list code to:

@product_pages, @user.products = paginate :products, :per_page => 10

but that gives me a nil object error.

I then tried it as
@product_pages, products = paginate :user.products, :per_page => 10
but got a unknown method 'user' error

Any pointers?
Michael D. (Guest)
on 2006-04-20 04:42
(Received via mailing list)
Vince,

Perhaps you should have a look at how Ruby does objects, methods, and
variables? The Poignant Guide might be helpful:

   http://poignantguide.net/ruby/

Anyhow, you don't need this line if you're using "user.id" to refer
to the user's id:

   user_id = user.id

Also, since you're using session[:user] to store a user's id, you
*could* get away with removing the first two lines and just doing this:

   @product_pages, @products = paginate :products, :per_page =>
10, :conditions => ['user_id = ?', session[:user]]

But maybe it's not a good idea to assume there'll be a usable user id
in session[:user]. Plus, maybe you have a few actions in that
controller that refer to the same user. In that case, you could write
a private (or protected, maybe) function like this:

   def find_user
     @user = User.find(session[:user])
   end

That sets the @user instance variable to the user that's referred to
in the session, so you can use @user in other methods. You might say:

   @product_pages, @products = paginate :products, :per_page =>
10, :conditions => ['user_id = ?', @user.id]

And so you don't have to call find_user in every method, you could
use a filter:

   before_filter :find_user

Or (and this is what I do sometimes) you could have a function called
"current_user" which returns the user with the id stored in session
[:user]:

   def current_user
     @current_user ||= User.find(session[:user])
   end

This says (sort of) "if the @current_user instance variable isn't set
already, set it to the user that the User model finds with the user
id in the session, and then return the value of @current_user. Then
you can say:

   @product_pages, @products = paginate :products, :per_page =>
10, :conditions => ['user_id = ?', current_user.id]

Also, if you're just starting to develop your application and you
don't have a login system yet, (which is really easy to add later but
is pretty mechanical, so it's a good idea to ignore it) you could
just tell current_user to return, for example:

   User.find_by_name("vince")

And you're always logged in! When you put your login system in, just
tell current_user to look at the session, or however else you might
keep track of users.


-- Michael D.
    http://www.mdaines.com
Vince W. (Guest)
on 2006-04-20 07:36
Michael, Kevin

Thanks very much for your help. It's really saved me a tremendous amount
of time and works very well.  I had a couple of warn statements that
were throwing me off but once I figured that out your solution works
perfectly.

Thanks again,
Vince
This topic is locked and can not be replied to.