Polymorphic Problem

Hi. I believe that I need to write a method to get my user’s
information, but I’m not sure how to write this and where it should go.

I have Reviews as polymorphic and there are several types items that can
be reviewed (books, music, movies, etc). A user can search for a book
and see all of the reviews for that book. Posted with each review, I
want to provide the name of the user. Based on what I have, what is the
best way to do this and where does this code go? Right now if I pull up
the book, I can see all of the reviews. In the review table I have the
review_user_id and now I want to display the name of that user from the
users table.

Here’s my basic structure, but noting that I have put snippets of the
data here for brevity.

class CreateReviews < ActiveRecord::Migration
def self.up
create_table :reviews
t.string :reviewable_type
t.integer :reviewable_id
t.string :title
t.text :body
t.integer :review_user_id
end
end
end

class CreateUsers < ActiveRecord::Migration
def self.up
create_table :users
t.string :name
end
end
end

class Review < ActiveRecord::Base
belongs_to :reviewable, :polymorphic => true
end

class Book < ActiveRecord::Base
has_many :reviews, :as => reviewable
end

class User < ActiveRecord::Base
has_many :reviews, :as => :reviewable
end

THANKS!

Please see the above post for the setup of my models.

While trying to figure this out, I put this into script/console:

Book.find(1).reviews

=> [<#Review id: 2, reviewable_type: “Book”, reviewable_id: 1,
review_user_id: 1>]

How can I take the value of review_user_id and get the name of the user
in the users table?

Thanks!

If your review model looks like this:

class Review
belongs_to :user
belongs_to :reviewable, :polymorphic => true
end

You could probably do something like this:

Book.find(1).reviews.each do |r|
puts r.user.name
end

On Fri, Sep 19, 2008 at 7:10 PM, Becca G.
[email protected] wrote:

How can I take the value of review_user_id and get the name of the user
in the users table?

Thanks!


Maurício Linhares
http://alinhavado.wordpress.com/ (pt-br) | http://blog.codevader.com/
(en)
João Pessoa, PB, +55 83 8867-7208

You need to let ActiveRecord know about the association:
(You don’t specify the Rails version you’re using, but I’m guessing 2.x)

Yes, using Rails 2.1

class User < ActiveRecord::Base
has_many :reviews, :as => :reviewable # can users be reviewed like
Books, etc.?

if you mean for user.reviews to be the set of reviews

that this user wrote, then you want:

has_many :reviews, :foreign_key => ‘review_user_id’
end

In my reviews table I have 2 user values, created_by and modifed_by.
Users can not be reviewed, but you can view all of the reviews per user.
Can I do the foreign key like you have in your second example if my
review table has 2 fields that link back to the user.id field?

On Sep 19, 2008, at 6:10 PM, Becca G. wrote:

How can I take the value of review_user_id and get the name of the
user
in the users table?

Thanks!

You need to let ActiveRecord know about the association:
(You don’t specify the Rails version you’re using, but I’m guessing 2.x)

class Review < ActiveRecord::Base
belongs_to :reviewable, :polymorphic => true
belongs_to :review_user, :class_name => ‘User’

or perhaps:

belongs_to :reviewer, :class_name => ‘User’, :foreign_key =>

‘review_user_id’
end

class Book < ActiveRecord::Base
has_many :reviews, :as => reviewable
end

class User < ActiveRecord::Base
has_many :reviews, :as => :reviewable # can users be reviewed like
Books, etc.?

if you mean for user.reviews to be the set of reviews

that this user wrote, then you want:

has_many :reviews, :foreign_key => ‘review_user_id’
end

Does that work for you?

-Rob

Rob B. http://agileconsultingllc.com
[email protected]

On Sep 22, 2008, at 9:23 AM, Becca G. wrote:

if you mean for user.reviews to be the set of reviews

that this user wrote, then you want:

has_many :reviews, :foreign_key => ‘review_user_id’
end

In my reviews table I have 2 user values, created_by and modifed_by.
Users can not be reviewed, but you can view all of the reviews per
user.
Can I do the foreign key like you have in your second example if my
review table has 2 fields that link back to the user.id field?

Then you need to give the proper foreign_key

class User
has_many :reviews, :foreign_key => ‘created_by’
end

class Review
belongs_to :creator, :class_name => ‘User’, :foreign_key =>
‘created_by’
end

-Rob

Rob B. http://agileconsultingllc.com
[email protected]

On Sep 22, 2008, at 9:54 AM, Becca G. wrote:

end
C:/var/intranet3/app/models/user.rb:1
55: parse error, unexpected kEND, expecting $ (SyntaxError)

class CreateReviews < ActiveRecord::Migration
def self.up
create_table :reviews
missing: do |t|

class User
has_many :reviews, :foreign_key => ‘create_review_user_id’
has_many :reviews, :foreign_key => ‘modify_review_user_id’
You can’t call both associations “reviews”
has_many :created_reviews, …
has_many :editted_reviews, …

end

class Review
belongs_to :creator, :class_name => ‘User’, :foreign_key =>
‘create_review_user_id’
belongs_to :modified, :class_name => ‘User’, :foreign_key =>
‘modify_review_user_id’
belongs_to :modifier might be a better name than ‘modifiED’

