1

I have a User model and a Book model joined with a Like model.

class Book < ActiveRecord::Base
belongs_to :user
# the like associations
has_many :likes
has_many :liking_users, :through => :likes, :source => :user 

class User < ActiveRecord::Base
has_many :books
# the like associations
has_many :likes
has_many :liked_books, :through => :likes, :source => :book

class Like < ActiveRecord::Base
belongs_to :user
belongs_to :book 

I want to add an attribute to the Like model so while right now a User can Like a book to add it to their profile, I want the User to be able to write a recommendation.

I generated the attribute Recommendation:text to the Like (joining) model, but am unsure how to add this to views so a User can write a recommendation that will be tied to the Like (and thus that book and user).

I'm looking at this post - Rails has_many :through Find by Extra Attributes in Join Model - which describes something similar but does not explain how to implement this in the views.

Let me know if you can point me in the right direction. Thanks!

Community
  • 1
  • 1
Dani Fankhauser
  • 651
  • 6
  • 16
  • I think you should separate the Like and the Recommendation models: You could like a book but not want to recommend it, also you could write a "bad text" about a Book (opposite of the recommendation) without liking it. You could create a new model `Comment` (or Recommendation as you said) which would act exactly as the Like model – MrYoshiji Jun 04 '14 at 15:19
  • Great, say I rename Like to be Comment and do just that. Can it have a text attribute, and how to I put that into the views so a User can fill it in? – Dani Fankhauser Jun 04 '14 at 15:38

2 Answers2

0

I think you should create a separate model for this Recommendation, dependent of the Like model:

class Book < ActiveRecord::Base
  belongs_to :user
  has_many :comments
  has_many :commenters, :through => :comments, :source => :user 

class User < ActiveRecord::Base
  has_many :books
  has_many :comments
  has_many :commented_books, :through => :comments, :source => :book

class Comment < ActiveRecord::Base
  belongs_to :user
  belongs_to :book

Then, the logic to create a comment for a book:

# Books Controller
def show
  @book = Book.find(params[:id])
  @comment = @book.comments.build
end

# show view of the book
form_for @comment do |form|
  form.hidden_field :user_id, value: current_user.id
  form.hidden_field :book_id
  form.text_area :content # the name of the attribute for the content of the comment

  form.submit "Post comment!"
end

To list all the comments of a specific User:

# users controller (profile page)
def show
  @user = User.find(params[:id])
end

# show view of Users
@user.comments.includes(:book).each do |comment|
  "Comment on the book '#{comment.book.name}' :"
  comment.content
end
MrYoshiji
  • 54,334
  • 13
  • 124
  • 117
  • Interesting. So on the user profile page I want to show all their book recommendations -- would this just be @user.commented_books ? (I'm going to try this tonite, thanks!!) – Dani Fankhauser Jun 04 '14 at 15:54
  • Hmm no this `@user.commented_books` would return Books objects, but you want to list `Comment` object: `@user.comments` is what you want. then you can access to the book via the comment object by doing `comment.book` – MrYoshiji Jun 04 '14 at 15:58
  • I DO want the book object -- the User page would show books they've recommended, and when you click on the book it would show their recommendation on the book view -- am I missing something? – Dani Fankhauser Jun 04 '14 at 16:13
  • It can work like that, yeah. It works for both cases (see my answer's update), you can either display the list of all comments + book's name OR list all the commented books. It's your choice – MrYoshiji Jun 04 '14 at 16:15
0

I suppose that the like functionnality works with ajax ? (remote: :true or in pure javascript) You can append a form with the response of your request with the id of the new like, and again handle the recommendation by an ajax request

dzof31
  • 1,423
  • 1
  • 12
  • 20