【问题标题】:ActiveRecord::RecordNotFound (Couldn't find Employer without an ID) while using form Rails 5使用表单 Rails 5 时 ActiveRecord::RecordNotFound(找不到没有 ID 的雇主)
【发布时间】:2018-10-23 23:47:26
【问题描述】:

我检查了各种可用的解决方案,但似乎没有一个解决我在项目中遇到的问题。我试图允许用户通过EmployerReview 模型为雇主创建评论。当我将employer_id 传递给employer_reviews_controller 中的form_for 时,它声称找不到没有身份证的雇主。 id 与@employer 实例变量一起传递。我不明白为什么它不起作用。最后,我使用的是friendly_id,它显示在新雇主审核地址 employer_reviews/new.bryers 的末尾。如何阻止此错误的发生?

架构

create_table "employer_reviews", force: :cascade do |t|
    t.text "review_body"
    t.string "review_title"
    t.bigint "user_id"
    t.bigint "employer_id"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.index ["employer_id"], name: "index_employer_reviews_on_employer_id"
    t.index ["user_id"], name: "index_employer_reviews_on_user_id"
  end

employer_review.rb

class EmployerReview < ApplicationRecord
  belongs_to :employer
  belongs_to :user
end

user.rb

class User < ApplicationRecord
  has_many :employer_reviews, dependent: :destroy
end

employer.rb

class Employer < ApplicationRecord
  extend FriendlyId
  friendly_id :username, use: [:slugged, :finders]
  has_many :employer_reviews, dependent: :destroy
end

employers_controller.rb

class EmployersController < ApplicationController
  before_action :set_employer, only: [:show]

  def show
    impressionist(@employer)
  end


  private

  def set_employer
    @employer = Employer.find(params[:id])
  end
end

employer_reviews_controller.rb

class EmployerReviewsController < ApplicationController
  before_action :set_employer_review, only: [:show, :edit, :update, :destroy]
  before_action :set_employer
  before_action :authenticate_user!

  # GET /employer_reviews/1
  # GET /employer_reviews/1.json
  def show
  end

  # GET /employer_reviews/new
  def new
    @employer_review = EmployerReview.new
  end

  # GET /employer_reviews/1/edit
  def edit
  end

  # POST /employer_reviews
  # POST /employer_reviews.json
  def create
    @employer_review = EmployerReview.new(employer_review_params)
    @employer_review.user_id = current_user.id
    @employer_review.employer_id = @employer_review.id

    respond_to do |format|
      if @employer_review.save
        format.html {redirect_to @employer_review, notice: 'Employer review was successfully created.'}
        format.json {render :show, status: :created, location: @employer_review}
      else
        format.html {render :new}
        format.json {render json: @employer_review.errors, status: :unprocessable_entity}
      end
    end
  end

  # PATCH/PUT /employer_reviews/1
  # PATCH/PUT /employer_reviews/1.json
  def update
    respond_to do |format|
      if @employer_review.update(employer_review_params)
        format.html {redirect_to @employer_review, notice: 'Employer review was successfully updated.'}
        format.json {render :show, status: :ok, location: @employer_review}
      else
        format.html {render :edit}
        format.json {render json: @employer_review.errors, status: :unprocessable_entity}
      end
    end
  end

  # DELETE /employer_reviews/1
  # DELETE /employer_reviews/1.json
  def destroy
    @employer_review.destroy
    respond_to do |format|
      format.html {redirect_to employer_reviews_url, notice: 'Employer review was successfully destroyed.'}
      format.json {head :no_content}
    end
  end

  private

  # Use callbacks to share common setup or constraints between actions.
  def set_employer_review
    @employer_review = EmployerReview.find(params[:id])
  end

  def set_employer
    @employer = Employer.find(params[:employer_id])
  end

  # Never trust parameters from the scary internet, only allow the white list through.
  def employer_review_params
    params.require(:employer_review).permit([:review_title, :review_body])
  end
end

employer show.html.erb

<%= link_to 'Write a review', new_employer_review_path(@employer) %>

routes.rb

resources :employers
resources :employer_reviews

审核表

<%= simple_form_for([@employer, @employer_review]) do |f| %>
  <%= f.error_notification %>
  <div class="form-group">
    <label>Review Title</label>
    <%= f.input :review_title, class: 'form-control', placeholder: 'Add a review title' %>
  </div>
  <div class="form-group">
    <label>Tell us about your experience</label>
    <%= f.input :review_body, :as => :text, :input_html => { 'rows' => 5, 'cols' => 10 }, class: 'form-control', placeholder: 'Add a review title' %>
  </div>

  <div class="form-actions">
    <%= f.button :submit %>
  </div>
<% end %>

更新 1: 当我在 simple_form 中同时使用 @employer_review 和 @employer 时,我收到以下错误。

ActionView::Template::Error (undefined method `model_name' for nil:NilClass):
    1: <%= simple_form_for([@employer_review, @employer]) do |f| %>
    2:   <%= f.error_notification %>
    3:   <div class="form-group">
    4:     <label>Review Title</label>

app/views/employer_reviews/_form.html.erb:1:in `_app_views_employer_reviews__form_html_erb__154747394_155744960'
app/views/employer_reviews/new.html.erb:3:in `_app_views_employer_reviews_new_html_erb__376973310_155859880'
Processing by ExceptionHandler::ExceptionsController#show as HTML
  Parameters: {"employer_id"=>"test_employer"}
Completed 500 Internal Server Error in 404ms (ActiveRecord: 0.0ms)

【问题讨论】:

  • 我认为EmployerReviewsController#create 中的@employer_review.employer_id = @employer_review.id 是一个错误

标签: ruby-on-rails ruby activerecord ruby-on-rails-5 friendly-id


【解决方案1】:

您的 employersemployer_reviews 资源没有嵌套。这意味着您的EmployerReviewsController 中的employer_id 参数是nil(如果未在查询字符串中明确设置)。调用set_employer 过滤器无效,@employer 实例变量为nil。这就是为什么simple_form 找不到那个雇主(没有 id)。

您要么必须将 employer_reviewsemployers 转换为 nested resource,要么从 EmployerReviewsController 中删除 @employer 变量并将 simple_form 仅用于 @employer_review

【讨论】:

  • 控制器肯定是分开的。目前你的控制器没问题。只需更改路由即可。
  • 我尝试了您的方法并取得了一些进展。我现在遇到的问题是验证显示为空白并返回到新操作。这可能意味着其中一个模型 ID 在插入之前没有保存到表单中。我试图在控制台内创建记录,并且没有问题。雇主 ID 不是 没有存储雇主 ID。在表单提交之前,我可以做些什么来获取要存储的值?
  • 我按照您的要求从表单中删除了@employer 变量。现在它只是 我接下来要做什么?
  • 对于employer_review 迁移。它设置为 t.references :user 和 t.references :employer。默认情况下,两者都应该在表单中可用。这很可能是它无法正常工作的原因。我需要从雇主那里获得参考 ID。
  • 我们去chat
猜你喜欢
  • 2010-11-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多