Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

So as of this question I had a has_and_belongs_to_many working with a join table between people and occasions.

I had it working (with help from the lovely SO wizard that helped me), but said wizard recommended that a has_many through: :association might work better for my purposes. Unfortunately, it definitely does, but in shifting over I seem to have broken it.

My schema.rb now reads like this, using gifts to connect people and occasions:

  create_table "gifts", force: :cascade do |t|
    t.string "name"
    t.decimal "price", precision: 8, scale: 2
    t.string "store"
    t.text "notes"
    t.boolean "purchased", default: false
    t.integer "user_id"
    t.integer "person_id", null: false
    t.integer "occasion_id", null: false
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.index ["occasion_id"], name: "index_gifts_on_occasion_id"
    t.index ["person_id"], name: "index_gifts_on_person_id"
    t.index ["user_id"], name: "index_gifts_on_user_id"
  end

  create_table "occasions", force: :cascade do |t|
    t.integer "person_id"
    t.integer "user_id"
    t.string "name"
    t.date "date"
    t.text "notes"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.index ["user_id"], name: "index_occasions_on_user_id"
  end

  create_table "people", force: :cascade do |t|
    t.string "relationship"
    t.string "first_name"
    t.string "middle_name"
    t.string "last_name"
    t.date "birthday"
    t.date "anniversary"
    t.date "other"
    t.string "other_date_name"
    t.text "notes"
    t.integer "user_id"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.string "group"
    t.integer "occasions_id"
    t.index ["user_id"], name: "index_people_on_user_id"
  end

I updated the models accordingly:

class Gift < ApplicationRecord
  # Validations
  validates_presence_of :person, :occasion, :user

  # Relations
  belongs_to :user
  belongs_to :occasion
  belongs_to :person
end

class Occasion < ApplicationRecord
  # Relations
  has_many :gifts
  has_many :people, through: :gifts
  belongs_to :user
end

class Person < ApplicationRecord
  # Relations
  belongs_to :user
  has_many :gifts
  has_many :occasions, through: :gifts

  def full_name
    "#{last_name}, #{first_name}"
  end
end