end

-Rob

Rob B. http://agileconsultingllc.com
[email protected]

Ok, here’s what I have in my models.

class Review < ActiveRecord::Base
belongs_to :reviewable, :polymorphic => true
belongs_to :created_reviews, :class_name => ‘User’, :foreign_key =>
‘create_review_user_id’
belongs_to :modified_reviews, :class_name => ‘User’, :foreign_key =>
‘modify_review_user_id’
end

class User < ActiveRecord::Base
has_many :reviews, :as => :reviewable
has_many :created_reviews, :foreign_key => ‘create_review_user_id’
has_many :modified_reviews, :foreign_key => ‘create_review_user_id’

Sorry I’m so dense, but after all of that, how do I access User.name?

Rob B. wrote:

Then you need to give the proper foreign_key

class User
has_many :reviews, :foreign_key => ‘created_by’
end

class Review
belongs_to :creator, :class_name => ‘User’, :foreign_key =>
‘created_by’
end

I must be missing what you’re telling me because I get an error.
Polymorphic associations are new to me and quite confusing. I’ve read a
lot, but still don’t quite understand how to set these up.

C:/project/vendor/rails/activesupport/lib/active_support/dependencies.rb:2
15:in `load_without_new_constant_marking’:
C:/var/intranet3/app/models/user.rb:1
55: parse error, unexpected kEND, expecting $ (SyntaxError)

class CreateReviews < ActiveRecord::Migration
def self.up
create_table :reviews
t.string :reviewable_type
t.integer :reviewable_id
t.string :title
t.text :body
t.integer :create_review_user_id
t.integer :modify_review_user_id
end
end
end

class User
has_many :reviews, :foreign_key => ‘create_review_user_id’
has_many :reviews, :foreign_key => ‘modify_review_user_id’
end

class Review
belongs_to :creator, :class_name => ‘User’, :foreign_key =>
‘create_review_user_id’
belongs_to :modified, :class_name => ‘User’, :foreign_key =>
‘modify_review_user_id’
end

review.created_reviews.name

On Mon, Sep 22, 2008 at 4:58 PM, Becca G.
[email protected] wrote:


Posted via http://www.ruby-forum.com/.


Maurício Linhares
http://alinhavado.wordpress.com/ (pt-br) | http://blog.codevader.com/
(en)
João Pessoa, PB, +55 83 8867-7208

Maurício Linhares wrote:

review.created_reviews.name

I wasn’t sure where this should all go, but I am still getting errors.
Here’s what I did in script/console:

Book.find(1).reviews

=> [<#Review id: 2, reviewable_type: “Book”, reviewable_id: 1,
create_review_user_id: 1>]

review.created_reviews.name

=> NameError: undefined local variable or method `review’ for
#Object:0x18fa38
from (irb):9

If I put this in, I also get an error.

Book.find(1).reviews.each do |r|
?> puts review.created_reviews.name

end
NameError: undefined local variable or method `review’ for
#Object:0x18fa38
from (irb):11

Clearly I’m lost and confused. Thanks for helping out this new ruby
girl.

On Sep 22, 2008, at 3:58 PM, Becca G. wrote:

Ok, here’s what I have in my models.

class Review < ActiveRecord::Base
belongs_to :reviewable, :polymorphic => true
belongs_to :created_reviews, :class_name => ‘User’, :foreign_key =>
‘create_review_user_id’
This would be clearer as something singular (like ‘reviewer’) since a
belongs_to is going to give a single associated record.

belongs_to :modified_reviews, :class_name => ‘User’, :foreign_key =>
‘modify_review_user_id’
end

class User < ActiveRecord::Base
has_many :reviews, :as => :reviewable
has_many :created_reviews, :foreign_key => ‘create_review_user_id’
has_many :modified_reviews, :foreign_key => ‘create_review_user_id’
Perhaps you meant for the second one to be ‘modify_review_user_id’?

Sorry I’m so dense, but after all of that, how do I access User.name?

On Sep 22, 2008, at 4:27 PM, Becca G. wrote:

=> [<#Review id: 2, reviewable_type: “Book”, reviewable_id: 1,
create_review_user_id: 1>]

review.created_reviews.name

=> NameError: undefined local variable or method `review’ for
#Object:0x18fa38
from (irb):9

review = Book.find(1).reviews.first

If I put this in, I also get an error.

Book.find(1).reviews.each do |r|
?> puts review.created_reviews.name

end
NameError: undefined local variable or method `review’ for
#Object:0x18fa38
from (irb):11

Close, try:
Book.find(1).reviews.each do |review|
then the block will have a variable named review (rather than the r in
your first attempt)

Clearly I’m lost and confused. Thanks for helping out this new ruby
girl.

Be aware that your confusion seems to be a mix of Rails (specifically,
ActiveRecord) conventions and Ruby syntax.

-Rob

Rob B. http://agileconsultingllc.com
[email protected]

Rob B. wrote:

Be aware that your confusion seems to be a mix of Rails (specifically,
ActiveRecord) conventions and Ruby syntax.

Yes, I’m still new to this. Thank you so much for your patience and
great help.

I’ve got it all working now!