首页 > 解决方案 > rails,相关字段在提交时未保存

问题描述

我正在尝试保存分配给它的受让人项目。所有字段都被保存,除了“被分配人”字段,它是一个关联字段。

# app/models/project.rb
class Project < ApplicationRecord
  belongs_to :owner, class_name: 'User'
  has_many   :assignments, dependent: :destroy
  has_many   :assignees, through: :assignments, source: :user
  has_and_belongs_to_many :adversaries, -> { adversaries }, class_name: 'Contact'
  has_and_belongs_to_many :clients,     -> { clients },     class_name: 'Contact'
end
# app/models/assignment.rb
class Assignment < ApplicationRecord
  belongs_to :project
  belongs_to :user
end
# app/models/user.rb
class User < ApplicationRecord
  has_many   :owned_projects, foreign_key: :owner_id, class_name: 'Project', dependent: :destroy
  has_many   :activities
  has_many   :deadlines
  has_many   :assignments, dependent: :destroy
  has_many   :projects, through: :assignments
end
# app/models/contact.rb
class Contact < ApplicationRecord
  has_and_belongs_to_many :projects

  scope :get_role,    -> (str) { includes(:role).where("contact_roles.label = '#{str}'").references(:contact_roles) }
  scope :clients,     ->       { get_role('client') }
  scope :adversaries, ->       { get_role('adversary') }
end
# app/controllers/projects_controller.rb
class ProjectsController < ApplicationController
  def create
    @project = Project.new(project_params)

    respond_to do |format|
      if @project.save
        format.html { redirect_to @project, notice: "Project was successfully created." }
      else
        format.html { render :new, status: :unprocessable_entity }
      end
    end
  end
  
  private
    def project_params
      params.require(:project).permit(:label, :reference, :status, :description, :owner_id, :project_category_id, assignee: [:id])
    end
end
# app/views/projects/_form.html.erb
<%= form_with(model: project, local: true, class: 'box') do |form| %>
  <%= form.label :assignee_id %>
  <%= form.collection_select(:assignee_id, User.all.order(role: :desc, last_name: :asc), :id, :friendly_name, { include_hidden: false }, { size: 6, required: true, multiple: true, id: :project_assignee_id }) %>
<% end %>

这是相关的终端输出:

Started POST "/en/projects" for 127.0.0.1 at 2021-06-19 15:43:53 +0200
Processing by ProjectsController#create as HTML
  Parameters: {"utf8"=>"✓&quot;, "authenticity_token"=>"r3ayqmMUFEh93KKhmqJ1VEYeF90QxpFOZiHwgZ0WEeqZM/DEQsI9tpJP8CwFqH0xBF4TZlQ5++Q6o6wt2hRkRA==", "project"=>{"label"=>"asdasdasd", "owner_id"=>"3", "project_category_id"=>"1", "description"=>"asdasdasd", "status"=>"active", "reference"=>"asdasd", "assignee_id"=>["3", "2"]}, "commit"=>"Créer projet", "locale"=>"en"}
  User Load (0.1ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 4], ["LIMIT", 1]]
Unpermitted parameter: :assignee_id
   (0.0ms)  begin transaction
  User Load (0.1ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 3], ["LIMIT", 1]]
  SQL (0.4ms)  INSERT INTO "projects" ("label", "reference", "status", "description", "owner_id", "project_category_id", "created_at", "updated_at") VALUES (?, ?, ?, ?, ?, ?, ?, ?)  [["label", "asdasdasd"], ["reference", "asdasd"], ["status", 1], ["description", "asdasdasd"], ["owner_id", 3], ["project_category_id", 1], ["created_at", "2021-06-19 13:43:53.565072"], ["updated_at", "2021-06-19 13:43:53.565072"]]
   (0.3ms)  commit transaction
Redirected to http://localhost:3000/en/projects/289
Completed 302 Found in 8ms (ActiveRecord: 1.2ms)

未经许可的参数也很神秘,因为我已经尝试了我在网上找到的所有变体......

关于如何进行的任何想法?甚至只是指向有关该问题的清晰教程的链接?

编辑:

同样的问题,但可能更清晰的代码:

# app/views/projects/_form.html.erb
<%= form.label :assignees %>
<%= form.collection_select(:assignees, User.lawyers.order(role: :desc, last_name: :asc), :id, :friendly_name, { include_hidden: false }, { size: 6, required: true, multiple: true, id: :project_assignees }) %>
# app/controllers/projects_controller.rb
    def project_params
      params.require(:project).permit(:label, :reference, :status, :description, :owner_id, :project_category_id, assignees: [:id])
    end

这现在清除了未经允许的参数问题,但“受让人”字段仍未保存:

Started POST "/en/projects" for 127.0.0.1 at 2021-06-19 16:09:40 +0200
Processing by ProjectsController#create as HTML
  Parameters: {"utf8"=>"✓&quot;, "authenticity_token"=>"XHqUoeH4o6XTOTlRPkNebIIhmJw6dgitxTnBtydUfvCvbCVNzNJx9dmMwA1UpSZn3FdVDjeJ21fNhtUP9YA89w==", "project"=>{"label"=>"aasdf", "owner_id"=>"3", "project_category_id"=>"1", "description"=>"asdasd", "status"=>"active", "reference"=>"", "assignees"=>["9"]}, "commit"=>"Créer projet", "locale"=>"en"}
  User Load (0.1ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 4], ["LIMIT", 1]]
   (0.0ms)  begin transaction
  User Load (0.2ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 3], ["LIMIT", 1]]
  SQL (0.7ms)  INSERT INTO "projects" ("label", "reference", "status", "description", "owner_id", "project_category_id", "created_at", "updated_at") VALUES (?, ?, ?, ?, ?, ?, ?, ?)  [["label", "aasdf"], ["reference", ""], ["status", 1], ["description", "asdasd"], ["owner_id", 3], ["project_category_id", 1], ["created_at", "2021-06-19 14:09:40.963949"], ["updated_at", "2021-06-19 14:09:40.963949"]]
   (0.3ms)  commit transaction
Redirected to http://localhost:3000/en/projects/296
Completed 302 Found in 10ms (ActiveRecord: 1.4ms)

标签: ruby-on-rails

解决方案


您想使用生成assignee_ids=的设置器:has_many

<%= 
form.collection_select(
   :assignee_ids,
   User.lawyers.order(role: :desc, last_name: :asc), # query should be moved to controller
   :id, 
   :friendly_name, 
   { include_hidden: false }, 
   { size: 6, required: true, multiple: true, id: :project_assignees }
) 
%>
def project_params
  params.require(:project)
        .permit(
          :label, :reference, :status, :description, 
          :owner_id, :project_category_id, 
          assignee_ids: [] # permits an array of ids
        )
end

请注意,此处不需要嵌套属性,这是一个非常常见的误解。如果您只想分配一个关系并隐式创建/销毁连接行,那么您只需要使用_idssetter/getter,Rails 会为您处理它。

仅当您需要使用描述两个实体之间关系的附加属性显式创建连接行时,才需要嵌套属性。例如,如果您需要将“角色”字段添加到描述项目中受让人角色的分配中。


推荐阅读