Ruby on Rails:根据用户输入添加关联,多对多使用 :through、create 和 destroy 方法错误

Ruby on Rails: adding association based on user input, many to many using :through, create and destroy method errors

我正在尝试构建一个简单的项目管理应用程序,其中一个用户可以是多个项目的成员,一个项目可以是多个用户的成员。这种多对多关系在我的以下模型中表示:

#project model
class Project < ActiveRecord::Base
 has_many :memberships, dependent: :destroy
 has_many :users, :through => :memberships
 accepts_nested_attributes_for :memberships
end

#user model
class User < ActiveRecord::Base
 has_many :memberships, dependent: :destroy
 has_many :projects, :through => :memberships
 accepts_nested_attributes_for :memberships
end

#membership model (join table)
class Membership < ActiveRecord::Base
 belongs_to :project
 belongs_to :user
end

我试图让应用程序用户在创建项目时选择哪些注册用户是该项目的成员,因此使用项目的新表单我希望有下拉列表来选择成员用户。 我目前有以下

#projects_controller.rb
def create    
    @user = User.find_by_id(session[:user_id])
    @project = Project.new(project_params)
    @project.manager_id = @user.id   

    respond_to do |format|
      if @project.save && @project.memberships.create(:user => @user)
        format.html { redirect_to projects_path, notice: "Project #{@project.name} was successfully created." }
        format.json { render :show, status: :created, location: @project }
      else
        format.html { render :new }
        format.json { render json: @project.errors, status: :unprocessable_entity }
      end
    end
  end

def destroy
    @project.destroy 
    respond_to do |format|
      format.html { redirect_to projects_url, notice: "Project #{@project.name} was successfully deleted." }
      format.json { head :no_content }
    end
  end 

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

    # Never trust parameters from the scary internet, only allow the white list through.
    def project_params
      params.require(:project).permit(:name, :description, memberships_attributes: [:user_id])
    end    
end

#index.html.erb for projects
<%= form_for(@project) do |f| %>
  <% if @project.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(@project.errors.count, "error") %> prohibited this project from being saved:</h2>

      <ul>
      <% @project.errors.full_messages.each do |message| %>
        <li><%= message %></li>
      <% end %>
      </ul>
    </div>
  <% end %>  

  <div class="field">
    <%= f.label :name %><br>
    <%= f.text_field :name %>
  </div>
  <div class="field">
    <%= f.label :description %><br>
    <%= f.text_area :description %>
  </div> 

  <%= f.fields_for :memberships do |m| %>
  <div class="field">
    <%= m.label :user_id %><br>
    <%= m.collection_select :user_id, User.all, :id, :username %>
  </div> 
  <% end %>

  <div class="actions">
    <%= f.submit %>
  </div>


<% end %>

此代码在成员资格中添加关联 table 但它需要当前登录的用户,我希望它与用户从表单中选择的每个用户创建关联。还有我的销毁方法 returns 错误和我的表单 collection_select 没有显示。任何帮助将不胜感激。

编辑: 我所做的更改:

#new.html.erb
<%= fields_for :memberships do |m| %>
  <div class="field">  
    <%= m.label "Add Member" %><br> 
    <%= collection_select :users, :user_id, User.all, :id, :username %>
  </div> 
  <% end %>

#projects_controller.rb
collection_ids = params[:users]
    collection_ids.each do |user_id|
    user = User.find(user_id)
    @project.memberships.create(:user => user)

我遇到错误 "Couldn't find all Users with 'id': (user_id, 3) (found 1 results, but was looking for 2)" 好像这种做法只能让用户添加一个成员怎么修改表单添加多个?

所以我猜你正在尝试为一个项目创建多个成员资格,当前用户将决定哪些用户应该成为新创建项目的成员? 在那种情况下

@project.memberships.create(:user => @user) 

不会工作,因为它只为 current_user 生成会员资格。 因此,当您将 user_ids 的集合传递给 project_controller 的创建方法时,您应该遍历这些 ID 并获取这些用户,然后 为他们每个人创建一个新的会员资格。 像

collection_ids.each do |user_id| # assuming collection_ids is an array
  user = User.find(user_id)
  @project.memberships.create(:user => user)
end

您似乎在 collection_select 中遗漏了对象参数,我认为应该是:

 <%= m.collection_select :users, :user_id, User.all, :id, :username %>

并且您仅在调用 @project.memberships.create(:user => @user) 时为当前用户创建成员资格,而选择 user_ids 将在您将对象参数添加到表单后 params[:users] 中。