【问题标题】:not able to save data in join table for has_many_through associations in rails无法在 rails 中的 has_many_through 关联的连接表中保存数据
【发布时间】:2013-06-27 17:22:47
【问题描述】:

我有 user、team 和 team_user 模型。由于 has_many 通过用户和团队之间的关联,team_use 正在加入模型。 team_user 具有来自用户和团队表的 user_id 和 team_id。团队有名称和 team_lead_id(这将是用户表中的用户)。

问题:

当我创建新团队时,我想将用户和团队负责人添加到团队中。一个团队可以有多个用户,但只有一个团队负责人。在创建 team 时, user_id 和 team_id 应该保存在 team_user 表中。但这并没有发生。我尝试在 team_controller.rb 中使用以下代码:

def create
    @team = Team.new(params[:team])
      @user_team = TeamUser.new( { user_id: '@user.id', team_id: 'params[:team_id]' } )
      if @team.save
        flash[:notice] = 'Team has been created'
        redirect_to teams_path
      else
        flash[:alert] = 'Team not created'
        redirect_to teams_path
      end
  end

使用 TeamUser.new( { user_id: '@user.id', team_id: 'params[:team_id]' } ) ,我尝试在 team_user 表中创建用户和团队条目,但失败了。

代码如下。

teams_controlller.rb

class TeamsController < ApplicationController
  before_filter :authorize_admin!

  def index
    @teams = Team.all
    @team = Team.new
  end

  def new
    @team = Team.new
  end

  def create
    @team = Team.new(params[:team])
      @user_team = TeamUser.new( { user_id: '@user.id', team_id: 'params[:team_id]' } )
      if @team.save
        flash[:notice] = 'Team has been created'
        redirect_to teams_path
      else
        flash[:alert] = 'Team not created'
        redirect_to teams_path
      end
  end

  def show
    @team = Team.find(params[:id])
  end

  def edit
    @team = Team.find(params[:id])
  end

  def update
    @team = Team.find(params[:id])
      if @team.update_attributes(params[:team])
        flash.notice = "Team #{@team.name} has been updated"
        redirect_to team_path
      else
        render 'edit'
      end
  end

  def destroy
    @team = Team.find(params[:id])
    @team.destroy
    redirect_to action:  'index'
  end

end

team.rb

class User < ActiveRecord::Base
 has_many :roles,  through: :role_users
 has_many :role_users
 has_many :leaves
 serialize :role
 has_many :teams, through: :team_users
 before_save :make_array
  # Include default devise modules. Others available are:
  # :token_authenticatable, :confirmable,
  # :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
  :recoverable, :rememberable, :trackable, :validatable

  # Setup accessible (or protected) attributes for your model
  attr_accessible :username, :email, :password, :password_confirmation,
  :remember_me, :first_name, :last_name, :is_admin, :contact_no, :birth_date,
  :joining_date, :is_active, :role, :is_manager, :user_code, :designation
  # attr_accessible :title, :body

   def active_for_authentication?
     super && is_active?
   end

  def make_array
   self.role.reject!(&:blank?) if self.role
  end

end

team_user.rb

class TeamUser < ActiveRecord::Base
  belongs_to :user
  belongs_to :team
  attr_accessible :team_id, :team_lead_id, :user_id
end

team.rb

class Team < ActiveRecord::Base
  has_many :users, through: :team_users
  has_many :team_users
  attr_accessible :name, :team_lead_id
end

_form.html.erb(团队)

<%= form_for @team do |f| %>
  <% @team.errors.full_messages.each do |msg| %>
    <li><%= msg %></li>
  <% end %>

  <div style=" margin-top:10px">
    <label> Team Name </label>
    <%= f.text_field :name, :class => 'text_field' %>
  </div>

  <label> Add Users </label>
  <%= select_tag "TeamUser[user_id]", options_from_collection_for_select( User.all, "id", "first_name"), :style => "width:270px; height:35px", :id => "drp_Books_Ill_Illustrations",
      :class => "leader MultiSelctdropdown Books_Illustrations" %>

   <label> Team Lead </label>
  <%= f.select(:team_lead_id, User.all.map { |u| [u.first_name, u.id] }) %>

  <div class=modal-footer>
    <button class="btn" data-dismiss="modal" aria-hidden="true">Cancel</button>
    <%= f.submit "Create Team", :class => 'btn btn-primary' %>
  </div>
