ruby 具有多个到的嵌套属性

xuo3flqw  于 2022-11-04  发布在  Ruby
关注(0)|答案(1)|浏览(202)

当我从UI传递值时,我得到了不允许的参数。模型之间的关联是多对多。

class User < ApplicationRecord
    has_many :user_posts
    has_many :posts, through: :user_posts
end

class Post < ApplicationRecord
    has_many :user_posts
    has_many :users, through: :user_posts

    accepts_nested_attributes_for :user_posts
end

class UserPost < ApplicationRecord
  belongs_to :user
  belongs_to :post

  accepts_nested_attributes_for :user
end

电子邮件地址:

<%= form_with(model: post) do |form| %>
  <% if post.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(post.errors.count, "error") %> prohibited this post from being saved:</h2>

      <ul>
        <% post.errors.each do |error| %>
          <li><%= error.full_message %></li>
        <% end %>
      </ul>
    </div>
  <% end %>

  <div class="field">
    <%#= form.label :name %>
    <%#= form.text_field :name %>
  </div>

  <div class="field">
    <%= form.fields_for :user_posts do |f| %>
      <%= f.collection_select :user_id, User.all, :id, :username,  {include_blank: false, include_hidden: false }, {:multiple => true, :class=>""} %> 
    <% end %>
  </div>

  <div class="actions">
    <%= form.submit %>
  </div>
<% end %>

class PostsController < ApplicationController
  before_action :set_post, only: %i[ show edit update destroy ]

  # GET /posts or /posts.json
  def index
    @posts = Post.all
  end

  # GET /posts/1 or /posts/1.json
  def show
  end

  # GET /posts/new
  def new
    @post = Post.new
    @post.user_posts.build 
  end

  # GET /posts/1/edit
  def edit
  end

  # POST /posts or /posts.json
  def create
    @post = Post.new(post_params)
    respond_to do |format|
      if @post.save
        format.html { redirect_to @post, notice: "Post was successfully created." }
        format.json { render :show, status: :created, location: @post }
      else
        format.html { render :new, status: :unprocessable_entity }
        format.json { render json: @post.errors, status: :unprocessable_entity }
      end
    end
  end

  # PATCH/PUT /posts/1 or /posts/1.json
  def update
    respond_to do |format|
      if @post.update(post_params)
        format.html { redirect_to @post, notice: "Post was successfully updated." }
        format.json { render :show, status: :ok, location: @post }
      else
        format.html { render :edit, status: :unprocessable_entity }
        format.json { render json: @post.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /posts/1 or /posts/1.json
  def destroy
    @post.destroy
    respond_to do |format|
      format.html { redirect_to posts_url, notice: "Post was successfully destroyed." }
      format.json { head :no_content }
    end
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_post
      @post = Post.find(params[:id])
    end

    # Only allow a list of trusted parameters through.
    def post_params
      params.require(:post).permit(:username, user_posts_attributes: [:user_id])
    end
end

当我运行下面的行时,它给出了不允许的参数

@post = Post.new(post_params)
Unpermitted parameter: :user_id

结构描述

\d users
                                          Table "public.users"
   Column   |              Type              | Collation | Nullable |              Default              
------------+--------------------------------+-----------+----------+-----------------------------------
 id         | bigint                         |           | not null | nextval('users_id_seq'::regclass)
 username   | character varying              |           |          | 
 created_at | timestamp(6) without time zone |           | not null | 
 updated_at | timestamp(6) without time zone |           | not null | 

 \d posts
                                          Table "public.posts"
   Column   |              Type              | Collation | Nullable |              Default              
------------+--------------------------------+-----------+----------+-----------------------------------
 id         | bigint                         |           | not null | nextval('posts_id_seq'::regclass)
 name       | character varying              |           |          | 
 created_at | timestamp(6) without time zone |           | not null | 
 updated_at | timestamp(6) without time zone |           | not null | 

\d user_posts
                                          Table "public.user_posts"
   Column   |              Type              | Collation | Nullable |                Default                 
------------+--------------------------------+-----------+----------+----------------------------------------
 id         | bigint                         |           | not null | nextval('user_posts_id_seq'::regclass)
 user_id    | bigint                         |           | not null | 
 post_id    | bigint                         |           | not null | 
 created_at | timestamp(6) without time zone |           | not null | 
 updated_at | timestamp(6) without time zone |           | not null |

我是不是错过了什么重要的东西?任何帮助都是感激不尽的
导轨-6.1
Ruby-3.0

w8rqjzmb

w8rqjzmb1#

您不需要,甚至不想在这里使用巢状属性。
如果您只想关联现有记录,则只需对user_ids属性进行选择:

<%= form_with(model: post) do |form| %>  
  ...
  <div class="field">
    <%= form.label :user_ids, 'Select the users'  %>
    <%= f.collection_select :user_ids, User.all, :id, :username, { include_blank: false, include_hidden: false }, { multiple: true, class: ""} %> 
  </div>
  ...
<% end %>

这些setter和getter由has_many :users, through: :user_posts创建。
要将post[user_ids]参数作为数组列入白名单:

def post_params
  params.require(:post).permit(
    :foo, 
    :bar,
    :baz,
    user_ids: []
  )
end

正如您所看到的,您也不需要明确地处理连接表,因为user_ids=将为您完成所有工作。
仅当连接表实际包含必须由用户输入的附加数据时,才需要创建具有嵌套属性的连接表实体。

相关问题