Form_for 助手

Posted

技术标签:

【中文标题】Form_for 助手【英文标题】:Form_for helper 【发布时间】: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 方法)。

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

非常感谢!

【问题讨论】:

【参考方案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

【讨论】:

以上是关于Form_for 助手的主要内容,如果未能解决你的问题,请参考以下文章

单击 form_for 中的 HTML 按钮时防止自动刷新

rails form_for标签的自定义文本

Rails 5:form_for 与 form_with

asm小助手上不了网

Google访问助手怎么下载?

携程微信行程助手