对于Rails中的多对多关联,值无法保存在数据库中。

时间:2013-06-01 13:20:50

标签: ruby-on-rails ruby database

我有用户和角色表,它们有多对多关联。我的数据库有users,roles和role_users表。基本上我想在role_users表中保存用户的角色,这基本上是用户和角色的连接表。我从角色表中获取用户页面上的user'role,并希望将它们保存在role_users表中。但是我无法在role_users表中保存用户角色。我在用户的“创建控制器”中编写了代码,以便在role_users表中保存数据但是没有发生。

users_controller.rb

class Admin::UsersController < Admin::BaseController
  before_filter :find_user, :only => [:show, :edit, :update, :destroy]
  def index
    @users = User.all( :order => :email ) 
    @roles = Role.all
  end

  def show
  end

  def new
    @user = User.new
  end

  def create
    is_admin = params[:user].delete(:is_admin) == "1"
    @user = User.new(params[:user])
    **@user_role = RoleUser.new({:user_id => @user.id, :role_id => params[:role_user]})**
    #@user_role.role_id = params[:role_id]
    #@user_role.user_id = current_user.id
    @user_role.save

    @user.is_admin = is_admin
  if @user.save
    flash[:notice] = "User has been created."
    redirect_to admin_users_path
  else
    flash[:alert] = "User has not been created."
    render :action => :new
  end
 end

  def edit
  end

  def update
    if params[:user][:password].empty?
      params[:user].delete(:password)
    end

    set_admin
    if @user.update_attributes(params[:user])
      flash[:notice] = "User has been updated."
      redirect_to admin_users_path
    else
      flash[:alert] = "User has not been updated."
      render :action => :new
    end
  end

  def destroy
    if @user == current_user
      flash[:alert] = "You cannot delete yourself!"
    else
      @user.destroy 
      flash[:notice] = "User has been deleted."
    end
    redirect_to admin_users_path
  end

  private

  def find_user
    @user = User.find(params[:id])
  end

  def set_admin
    is_admin = params[:user].delete(:is_admin) == "1"
    @user.is_admin = true
  end
end

schema.rb

# encoding: UTF-8
# This file is auto-generated from the current state of the database. Instead
# of editing this file, please use the migrations feature of Active Record to
# incrementally modify your database, and then regenerate this schema definition.
#
# Note that this schema.rb definition is the authoritative source for your
# database schema. If you need to create the application database on another
# system, you should be using db:schema:load, not running all the migrations
# from scratch. The latter is a flawed and unsustainable approach (the more migrations
# you'll amass, the slower it'll run and the greater likelihood for issues).
#
# It's strongly recommended to check this file into your version control system.

ActiveRecord::Schema.define(:version => 20130601093644) do




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

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

  create_table "team_users", :force => true do |t|
    t.integer  "team_id"
    t.integer  "user_id"
    t.integer  "team_lead_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

  create_table "users", :force => true do |t|
    t.string   "email",                  :default => "", :null => false
    t.string   "encrypted_password",     :default => "", :null => false
    t.string   "reset_password_token"
    t.datetime "reset_password_sent_at"
    t.datetime "remember_created_at"
    t.integer  "sign_in_count",          :default => 0
    t.datetime "current_sign_in_at"
    t.datetime "last_sign_in_at"
    t.string   "current_sign_in_ip"
    t.string   "last_sign_in_ip"
    t.datetime "created_at",                             :null => false
    t.datetime "updated_at",                             :null => false
    t.boolean  "is_admin"
    t.string   "username"
    t.string   "first_name"
    t.string   "last_name"
    t.string   "contact_no"
    t.date     "birth_date"
    t.boolean  "is_active"
    t.date     "joining_date"
    t.string   "avatar_url"
    t.boolean  "is_hr"
    t.boolean  "is_manager"
    t.string   "designation"
    t.string   "user_code"
    t.string   "user_role"
  end

  add_index "users", ["email"], :name => "index_users_on_email", :unique => true
  add_index "users", ["reset_password_token"], :name => "index_users_on_reset_password_token", :unique => true

end

_form.html.erb(用于创建新用户)

