Reputation: 345
I have two objects - User and Reviews. One User can write many reviews, but one review can be written by one user. Every user has a picture. I have:
class Review < ActiveRecord::Base
belongs_to :user
end
class User < ActiveRecord::Base
has_many :reviews
end
Why can't I do the following?
review.user.picture
Upvotes: 0
Views: 63
Reputation: 76784
Method
The bottom line is your picture
method will not be present in your user
model
You can either use an instance method
to create some functionality in your User
model, use an ActiveRecord Association
, or use something like Paperclip
to provide an appended object on your user
object
Association
You'll need to create the correct association for your review
& picture
objects -
#app/models/user.rb
Class Review < ActiveRecord::Base
has_many :reviews
has_one :picture
end
#app/models/picture.rb
Class Picture < ActiveRecord::Base
belongs_to :user
end
This will allow you to call:
@review = Review.find params[:id]
@picture = @review.user.picture
A bonus tip for this is if you wanted to ensure compatibility with the law of dementer, you could use the delegate
method in your user
model:
#app/models/user.rb
Class User < ActiveRecord::Base
...
delegate :attribute, to: :picture, prefix: true
end
This will allow you to call the likes of:
@review.user.picture_name
Paperclip
If you're using a picture model to store images, you may wish to use the likes of Paperclip
to give you the ability to use the functionality of images in your Picture
model:
#app/models/user.rb
Class User < ActiveRecord::Base
...
delegate :url, to: :picture
end
#app/models/picture.rb
Class Picture < ActiveRecord::Base
has_attached_file :picture
end
These will all help you. Using this answer with Иван Бишевац
's will help you profusely :)
Upvotes: 0
Reputation: 9318
Based on the info you provided, I'm assuming you still need to set up a foreign key in the database. The database migration for the the reviews table should look similar to this:
class CreateReviews < ActiveRecord::Migration
def change
create_table :reviews do |t|
t.integer :user_id
t.timestamps
end
add_index :reviews, :user_id
end
end
Then you would be able to add a related user_id
to a new review object. For instance, in rails console:
Review.new(user_id: 1)
Assuming that you defined picture
as a column in your User table, you should be able to run review.user.picture
without any issues.
Upvotes: 0
Reputation: 14701
You have to establish has_one
/belongs_to
associations on user
/picture
models and of course to have appropriate database migrations (foreign key user_id on picture table and foreign key user_id on review table).
Models look like:
class Review < ActiveRecord::Base
belongs_to :user
end
class User < ActiveRecord::Base
has_many :reviews
has_one :picture
end
class Picture
belongs_to :user
end
To try it, first create data in rails console:
user = User.create
review = Review.create user: user
picture = Picture.create user: user
Now you can find user picture if you have only reference to review object. Exit console and run again and type:
review = Review.last
review.user.picture
It returns picture object.
More info:
http://guides.rubyonrails.org/association_basics.html#choosing-between-belongs-to-and-has-one
Upvotes: 2