Sabrina
Sabrina

Reputation: 369

Rails does not create associated model

I created a form where a user can create a profile. In the form the user can select multiple companies. A profile has many companies through a join-table named profile_companies. My code does create a new profile, but it does not create the association. Meaning that when I hit in the console: Profile.last.companies it returns an empty array. When I check the params before a profile is created, it does show me a full array for company_ids. So it looks like it cannot pass these values and create the association. Does anyone have an idea where the error is?

Here is my Profile model:

class Profile < ApplicationRecord
  belongs_to :user
  has_many :profile_companies
  has_many :companies, through: :profile_companies

  STATUSES = ["currently looking for a job", "employed but open for a new challenge"]
  validates :status, inclusion: {in: STATUSES}
end

here is my company model:

class Company < ApplicationRecord
  has_many :vacancies
  has_many :profile_companies
  has_many :profiles, through: :profile_companies
end

here is my profiles controller:

class ProfilesController < ApplicationController
  def new
    @profile = Profile.new
  end
  def create
    @profile = Profile.new(params_profile)

    if @profile.save
      redirect_to profile_path
    else
      render :new
    end
  end

  private

  def params_profile
    params.require(:profile).permit(:status, :name, :content, :company_ids)
  end

end

And here is my pry to show the params handed to the controller:

[1] pry(#<ProfilesController>)> params[:profile] => <ActionController::Parameters {"name"=>"test 4", "status"=>"employed but open for a new challenge", "company_ids"=>["", "31", "34"], "content"=>"test 4"} permitted: false>

And here are my Logs:

Started POST "/profiles" for ::1 at 2019-08-05 22:54:36 +0200
Processing by ProfilesController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"bmmqCdtWvTcDjlbR6yGrdZTGj+t3O2NMwNKanY5qP84eCSsCuBVF4SdzDkQ+0YOe5q+CapWx5NLaftunZ+ANSg==", "profile"=>{"name"=>"test 4", "status"=>"employed but open for a new challenge", "company_ids"=>["", "17", "31", "32"], "content"=>"rrr"}, "commit"=>"Save your profile"}
  User Load (0.3ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2  [["id", 16], ["LIMIT", 1]]
Unpermitted parameter: :company_ids
   (0.1ms)  BEGIN
   (0.1ms)  ROLLBACK
  Rendering profiles/new.html.erb within layouts/application
  Company Load (2.6ms)  SELECT "companies".* FROM "companies"
  CACHE Company Load (0.0ms)  SELECT "companies".* FROM "companies"
  CACHE Company Load (0.0ms)  SELECT "companies".* FROM "companies"
  Rendered profiles/new.html.erb within layouts/application (29.2ms)
  Rendered shared/_navbar.html.erb (1.4ms)
  Rendered shared/_flashes.html.erb (0.4ms)
Completed 200 OK in 178ms (Views: 170.6ms | ActiveRecord: 3.2ms)

Upvotes: 0

Views: 319

Answers (1)

jvillian
jvillian

Reputation: 20263

A couple of things. First, as you can see from the Unpermitted parameter: :company_ids message:

Started POST "/profiles" for ::1 at 2019-08-05 22:54:36 +0200
Processing by ProfilesController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"bmmqCdtWvTcDjlbR6yGrdZTGj+t3O2NMwNKanY5qP84eCSsCuBVF4SdzDkQ+0YOe5q+CapWx5NLaftunZ+ANSg==", "profile"=>{"name"=>"test 4", "status"=>"employed but open for a new challenge", "company_ids"=>["", "17", "31", "32"], "content"=>"rrr"}, "commit"=>"Save your profile"}
  User Load (0.3ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2  [["id", 16], ["LIMIT", 1]]
Unpermitted parameter: :company_ids
   (0.1ms)  BEGIN
   (0.1ms)  ROLLBACK
  Rendering profiles/new.html.erb within layouts/application
  Company Load (2.6ms)  SELECT "companies".* FROM "companies"
  CACHE Company Load (0.0ms)  SELECT "companies".* FROM "companies"
  CACHE Company Load (0.0ms)  SELECT "companies".* FROM "companies"
  Rendered profiles/new.html.erb within layouts/application (29.2ms)
  Rendered shared/_navbar.html.erb (1.4ms)
  Rendered shared/_flashes.html.erb (0.4ms)
Completed 200 OK in 178ms (Views: 170.6ms | ActiveRecord: 3.2ms)

...you are using permit incorrectly and company_ids, therefore, is not being permitted.

It should look something more like:

def params_profile
  params.require(:profile).permit(:status, :name, :content, company_ids: [])
end

...since company_ids is an array. Permitted arrays should go at the end of the permit list, see the docs for more information.

Second, your Profile model doesn't have a company_ids attribute. So, you may get an error when you do:

@profile = Profile.new(params_profile)

(TBH, I forget how smart (or not) rails is in this type of circumstance.) Which is a whole other thing you'll have to deal with.

Third, your Profile model includes belongs_to :user, but you never assign a user which is why your transaction is getting the ROLLBACK. In general, to see why you're getting a ROLLBACK, you can do something like:

if @profile.save!

...and the bang (!) will cause an error and provide an explanation.

To set the user_id, I would suggest you do something like:

@profile = current_user.build_profile(params_profile)

This assumes that User has_one :profile. See the docs for more information.

Upvotes: 1

Related Questions