我需要一个直截了当,易于理解的答案。我正在为管理用户构建一个用户控制面板,通过Web界面创建/编辑/删除系统用户(在Authlogic和rails-authorization上)。
在/users
视图中,我列出了所有用户,然后根据角色对其进行了细分。
在每个角色列表的末尾,我都有一个链接“添加新的{用户类型}”。
现在,我想要的是:
app/controllers/users_controller.rb new
操作。我尝试过通过链接传递参数,然后通过params[]
访问它们,但没有运气。我的角色分配不是用户模型的一部分,我知道这会让事情变得复杂。
目前,只要表单提交失败,它就会使:type
空白,并呈现香草(非定制)表单。
任何人都能做出这样的正面或反面吗?给我一些指示?我相信我已经在下面复制了我的代码的相关部分(任何想要回答清理代码的人,我也很感激!)
视图
app/views/users/index.html.haml
:
.tabs
%ul
%li
%a{ :href => '#all' }
%span All Users
%li
%a{ :href => '#employees' }
%span Employees
%li
%a{ :href => '#clients' }
%span Clients
%li
%a{ :href => '#prospects' }
%span Prospects
%li
%a{ :href => '#affiliates' }
%span Affiliates
#all
= render :partial => 'users', :locals => { :users => @users, :type => 'All' }
#employees
= render :partial => 'users', :locals => { :users => @employees, :type => 'Employee' }
#clients
= render :partial => 'users', :locals => { :users => @clients, :type => 'Client' }
#prospects
= render :partial => 'users', :locals => { :users => @prospects, :type => 'Prospect' }
#affiliates
= render :partial => 'users', :locals => { :users => @affiliates, :type => 'Affiliate' }
app/views/users/_users.html.haml
:
- if users.empty?
%p{ :class => 'notice' }= "No #{type.pluralize} Found"
%p{ :class => 'controls' }= link_to "Add a new #{type}", new_user_path(:type => type)
- else
%table
%tr
%th Username
%th Email
%th Roles
- users.each do |user|
%tr{ :class => cycle('even','odd') }
%td=h user.username
%td=h user.email
%td= user.list_roles.collect{ |role| "<span class=\"role #{role}\">#{role}</span>" }.sort
%td= link_to 'Edit', edit_user_path(user, :type => type)
- if user.is_root?
%td Can’t delete root
- else
%td= link_to 'Delete', user, :confirm => 'Are you sure you wish to delete this user? This is irreversible!', :method => :delete
%p{ :class => 'controls' }= link_to "Add a new #{type}", new_user_path(:type => type)
app/views/users/new.html.haml
:
- title 'New User'
- form_for @user do |f|
= f.error_messages
%ol{ :class => 'form' }
%li
= f.label :username
= f.text_field :username
%li
= f.label :email
= f.text_field :email
%li
= f.label :password
= f.password_field :password
%li
= f.label :password_confirmation
= f.password_field :password_confirmation
%li
- if @roles
- @roles.each do |role|
= label_tag role
= check_box_tag 'user[assigned_roles][]', role
- else
= hidden_field_tag 'user[assigned_roles][]', @type
%li{ :class => 'submit' }
= f.submit 'Register'
= link_to 'cancel', @cancel
控制器
app/controllers/users_controller.rb
:
class UsersController < ApplicationController
permit 'admin', :only => 'index', :get_user_method => 'current_user'
def index
@users = User.all
@employees = find_all_users_with_roles(['root','admin'])
@clients = find_all_users_with_roles(['client'])
@prospects = find_all_users_with_roles(['prospect'])
@affiliates = find_all_users_with_roles(['affiliate'])
end
def new
@user = User.new
@roles = get_all_roles
@type = params[:type]
@cancel = users_path
end
def create
@user = User.new(params[:user])
type = params[:type]
roles = params[:user][:assigned_roles]
if @user.save
update_user_roles(@user,roles)
if current_user.is_admin_or_root?
flash[:message] = "User \"#{@user.username}\" created."
redirect_to users_path
else
flash[:message] = "Congrats! You’re now registered, #{@user.username}!"
redirect_to app_path
end
else
params[:type] = type
render :action => 'new'
end
end
...
private
def get_all_roles
roles = []
Role.find(:all).each do |role|
roles << role.name
end
roles
end
# code cleanup (using '.roles' ?)
def find_all_users_with_roles(find_roles)
users = []
find_roles.each do |find_role|
user_role_id = Role.find_by_name(find_role).id unless Role.find_by_name(find_role).nil?
RolesUser.find_all_by_role_id(user_role_id).each do |role|
users << User.find(role.user_id) unless users.include?(User.find(role.user_id))
end
end
users
end
# cleanup - virtual attribute?? couldn't get that to work last time
def update_user_roles(user,roles)
# add new roles
roles.each do |role|
user.has_role role unless user.has_role? role
end
# delete roles
(user.list_roles - roles).each do |role|
user.has_no_role role
end
end
end
答案 0 :(得分:1)
正如你没有说过的那样,它看起来是正确的,我将假设单击“添加新的#{type}”链接可以正常工作。看起来您也可以成功创建用户。因此,我将继续解决保存失败的问题。
控制器在失败的创建操作上呈现新模板,但未定义与新操作相同的实例变量。所以我们需要再次定义它们。我已将它们添加到故障块中的create方法中。我也对新的做了一个微妙的改变,使你的表格更清洁。
应用/控制器/ users_controller.rb:强>
def new
@user = User.new
@type = params[:type]
@roles = get_all_roles.reject{|r| r.name == @type}
@cancel = users_path
end
def create
@user = User.new(params[:user])
@assigned_roles = params[:user][:assigned_roles].select{|k,v| ! v.nil?}
if @user.save
update_user_roles(@user,roles)
if current_user.is_admin_or_root?
flash[:message] = "User \"#{@user.username}\" created."
redirect_to users_path
else
flash[:message] = "Congrats! You’re now registered, #{@user.username}!"
redirect_to app_path
end
else
@type = params[:type]
@roles = get_all_roles.reject{|r| r.name == @type}
@cancel = users_path
render :action => 'new'
end
end
然而,我们只是部分完成,只需在控制器中进行更改,我们就会正确列出角色,但不会分配类型。所以我们必须修改form_for调用以将type参数传递给create调用。我们还需要更改表单,以便在失败后保留角色。通过从控制器中的@roles中删除类型,表单中未列出指定的类型。它会自动应用为hidden_field。我也冒昧地围绕角色复选框重构部分,这样只有在要显示的角色时才会显示包含角色部分的%li。
应用/视图/用户/ new.html.haml 强>
- form_for @user, :url => {:action => :create, :type => @type) do |f|
%ol{ :class => 'form' }
%li
= f.label :username
= f.text_field :username
%li
= f.label :email
= f.text_field :email
%li
= f.label :password
= f.password_field :password
%li
= f.label :password_confirmation
= f.password_field :password_confirmation
- if @roles
%li
- @assigned_roles ||= []
- @roles.each do |role|
= label_tag role
= check_box_tag 'user[assigned_roles][]', role, @assigned_roles.include?(role)
= hidden_field_tag 'user[assigned_roles][]', @type
%li{ :class => 'submit' }
= f.submit 'Register'
= link_to 'cancel', @cancel
通过这些快速变化,事情应该按照你期望的方式发挥作用。
答案 1 :(得分:0)
基本上是EmFi建议的所有内容,加上一些调整:
应用/视图/用户/ new.html.haml 强>
- if @roles
%li
- @assigned_roles ||= []
- @roles.each do |role|
= label_tag role
= check_box_tag 'user[assigned_roles][]', role, (@roles & @assigned_roles ).include?(role)
<强>除去:强>
= hidden_field_tag 'user[assigned_roles][]', @type
(我想继承的参数由:
提供- form_for @user, :url => {:action => :create, :type => @type) do |f| ...
由于我只将它用于演示,我不需要将其存储在表格中。)
应用/控制器/ users_controller.rb:强>
def new
@user = User.new
@type = params[:type]
@roles = get_all_roles # don't need to reject anything here either, since the :type is no longer part of this array
@cancel = users_path
end
def create
@user = User.new(params[:user])
@assigned_roles = params[:user][:assigned_roles] # already has the roles I need; unchecked checkboxes are not passed into this; only checked ones
if @user.save
update_user_roles(@user,@assigned_roles)
if current_user.is_admin_or_root?
flash[:message] = "User \"#{@user.username}\" created."
redirect_to users_path
else
flash[:message] = "Congrats! You’re now registered, #{@user.username}!"
redirect_to app_path
end
else
@type = params[:type]
@roles = get_all_roles # don't need to reject anything, since the :type is no longer part of this array
@cancel = users_path
render :action => 'new'
end
end
谢谢,EmFi,让我直截了当! @assigned_roles
逻辑和
- form_for @user, :url => {:action => :create, :type => @type) do |f| ...
是我正在寻找的这个难题的关键!