Rails 4 _form部分创建新记录,但不会编辑当前记录 [英] Rails 4 _form partial creates new record but won't edit current record

查看:98
本文介绍了Rails 4 _form部分创建新记录,但不会编辑当前记录的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我构建了一个具有业务的简单应用,这些业务有很多评论.我正在使用部分_form来创建/更新评论.创建动作可以正常工作,但是更新动作将创建一个新的审阅,而不是像预期的那样更新审阅.这是相关代码(为简便起见,删除了不相关的代码):

I've built a simple app that has businesses, and those businesses have many reviews. I'm using a partial _form to create/update reviews. The create action works fine, but the update action creates a new review instead of updating the review like its supposed to. Here's the relevant code (irrelevant code removed for brevity):

来自routes.rb的代码:

resources :businesses do
  resources :reviews
end

models/business.rb中的代码:

class Business < ActiveRecord::Base
  has_many :reviews, dependent: :destroy
  validates_associated :reviews
end

来自models/review.rb的代码:

class Review < ActiveRecord::Base
  belongs_to :business
  belongs_to :user
end

来自controllers/reviews_controller.rb的代码:

class ReviewsController < ApplicationController
  load_and_authorize_resource

  before_filter :load_business

  def new
  end

  def index
  end

  def create
    @review = @business.reviews.create(review_params)
    @review.user_id = current_user.id
    @review.reviewer = current_user.first_name + ' ' + current_user.last_name
    if @review.save
        redirect_to business_path(@business)
        flash[:notice] = 'Review posted!'
    else
        redirect_to business_path(@business)
        flash[:danger] = 'Your review has an error. Please double check!'
    end
  end

  def edit
    @review = @business.reviews.find(params[:id])
  end

  def update
    @review = @business.reviews.find(params[:id])
    if @review.update(params[review_params])
        redirect_to businesses_path(@business)
        flash[:notice] = 'Review updated!'
    else
        render :action => 'edit'
    end
  end

  def destroy
    @review = @business.reviews.find(params[:id])
    @review.destroy
    redirect_to business_path(@business)
    flash[:notice] = "Review deleted."
  end

  private

  def load_business
    @business = Business.find(params[:business_id])
  end

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

reviews/_form.html.erb的代码:

Code for `reviews/_form.html.erb:

<%= simple_form_for([@business, @business.reviews.build]) do |f| %>
  <%= f.error_notification %>
  <p>
    <%= f.input :review %>
  </p>
  <p>
    <%= f.input :rating, collection: 1..10 %>
  </p>
  <p>
    <%= f.submit :class => 'btn btn-primary' %>
  </p>
<% end %>

评论在business#show视图中作为部分呈现. `reviews/_review.html.erb的代码:

The reviews are rendered in the business#show view as a partial. Code for `reviews/_review.html.erb:

<% if !review.user_id.nil? %>
  <div class="well">
    <p>
      <strong>Reviewer:</strong>
      <%= review.reviewer %>
    </p>
    <p>
      <strong>Review:</strong>
      <%= review.review %>
    </p>
    <p>
      <strong>Rating:</strong>
      <%= review.rating %>
    </p>
    <span class = "timestamp">
      posted <%= time_ago_in_words(review.created_at) %> ago.
    </span>
    <% if can? :update, review %>
      <span class = "timestamp">
        <%= link_to "Edit", [:edit, review.business, review], class: 'btn btn-small' %>|
        <%= link_to "Delete", [review.business, review], method: :delete,
                   data: { confirm: 'Are you sure?' } %>
      </span>
    <% end %>
  </div>
<% end %>

reviews/edit.html.erb的代码:

<h1>Edit Review</h1>

<%= render 'form', review: @review %>

<button type="button" class="btn btn-default"><%= link_to 'Back', businesses_path %></button>

奇怪的是,当我单击_review.html.erb中的编辑"链接时,生成的URL似乎是正确的,例如,我得到了http://localhost:3000/businesses/10/reviews/82/edit.但是,_form.html.erb是空的,我希望它使用当前数据进行填充,以供审核#82.此外,当我单击创建评论"按钮时,它会创建一个新评论,并且不会编辑评论#82.

The weird thing is, when I click on the "Edit" link in _review.html.erb, the URL that's generated appears to be correct, for example I get http://localhost:3000/businesses/10/reviews/82/edit. However, the _form.html.erb is empty where I would expect it to be populated with the current data for review #82. Furthermore, when I click the "Create Review" button, it creates a new review and doesn't edit review #82.

这是我单击编辑"以查看现有评论后的服务器日志:

Here's the server logs after I click "Edit" for an existing review:

Started GET "/businesses/3/reviews/81/edit" for 127.0.0.1 at 2014-08-28 19:18:58 -0500
Processing by ReviewsController#edit as HTML
  Parameters: {"business_id"=>"3", "id"=>"81"}
  User Load (0.8ms)  SELECT  "users".* FROM "users"  WHERE "users"."id" = 8  ORDER BY "users"."id" ASC LIMIT 1
  Review Load (6.9ms)  SELECT  "reviews".* FROM "reviews"  WHERE "reviews"."id" = $1 LIMIT 1  [["id", 81]]
  Business Load (0.5ms)  SELECT  "businesses".* FROM "businesses"  WHERE "businesses"."id" = $1 LIMIT 1  [["id", 3]]
  Review Load (27.4ms)  SELECT  "reviews".* FROM "reviews"  WHERE "reviews"."business_id" = $1 AND "reviews"."id" = $2 LIMIT 1  [["business_id", 3], ["id", 81]]
  Rendered reviews/_form.html.erb (107.0ms)
  Rendered reviews/edit.html.erb within layouts/application (143.4ms)
Completed 200 OK in 967ms (Views: 669.2ms | ActiveRecord: 35.6ms)


