表没有在连接表中更新,我无法弄清楚原因

时间:2013-11-21 05:22:32

标签: ruby-on-rails ruby devise

我在保存与联接表相关的数据时遇到了麻烦。我正在使用Rails 4.01和Devise 3.23并进行rolify。我对Rails相当新,所以这可能是一个noob问题,虽然我已经搜索了所有内容,但我可以。

基本上,当我尝试更改角色时,它不会将数据保存在连接表中,但它似乎没有抛出任何错误。我在日志中也找不到任何东西。 我和第二个连接表有完全相同的问题。共同点是他们都加入了我的用户表,我正在我的用户控制器上使用更新操作。

我花了最后两个小时试图找到解决方案。我认为它可能是一个强大的参数问题,但我找不到问题。我尝试降级到Rails 4.0.0以防万一,但没有好处。我有另一个应用程序具有基本相同的代码,没有任何问题。

这是我的用户控制器:

class UsersController < ApplicationController
  before_filter :authenticate_user!
  before_action :set_user, only: [:show, :edit, :update, :destroy]

  def index
    authorize! :index, @user, :message => 'Not authorized as an administrator.'
    @users = User.all
  end

  def show
  end

  def update
    authorize! :update, @user, :message => 'Not authorized as an administrator.'
    if @user.update_attributes(user_params[:user])
      redirect_to users_path, :notice => "User updated."
    else
      redirect_to users_path, :alert => "Unable to update user."
    end
  end

  def destroy
    authorize! :destroy, @user, :message => 'Not authorized as an administrator.'
    user = User.find(params[:id])
    unless user == current_user
      user.destroy
      redirect_to users_path, :notice => "User deleted."
    else
      redirect_to users_path, :notice => "Can't delete yourself."
    end
  end

  # new function to set the password without knowing the current password used in our confirmation controller. 
  def attempt_set_password(params)
    p = {}
    p[:password] = params[:password]
    p[:password_confirmation] = params[:password_confirmation]
    update_attributes(p)
  end

  # new function to return whether a password has been set
  def has_no_password?
   self.encrypted_password.blank?
 end

 # new function to provide access to protected method unless_confirmed
 def only_if_unconfirmed
   unless_confirmed {yield}
 end

private

    # Use callbacks to share common setup or constraints between actions.
    def set_user
      @user = User.find(params[:id])
    end

    # Never trust parameters from the scary internet, only allow the white list through.
    def user_params
      params.require(:user).permit( :name, :role_ids, :qualification_id, :role, :qualification )
    end

end

我的用户模型:

class User < ActiveRecord::Base
  belongs_to :qualification

  rolify
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
  :recoverable, :rememberable, :trackable, :validatable, :confirmable

  validates :phone, presence: true, format: { with: /1.\d{3}.\d{3}.\d{4}/, message: "Must be in 1.555.555.5555 format" }
  validates :name, presence: true
  validates :email, presence: true
  validates :acknowledgement, presence: true


# new function to set the password without knowing the current password used in our confirmation controller. 
def attempt_set_password(params)
  p = {}
  p[:password] = params[:password]
  p[:password_confirmation] = params[:password_confirmation]
  update_attributes(p)
end

# new function to return whether a password has been set
def has_no_password?
  self.encrypted_password.blank?
end

# new function to provide access to protected method unless_confirmed
def only_if_unconfirmed
  pending_any_confirmation {yield}
end

def password_required?
  # Password is required if it is being set, but not for new records
  if !persisted? 
    false
  else
    !password.nil? || !password_confirmation.nil?
  end
end

end

我的资格模型:

class Qualification < ActiveRecord::Base
  has_many :users
end

我的角色模型:

class Role < ActiveRecord::Base
  has_and_belongs_to_many :users, :join_table => :users_roles
  belongs_to :resource, :polymorphic => true

  scopify
end

这是我改变角色的索引视图:

