سؤال

I have 2 models that are associated with each other via a join table:

class Book < ActiveRecord::Base
  has_many :reviews
end

class Reader < ActiveRecord::Base
  has_many :reviews
end

class Reviews < ActiveRecord::Base
  belongs_to :reader
  belongs_to :book
end

Right now, I am able to update a review (which I created manually in the console) on route:

readers/:id/books 

The above route was create using rails' member method:

resources :readers
  member do
    get 'books'
  end
end

The update action in reviews controller (reviews#update) is defined like so:

def update
  @reader = current_reader
  @review = Review.find_by_reader_id(@reader.id)
  @book = Book.find(params[:review][:book]
  if @reader.books.include?(@book)
     @review.update_attributes(review_params)
     redirect_to (@reader)
  else
     flash[:error] = 'You can only edit reviews that belong to you'
  end
end

My form_for reviews (reviews#update) looks like this: Reader Reviews:

<% book.reviews.each do |review| %>
  <% if current_reader == (review.reader) %>
  <%= review.content %> written by <%= review.reader.name %>
    <% if current_reader.reviews.include?(review) %>
      <%= form_for ([book, review]) do |f| %>
        <div class="field">
         <%= f.hidden_field :book, :value => book.id %>
         <%= f.text_area :content, placeholder: "compose new review" %>
        </div>
        <%= f.submit "Update", class: "btn btn-large btn-primary" %>
     <% else %>
       <%= form_for ([book, review]) do |f| %>
         <div class="field">
           <%= f.hidden_field :book, :value => book.id %>
           <%= f.text_area :content, placeholder: "compose new review" %>
         </div>
         <%= f.submit "Post", class: "btn btn-large btn-primary" %>
       <% end %>
     <% end %>
  <% end %>
<% end %>

The above works for update. But the 2nd form doesn't.

My intent is to check for a review => if there is one - display a form so that reader can update review; if there isn't one then display a form so that reader can create a review. I have a private method in reviews controller that checks to make sure that a reader has a book before either action is carried out (a before_action method I guess).

The first form works well (the update form) but the second does not - the form is not displayed at all. I have tried various things to get the form to display but no luck. Can you please me determine the best way to resolve this issue?

Thank you very much!

لا يوجد حل صحيح

نصائح أخرى

There could be several issues:

elsif

The likely reason your other form won't show will be that your elsif logic won't be correct

I had a look at the .include? Ruby function, and it seems to just be for arrays. Why not try using .exists? instead?

<% elseif !current_reader.reviews.exists?(review) %>

You may have to use review.id or similar to get the correct response. Failing that, why don't you just use <% else %>?


form_for

The second issue may be with your second form_for

<%= form_for [:book, review] do |f| %>

You're currently passing a local variable called book to the form_for builder. Although this is probably correct (I can't find your reference to creating book), I've found it best to put a symbol in the nested form (to show Rails which data it needs to use)

Could you try using else instead of elsif !current_reader.reviews.include?(review)?

Also, it's elsif and not elseif. The problem should not because of this - The page would not have loaded in the first place if this is the case.

UPDATE I fixed my first error by updating my forms: Reader Reviews:

<% book.reviews.where(reader_id: current_reader.id).each do |review| %>
  <li>
    <span><%= review.content %> writen by <%= review.reader.name %> </span
    <%= form_for ([book, review]) do |f| %>
      <div class="field">
        <%= f.hidden_field :book, :value => book.id %>
        <%= f.text_area :content, placeholder: "compose new review" %>
      </div>
        <%= f.submit "Update", class: "btn btn-large btn-primary" %>
    <% end %>
  </li>
    <% if book.reviews.where(reader_id: current_reader.id).size == 0 %>
      <%= form_for ([book, book.reviews.build]) do |f| %>
        <div class="field">
          <%= f.hidden_field :book, :value => book.id %>
          <%= f.text_area :content, placeholder: "compose new review" %>
        </div>
        <%= f.submit "Post", class: "btn btn-large btn-primary" %>
    <% end %>
  <% end %>
<% end %>

This displays the forms (both post and update). BUT I got this error when I tried to post a new review:

(rdb:35) @review
#<Review id: nil, reader_id: 101, content: "Trial", created_at: nil, updated_at: nil, book_id: nil>
(rdb:35) review_params
Unpermitted parameters: book
{"content"=>"Trial"}
(rdb:35) 

So I changed my create action for review to make sure book_id isn't nill:

def create
  @reader = current_reader
  # @book = Book.find(params[:book_id])
  @book = Book.find(params[:review][:book])
  if @reader.reviews.where(book_id: @book.id).exists? 
    flash[:error] = "You already reviewed this book"
  else
    @review = current_reader.reviews.create(:book_id => params[:book_id.to_i, :content => review_params[:content])
    debugger
    if @review.save
      flash[:success] = "Review created"
      redirect_to reader_path(@reader)
    else
      flash[:error] = "You can only review books that are in your library"
      redirect_to reader_path(@reader)
    end
  end
end

Also changed how I defined review_params:

def review_params
  params.require(:review).permit(:content, :book_id)
end

All this changes gave the desired results. My code isn't dry AT ALL but the most important thing to me at this point is getting things to work. Here is to hoping I don't break it again. Thanks for your help @RichPeck

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top