My params would (I'm guessing) be where a potential issue might lie:

def occasion_params
  params.require(:occasion).permit(:user_id, :name, :date, :notes, gift_ids: [])
end

and

def person_params
  params.require(:person).permit(:relationship, :first_name, :middle_name, :last_name, :birthday, :anniversary, :other, :other_date_name, :notes, :group, :user_id, gift_ids: [])
end

This is taking place on my occasions#index page:

  def index
    @occasions = Occasion.where(user_id: current_user.id).order("date ASC")
    @occasion = Occasion.new
    @gifts = Gift.where(user_id: current_user.id)
  end

And the occasion#create method looks like this:

  def create
    @occasion = Occasion.new(occasion_params)
    @occasion.user_id = current_user.id

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

Finally, here's the server log when I attempt to add a new occasion:

Started POST "/occasions" for 127.0.0.1 at 2018-10-14 11:03:42 -0700
Processing by OccasionsController#create as HTML
  Parameters: {"utf8"=>"?", "authenticity_token"=>"0CaXl8VdEMITUv7/2ouzrF6ArOpe1Wh7QJS3pno8AdAeL834G9rFebfixgsXU7sQ7/HjzGh17yYWhtIGbN18jQ==", "occasion"=>{"name"=>"Here's a Test Occasion", "date"=>"2018-10-31", "notes"=>"", "person_ids"=>["", "22", "24", "25", "26", "27"]}, "commit"=>"Create Occasion"}
  User Load (4.6ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? ORDER BY "users"."id" ASC LIMIT ?  [["id", 1], ["LIMIT", 1]]
  ? /Users/lizbayardelle/.rvm/gems/ruby-2.5.0/gems/activerecord-5.2.1/lib/active_record/log_subscriber.rb:98
Unpermitted parameter: :person_ids
   (0.2ms)  begin transaction
  ? app/controllers/occasions_controller.rb:35
  User Load (0.3ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 1], ["LIMIT", 1]]
  ? app/controllers/occasions_controller.rb:35
  Occasion Create (6.8ms)  INSERT INTO "occasions" ("user_id", "name", "date", "notes", "created_at", "updated_at") VALUES (?, ?, ?, ?, ?, ?)  [["user_id", 1], ["name", "Here's a Test Occasion"], ["date", "2018-10-31"], ["notes", ""], ["created_at", "2018-10-14 18:03:43.003716"], ["updated_at", "2018-10-14 18:03:43.003716"]]
  ? app/controllers/occasions_controller.rb:35
   (2.3ms)  commit transaction
  ? app/controllers/occasions_controller.rb:35
Redirected to http://localhost:3000/occasions
Completed 302 Found in 131ms (ActiveRecord: 14.2ms)

Can anyone with an eye for :associations help me troubleshoot?

UPDATED SERVER LOG

Started POST "/occasions" for 127.0.0.1 at 2018-10-14 14:33:16 -0700
Processing by OccasionsController#create as HTML
  Parameters: {"utf8"=>"?", "authenticity_token"=>"9z9jHd5I9Q+oiRVSxC8T2MpP/X99wcGt8/USh7oEdOc5NjlyAM8gtAw5LaYJ9xtkez6yWUthRvCl53cnrOUJug==", "occasion"=>{"name"=>"Test Occasion", "date"=>"2018-10-01", "notes"=>"", "person_ids"=>["", "22", "24", "25"]}, "commit"=>"Create Occasion"}
  User Load (3.9ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? ORDER BY "users"."id" ASC LIMIT ?  [["id", 1], ["LIMIT", 1]]
  ? /Users/lizbayardelle/.rvm/gems/ruby-2.5.0/gems/activerecord-5.2.1/lib/active_record/log_subscriber.rb:98
  Person Load (1.6ms)  SELECT "people".* FROM "people" WHERE "people"."id" IN (?, ?, ?)  [["id", 22], ["id", 24], ["id", 25]]
  ? app/controllers/occasions_controller.rb:31
   (0.2ms)  begin transaction
  ? app/controllers/occasions_controller.rb:35
  User Load (1.1ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 1], ["LIMIT", 1]]
  ? app/controllers/occasions_controller.rb:35
  CACHE User Load (0.0ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 1], ["LIMIT", 1]]
  ? app/controllers/occasions_controller.rb:35
  CACHE User Load (0.1ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 1], ["LIMIT", 1]]
  ? app/controllers/occasions_controller.rb:35
  CACHE User Load (0.0ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 1], ["LIMIT", 1]]
  ? app/controllers/occasions_controller.rb:35
   (0.1ms)  rollback transaction
  ? app/controllers/occasions_controller.rb:35
Completed 422 Unprocessable Entity in 87ms (ActiveRecord: 6.9ms)



ActiveRecord::RecordInvalid - Validation failed: Gifts is invalid:
  app/controllers/occasions_controller.rb:35:in `block in create'
  app/controllers/occasions_controller.rb:34:in `create'

Started POST "/__better_errors/a57498aade504932/variables" for 127.0.0.1 at 2018-10-14 14:33:17 -0700
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
870 views
Welcome To Ask or Share your Answers For Others

1 Answer

Unpermitted parameter: :person_ids

You are very close! You just need to change gift_ids[] to person_ids[] in occasion_params

def occasion_params
  params.require(:occasion).permit(:user_id, :name, :date, :notes, person_ids: [])
end

Also, you shall encounter same error when you create a Person instance as you have gift_ids[] in person_params as well. Change it to occasion_ids[]

def person_params
  params.require(:person).permit(:relationship, :first_name, :middle_name, :last_name, :birthday, :anniversary, :other, :other_date_name, :notes, :group, :user_id, occasion_ids: [])
end

Update:

ActiveRecord::RecordInvalid - Validation failed: Gifts is invalid

This error is due the Gift instance getting created with a nil user_id. You can add optional: true to the association to counter the error add a callback for Gift instance to create with a correct entry for user_id

#gift.rb
class Gift < ApplicationRecord
  # Validations
  validates_presence_of :person, :occasion

  # Relations
  belongs_to :user, optional: true
  belongs_to :occasion
  belongs_to :person

  after_create :set_user_id

  private
  def set_user_id
    self.update_column(:user_id, self.occasion.user_id)
  end
end

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...