Started POST "/businesses/3/reviews" for 127.0.0.1 at 2014-08-28 19:19:23 -0500
Processing by ReviewsController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"<redacted>", "review"=>{"review"=>"Edit review #81.", "rating"=>"1"}, "commit"=>"Create Review", "business_id"=>"3"}
  User Load (0.8ms)  SELECT  "users".* FROM "users"  WHERE "users"."id" = 8  ORDER BY "users"."id" ASC LIMIT 1
  Business Load (0.6ms)  SELECT  "businesses".* FROM "businesses"  WHERE "businesses"."id" = $1 LIMIT 1  [["id", 3]]
    (28.9ms)  BEGIN
  SQL (132.9ms)  INSERT INTO "reviews" ("business_id", "created_at", "rating", "review", "updated_at") VALUES ($1, $2, $3, $4, $5) RETURNING "id"  [["business_id", 3], ["created_at", "2014-08-29 00:19:23.470750"], ["rating", 1], ["review", "Edit review #81."], ["updated_at", "2014-08-29 00:19:23.470750"]]
    (39.7ms)  COMMIT
    (0.3ms)  BEGIN
  SQL (0.9ms)  UPDATE "reviews" SET "reviewer" = $1, "updated_at" = $2, "user_id" = $3 WHERE "reviews"."id" = 83  [["reviewer", "<redacted>"], ["updated_at", "2014-08-29 00:19:23.692880"], ["user_id", 8]]
    (17.5ms)  COMMIT
Redirected to http://localhost:3000/businesses/3
Completed 302 Found in 553ms (ActiveRecord: 221.6ms)


Started GET "/businesses/3" for 127.0.0.1 at 2014-08-28 19:19:23 -0500
Processing by BusinessesController#show as HTML
  Parameters: {"id"=>"3"}
  User Load (0.7ms)  SELECT  "users".* FROM "users"  WHERE "users"."id" = 8  ORDER BY "users"."id" ASC LIMIT 1
  Business Load (0.5ms)  SELECT  "businesses".* FROM "businesses"  WHERE "businesses"."id" = $1 LIMIT 1  [["id", 3]]
    (0.5ms)  SELECT AVG("reviews"."rating") AS avg_id FROM "reviews"  WHERE "reviews"."business_id" = $1  [["business_id", 3]]
  Rendered reviews/_form.html.erb (5.7ms)
  Review Load (0.6ms)  SELECT "reviews".* FROM "reviews"  WHERE "reviews"."business_id" = $1  ORDER BY "reviews"."id" DESC  [["business_id", 3]]
  Rendered reviews/_review.html.erb (58.1ms)
  Rendered businesses/show.html.erb within layouts/application (173.5ms)
  Rendered users/_avatar.html.haml (13.1ms)
  Rendered layouts/_navigation.html.haml (30.9ms)
  Rendered layouts/_messages.html.haml (1.5ms)
  Rendered layouts/_footer.html.haml (16.5ms)
  Rendered layouts/_analytics.html.haml (0.6ms)
  Rendered layouts/_javascripts.html.haml (0.5ms)
Completed 200 OK in 421ms (Views: 391.5ms | ActiveRecord: 2.3ms)

很明显,服务器日志中的第二个操作是"Started POST ...",这是不正确的.在讨论过程中,我还可以提供从rake routes:

It's clear that the second action in the server log is "Started POST..." which isn't correct. While I'm at it, I may as well provide the relevant routes from rake routes:

business_reviews     GET      /businesses/:business_id/reviews(.:format)          reviews#index
                     POST     /businesses/:business_id/reviews(.:format)          reviews#create
new_business_review  GET      /businesses/:business_id/reviews/new(.:format)      reviews#new
edit_business_review GET      /businesses/:business_id/reviews/:id/edit(.:format) reviews#edit
business_review      GET      /businesses/:business_id/reviews/:id(.:format)      reviews#show
                     PATCH    /businesses/:business_id/reviews/:id(.:format)      reviews#update
                     PUT      /businesses/:business_id/reviews/:id(.:format)      reviews#update
                     DELETE   /businesses/:business_id/reviews/:id(.:format)      reviews#destroy

我已经尝试实现在这里可以找到的所有答案,但无济于事.我发现最接近我确切问题的那个是这个问题,但这也没有帮助:

I've already tried implementing every answer I could find on here, but to no avail. The closest one I've found to being almost my exact problem was this one, but it didn't help either: Rails: Use same partial for creating and editing nested items

非常感谢.

推荐答案

根据控制台中的输出,在更新stmt之前您已获得一个sql插入stmt.表单中的代码会导致这种情况. @business.reviews.build即使在编辑时也会创建新的审阅对象.

According to your output in console, you've got a sql insert stmt before update stmt. Your code in the form cause it. @business.reviews.build will create new review object even when edit.

将您的form_for更新为:

Update your form_for to:

<%= simple_form_for([@business, @review]) do |f| %>

而不是@business.reviews.build.您应该在控制器而不是视图中创建对象.

Instead of @business.reviews.build. You should create objects in controller instead of view.

因此,您可能还需要在新操作中重新审核对象.

So you may need to new review objects in your new action too.

  def new
     @review = @business.reviews.build
  end


我还有更多建议可简化您的代码,使事情变得更容易.


I have some more suggestions for you to simplify your code that could make things easier.

使用评论ID而不是通过业务查找评论.
例如编辑和更新中的代码,您可以:

Use review id to find review, instead of through business.
Such as code in edit and update, you could:

  def edit
    @review = Reviews.find(params[:id])
  end

  def update
    @review = Reviews.find(params[:id])
    ...
  end

这篇关于Rails 4 _form部分创建新记录,但不会编辑当前记录的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