-1

I checked various solutions that are available, but none seem to address the issue that I am having with my project. I am trying to allow the user to create reviews through the EmployerReview model for the employer. When I pass the employer_id to the form_for in the employer_reviews_controller it claims that it cannot find an employer without an ID. The id is being passed with the @employer instance variable. I don't get why it's not working. Lastly, I am using friendly_id, and it shows at the end of the new employer review address employer_reviews/new.bryers. How can I stop this error from occurring?

schema

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

review form

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

UPDATE 1: I'm receiving the error below when I use both @employer_review and @employer in the simple_form.

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)
Cole Phiper
  • 349
  • 1
  • 13

1 Answers1

3

Your employers and employer_reviews resources are not nested. It means employer_id param in your EmployerReviewsController is nil (if it is not set explicitly in query string). Calling set_employer filter has no effect and @employer instance variable is nil. That's why simple_form cannot find that employer (without id).

You either have to turn employer_reviews to nested resource of employers, or remove @employer variable from EmployerReviewsController and use simple_form solely for @employer_review.

Ilya Konyukhov
  • 2,666
  • 1
  • 12
  • 21
  • Controllers should be separate for sure. Currently your controllers are ok. Just change routing. – Ilya Konyukhov Oct 24 '18 at 01:14
  • I tried your approach and made some progress. The issue that I'm having now, is the the validation is showing blank and returning back to the new action. Which probably means one of the model ids are not saving to the form before insertion. I tried to create the record inside of the console and it worked without issue. The employer_id is not <%= link_to "Review Company", new_employer_employer_review_path(@employer), class: 'bttn-bordered bttn-md bttn-royal' %> is not storing the employer_id. What can I do to get the value to store before the form commits? – Cole Phiper Oct 24 '18 at 02:14
  • I removed the @employer variable from the form as you asked. Now its just <%= simple_form_for(@employer_review) %> What do I do next? – Cole Phiper Oct 24 '18 at 02:16
  • For the employer_review migration. Its set to t.references :user and t.references :employer. Both should be available by default to the form. That's most likely why its not working correctly. I need to get a reference id from employers. – Cole Phiper Oct 24 '18 at 02:26
  • Let's go to [chat](https://chat.stackoverflow.com/rooms/182392/room-for-ilya-konyukhov-and-cole-phiper) – Ilya Konyukhov Oct 24 '18 at 03:04