Another DRY question


#1

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?


#2

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


#3

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?


#4

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


#5

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