我在保存与联接表相关的数据时遇到了麻烦。我正在使用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">×</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)
我正在把头发拉出来,所以任何帮助都会非常感激。
答案 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
并不过分熟悉,所以其他人可能会有更好的建议,但这至少可以让你更接近。