<% end %>

schema.rb

 create_table "team_users", :force => true do |t|
    t.integer  "team_id"
    t.integer  "user_id"
    t.datetime "created_at",   :null => false
    t.datetime "updated_at",   :null => false
  end

  create_table "teams", :force => true do |t|
    t.string   "name"
    t.datetime "created_at",   :null => false
    t.datetime "updated_at",   :null => false
    t.integer  "team_lead_id"
  end

我能够在团队模型中使用 team_lead_id 创建团队,但未能在 team_user 团队中保存数据。

【问题讨论】:

    标签: ruby-on-rails ruby associations


    【解决方案1】:

    它没有被保存的原因是你调用了new而不是create。此外,当您尝试创建TeamUser 记录时,您不知道@team.id,但此时尚未保存。但还有其他一些事情需要修复。首先,您的 new 操作应如下所示:

    def new
      @team = Team.new
      @users = User.all
    end
    

    现在您不需要在您的视图中调用User.all 两次,这不是很好的做法。 现在,视图:

      <%= form_for @team do |f| %>
      <% @team.errors.full_messages.each do |msg| %>
        <li><%= msg %></li>
      <% end %>
    
      <div style=" margin-top:10px">
        <label> Team Name </label>
        <%= f.text_field :name, :class => 'text_field' %>
      </div>
    
      <label> Add Users </label>
      <%= select_tag "users[]", options_from_collection_for_select( @users, :id, :first_name), :style => "width:270px; height:35px", :id => "drp_Books_Ill_Illustrations",
          :class => "leader MultiSelctdropdown Books_Illustrations", :multiple => true %>
    
       <label> Team Lead </label>
      <%= select_tag(:team_lead_id, options_from_collection_for_select(@users, :id, :first_name)) %>
    
      <div class=modal-footer>
        <button class="btn" data-dismiss="modal" aria-hidden="true">Cancel</button>
        <%= f.submit "Create Team", :class => 'btn btn-primary' %>
      </div>
    <% end %>
    

    在您的create 操作中:

    def create
      @team = Team.new(params[:team])
      team_lead = User.find(params[:team_lead_id])
      @team.team_lead = team_lead
      if @team.save
        users = User.where(:id => params[:users])
        users.each {|user| @team.users << user}
        flash[:notice] = 'Team has been created'
        redirect_to teams_path
      else
        flash[:alert] = 'Team not created'
        redirect_to teams_path
      end
    end
    

    您还应该更新您的Team 模型:

    class Team < ActiveRecord::Base
      has_many :users, through: :team_users
      has_many :team_users
      belongs_to :team_lead, class_name: 'User'
      attr_accessible :name
    end
    

    由于您不仅在 new 操作中显示表单,因此我建议您在控制器中创建 before_filter 以设置表单所需的变量:

    before_filter :set_form_variables, only: [:new, :index] # everywhere the form is displayed
    # ...
    private
      def set_form_variables
        @team = Team.new
        @users = User.all
      end
    

    【讨论】:

    • 嗨@mar​​ek-lipka,我尝试使用你的代码,但我在 TeamsController#create User(#89523760) 中得到 ActiveRecord::AssociationTypeMismatch,得到 NilClass(#74554310) 错误。
    • 我知道不是。 class_name 选项指定关系的类。由于Teamteam_lead 应该是User 的实例,并且不能从关联名称中推断出来,所以需要明确指定class_name。这段代码应该可以工作。
    • 这是因为您在index 操作中也显示表单,而@users 实例变量在此操作中未设置。等几分钟,我会更新我的答案。
    • 是的,这是我的错误。另一个更新。 :) 你是对的,它应该是控制器中的params[:team_lead_id],你的原因是不对的。原因是我们在名为team_lead_id 的参数中传递了lead_id。如果我在视图中写了select_tag :team_lead,那么控制器中也会有params[:team_lead]
    • 这很奇怪。行。尝试进入沙盒控制台(使用rails c -s)并手动创建Team记录:team = Team.newteam.team_lead = User.firstteam.save。然后致电team.reload 并检查team.team_lead_id
    猜你喜欢
    • 1970-01-01
    • 2017-05-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-16
    相关资源
    最近更新 更多