【问题标题】:Form_for helperForm_for 助手
【发布时间】:2014-03-04 08:06:52
【问题描述】:

我有 2 个模型通过连接表相互关联:

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

现在,我可以更新路线上的评论(我在控制台中手动创建的):

readers/:id/books 

上面的路由是使用rails的成员方法创建的:

resources :readers
  member do
    get 'books'
  end
end

评论控制器中的更新操作(reviews#update)定义如下:

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

我的 form_for 评论 (reviews#update) 如下所示: 读者评论:

<% 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 %>

以上适用于更新。但第二种形式没有。

我的意图是检查评论 => 如果有 - 显示一个表格,以便读者可以更新评论;如果没有,则显示一个表格,以便读者可以创建评论。我在评论控制器中有一个私有方法,可以在执行任一操作之前检查以确保读者有书(我猜是 before_action 方法)。

第一个表单(更新表单)运行良好,但第二个不行——表单根本不显示。我尝试了各种方法来显示表单,但没有运气。能否请我确定解决此问题的最佳方法?

非常感谢!

【问题讨论】:

    标签: ruby-on-rails forms associations


    【解决方案1】:

    可能有几个问题:

    elsif

    您的其他表单不显示的可能原因是您的 elsif 逻辑不正确

    我查看了.include? Ruby 函数,它似乎只适用于数组。为什么不尝试改用.exists?

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

    您可能必须使用 review.id 或类似名称才能获得正确的响应。做不到这一点,你为什么不直接使用&lt;% else %&gt;


    form_for

    第二个问题可能是你的第二个form_for

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

    您当前正在将名为 book 的局部变量传递给 form_for 构建器。虽然这可能是正确的(我找不到您对创建 book 的引用),但我发现最好在嵌套形式中放置一个符号(以向 Rails 显示它需要使用哪些数据)

    【讨论】:

    • 抱歉!不小心按回车:(我确实尝试了你的两个建议:将 .include? 更改为 .exists? 并将 elsif 更改为 否则。不幸的是,页面上显示的唯一表单是更新表单。我仍然无法显示用于创建新评论的表单。我现在正在去学校的路上,但我会更新我的问题(提供更多信息)我一进去。谢谢你的帮助!
    • 添加了我的答案!感谢您的帮助:)
    【解决方案2】:

    您可以尝试使用else 代替elsif !current_reader.reviews.include?(review) 吗?

    另外,它是elsif 而不是elseif。问题不应该是因为这个 - 如果是这种情况,页面一开始就不会加载。

    【讨论】:

      【解决方案3】:

      更新 我通过更新表单修复了我的第一个错误: 读者评论:

      <% 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 %>
      

      这将显示表单(发布和更新)。 但是我在尝试发布新评论时收到此错误:

      (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) 
      

      所以我更改了我的创建操作以确保 book_id 不为零:

      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
      

      还改变了我定义 review_params 的方式:

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

      所有这些更改都产生了预期的结果。我的代码一点也不枯燥,但此时对我来说最重要的是让事情正常工作。这是希望我不要再次破坏它。感谢您的帮助@RichPeck

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-09-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多