<h2 class='subheader'>People</h2>
  <% @users.each do |user| %>
  <div class='row collapse'>
      <div class='large-2 columns'><%= link_to user.name, user_path(user) %></div>
      <div class='large-2 columns'><%= user.email %></div>
      <div class='large-2 columns'><%= user.phone %></div>
      <div class='large-2 columns'><%=  user.qualification.name unless user.qualification.nil?%></div>
      <div class='large-2 columns'><%= user.roles.first.name.titleize unless user.roles.first.nil? %></div>
      <div class='large-2 columns'>
        <% if user != current_user %> 
        <a data-reveal-id="role-options-<%= user.id %>" href="#" class="button tiny radius" type="button">Change role</a>
      <% end %>
      </div>
      <div class='large-2 columns'>
        <%= link_to("Delete Person", user_path(user), :data => { :confirm => "Are you sure?" }, method: :delete, class: 'button radius tiny') unless user == current_user %></div>
        <hr>
    </div>
<div id="role-options-<%= user.id %>" class="reveal-modal tiny" style="display: none;">
  <%= simple_form_for user, url: user_path(user), html: {:method => :put, class: 'custom' } do |f| %>
  <div>
    <a class="close-reveal-modal">&#215;</a>      
    <h3>Change Role</h3>
  </div>
  <div>
    <%= f.input :role_ids, collection: Role.all, as: :radio_buttons, label_method: lambda {|t| t.name.titleize}, label: false, item_wrapper_class: 'inline', checked: user.role_ids.first %>
  </div>
  <div>
    <%= f.submit "Change Role", :class => "button tiny radius" %>
  </div>
  <% end %>
</div>  
<% end %>

以下是我日志中的相关摘录:

Started PUT "/users/47" for 127.0.0.1 at 2013-11-20 22:27:59 -0700
Processing by UsersController#update as HTML
  Parameters: {"utf8"=>"✓",     "authenticity_token"=>"3kfL/K47ynC4LGF9kh/cAfAadGu8OXhH9kXhxeGPsvo=", "user"=> {"role_ids"=>"2"}, "commit"=>"Change Role", "id"=>"47"}
  [1m[35mUser Load (0.2ms)[0m  SELECT "users".* FROM "users" WHERE "users"."id" = 1 ORDER BY "users"."id" ASC LIMIT 1
  [1m[36mUser Load (0.1ms)[0m  [1mSELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1[0m  [["id", "47"]]
  [1m[35m (0.1ms)[0m  SELECT COUNT(*) FROM "roles" INNER JOIN "users_roles" ON "roles"."id" = "users_roles"."role_id" WHERE "users_roles"."user_id" = ? AND (((roles.name = 'admin') AND (roles.resource_type IS NULL) AND (roles.resource_id IS NULL)))  [["user_id", 1]]
  [1m[36m (0.1ms)[0m  [1mbegin transaction[0m
  [1m[35m (0.1ms)[0m  commit transaction
Redirected to http://localhost:3000/users
Completed 302 Found in 8ms (ActiveRecord: 0.7ms)

我正在把头发拉出来,所以任何帮助都会非常感激。

1 个答案:

答案 0 :(得分:0)

我对rolify并不是非常熟悉,但看起来你的User模型不会对参数中的role_ids属性做任何事情......

假设没有,您需要在控制器中迭代每个role_id(如果存在):

def update
  authorize! :update, @user, :message => 'Not authorized as an administrator.'

  @user.update_roles(user_params[:role_ids]) if user_params[:role_ids].present?

  if @user.update_attributes(user_params[:user])
    redirect_to users_path, :notice => "User updated."
  else
    redirect_to users_path, :alert => "Unable to update user."
  end
end

然后在您的User模型上,您将拥有:

def update_roles(role_ids)
  role_names = Role.find_all_by_id(role_ids).map(&:name)

  role_names.each {|role_name| self.add_role role_name.to_sym }
end

同样,我没有对此进行测试,我对rolify并不过分熟悉,所以其他人可能会有更好的建议,但这至少可以让你更接近。