<div style="margin-left:200px">
<%= form_for [:admin, @user] do |f| %>

    <% @user.errors.full_messages.each do |msg| %>
      <li><%= msg %></li>
    <% end %>


  <div style=" margin-top:10px">
    <%= f.label :first_name, :class => 'control-label' %>
    <div class="">
      <%= f.text_field :first_name, :class => 'text_field' %>
    </div>
  </div>
  <div style="margin-left:350px; margin-top:-65px">
    <%= f.label :last_name, :class => 'control-label' %>
    <div class="">
      <%= f.text_field :last_name, :class => 'text_field' %>
    </div>
  </div>

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

    <div style="margin-left:350px; margin-top:-65px">
    <%= f.label :email, :class => 'control-label' %>
    <div class="">
      <%= f.text_field :email, :class => 'text_field' %>
    </div>
  </div>

   <div style=" margin-top:10px">
    <%= f.label :contact_no, :class => 'control-label' %>
    <div class="">
      <%= f.text_field :contact_no, :class => 'text_field' %>
    </div>
  </div>
  <div style="margin-left:350px; margin-top:-65px">
    <%= f.label :birth_date, :class => 'control-label' %>
    <div class="">
      <%= f.text_field :birth_date, :class => 'datepicker ' %>
    </div>
  </div>

    <div style=" margin-top:10px">
    <%= f.label :joining_date, :class => 'control-label' %>
    <div class="">
      <%= f.text_field :joining_date, :class => 'datepicker ' %>
    </div>
  </div>

   <div style="margin-left:350px; margin-top:-65px">
    <%= f.label :password, :class => 'control-label' %>
    <div class="">
      <%= f.password_field :password, :class => 'password-field' %>
    </div>
  </div>
 <div style="margin-left:0px; margin-top:00px">
   <%= f.label :designation , :class => 'control-label' %>
   <select name="user[designation]">
    <option value="">Please select</option>
    <option value="Administrator">Administrator</option>
    <option value="User">Trainee</option>
    <option value="Software Engineer">Software Engineer</option>
    <option value="Senior Software Engineer">Senior Software Engineer</option>
    <option value="Quality Engineer">Quality Engineer</option>
   <option value="Team Lead">Team Lead</option>
 </select>
</div>

<label> User Role</label>
<%= select_tag "role_id", options_from_collection_for_select( Role.all, "id", "name"), :style => "width:270px; height:35px" %>

 <div style="margin-top:20px">
    <%= f.check_box :is_active %>
    <div class="">
      <%= f.label :is_active, "Is an active user?", :class => 'control-label' %>
    </div>
  </div>
  <div style="margin-left:190px; margin-top:-35px">
    <%= f.check_box :is_admin %>
    <div class="">
      <%= f.label :is_admin, "Is an admin?", :class => 'control-label' %>
    </div>
  </div>


    <div style="margin-left:00px; margin-top:15px">
    <%= f.check_box :is_hr %>
    <div class="">
      <%= f.label :is_hr, "Is hr?", :class => 'control-label' %>
    </div>
  </div>

  <div style="margin-left:190px; margin-top:-35px">
    <%= f.check_box :is_manager %>
    <div class="">
      <%= f.label :is_manager, "Is Manager?", :class => 'control-label' %>
    </div>
  </div>

  <div style="margin-left:00px; margin-top:30px">
    <%= f.submit :class => 'btn btn-primary' %>

    <div style="margin-left:130px;margin-top:-32px">
   <%= link_to t('.back', :default => t("helpers.links.back")),
    admin_users_path, :class => 'btn'  %>
    </div>
</div>
<% end %>
</div>

user.rb

class User < ActiveRecord::Base
 has_many :roles,  through: :role_users
 has_many :role_users
  # 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, :is_hr, :is_manager, :user_code, :designation
  # attr_accessible :title, :body
end

role_user.rb

class RoleUser < ActiveRecord::Base
  belongs_to :user
  belongs_to :role
  attr_accessible :role_id, :user_id
end

role.rb

class Role < ActiveRecord::Base
  attr_accessible :name
  has_many :users,  through: :role_users
  has_many :role_users

end

简而言之,我想在role_users表中保存user'role,这是用户和角色的连接表。为此,我在 users_controller.rb

中编写了以下代码
@user_role = RoleUser.new({:user_id => @user.id, :role_id => params[:role_user]})

但是,数据不会保存在db。

1 个答案:

答案 0 :(得分:1)

在您创建RoleUser时,您的User个实例中还没有ID。

def create
  is_admin = params[:user].delete(:is_admin) == "1"
  @user = User.new(params[:user])

  # @user is not saved here and has no id

  **@user_role = RoleUser.new({:user_id => @user.id, :role_id => params[:role_user]})**

  @user_role.save

  # based on your validations, it's likely that this @user_role.save is returning false

在有星星的行上,@ user已经构建但未保存。保存RoleUser后尝试构建User个实例。

尝试在此行之后保存RoleUserif @user.save