我在一个视图中有两个表单如果用户是主持人,则显示一个表单;如果是普通用户,则显示另一个表单,并且他们都将信息发送到2个不同的控制器。我的问题是,如果它是普通用户,为他们显示的表单使用错误的控制器。
这是编码
类别/ new.html.erb
<% if current_user.mod_of_game? @guide %>
<%= form_for([@guide, @category], url: guide_categories_path) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<%= f.label :name, "Category name" %>
<%= f.text_field :name %>
<%= f.submit "Next" %>
<% end %>
<% else %>
<%= form_for([@guide, @check_category], url: check_category_post_path) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<%= f.label :name, "Category name" %>
<%= f.text_field :name %>
<%= f.submit "Next" %>
<% end %>
<% end %>
分类控制器
before_action :mod_checker, only: [:create]
def new
@guide = Guide.friendly.find(params[:guide_id])
@category = Guide.friendly.find(@guide.id).categories.new
@check_category = CheckCategory.new
end
def create
@guide = Guide.friendly.find(params[:guide_id])
@category = Guide.friendly.find(@guide.id).categories.new(category_params)
if ((@category.save) && (current_user.mod_of_game? @guide))
flash[:info] = "guide category added succesfully!"
redirect_to @guide
else
render 'new'
end
end
private
def category_params
params.require(:category).permit(:name)
end
def mod_checker
@guide = Guide.friendly.find(params[:guide_id])
unless current_user.mod_of_game? @guide
flash[:danger] = "Sorry something went wrong!"
redirect_to root_path
end
end
check_categories控制器
def new
end
def create
if @check_category.save
flash[:info] = "Game category added successfully. A mod will apporve it shortly."
redirect_to @guide
else
render 'new'
end
end
private
def check_category_params
params.require(:check_category).permit(:name)
end
和路线
resources :guides do
resources :categories, only: [:new, :create, :edit, :update]
end
resources :check_categories, only: [:new, :edit, :update]
match 'guides/:guide_id/categories/' => 'check_categories#create', :via => :post, as: :check_category_post
抱歉,编码有点乱,把它放在代码块中的4个空格是我的编码奇怪。
如果我有非主持人用户提交表单,则会运行类别控制器中的before操作,然后我将重定向到主页。我不知道为什么会这样做,因为提交路径应该转到非主持人用户的check_categories控制器,check_categories控制器没有before过滤器。
为什么它在控制器中使用之前的过滤器我没有用于那个表单?我该如何解决?
构建此应用以更好地学习rails。所以我只能假设缺乏铁路知识导致我做错了。
答案 0 :(得分:1)
使用相同代码的两个表单(path
除外)的不良做法违反了DRY Don't Repeat Yourself
。
如@Akash
所述,这听起来像是authorization的工作。
此外,它还表示您的代码的基础结构存在问题。具体来说,您有antipattern CheckCategory
(您可以将其全部放入Category
模型中):
#config/routes.rb
resources :guides do
resources :categories, only: [:new, :create, :edit, :update] do
patch :approve, on: :member
end
end
#app/models/category.rb
class Category < ActiveRecord::Base
before_action :set_guide
def new
@category = current_user.categories.new
flash[:notice] = "Since you are not a moderator, this will have to be approved." unless current_user.mod_of_game? @guide
end
def create
@category = current_user.categories.new category_params
@category.guide = @guide
@category.save
end
def approve
@category = @guide.categories.find params[:id]
@category.approve
end
private
def set_guide
@guide = Guide.find params[:guide_id]
end
end
#app/views/categories/new.html.erb
<%= form_for [@guide, @category] do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<%= f.label :name, "Category name" %>
<%= f.text_field :name %>
<%= f.submit "Next" %>
<% end %>
以上将解决您的大多数结构性问题。
-
要解决授权问题,您最好在模型中表示该类别是否已“批准”:
#app/models/category.rb
class Category < ActiveRecord::Base
enum status: [:pending, :approved]
belongs_to :user
belongs_to :guide
validates :user, :guide presence: true
before_create :set_status
def approve
self.update status: "approved"
end
private
def set_status
self[:status] = "approved" if self.user.mod_of_game? self.guide
end
end
-
如果我理解正确,你想允许任何人创建一个类别,但是没有mods是由主持人“检查”他们的类别。
上面的代码应该为您实现。
您需要添加一个gem,例如 CanCan
CanCanCan
来实施某些授权:
#app/views/categories/index.html.erb
<% @categories.each do |category| %>
<%= link_to "Approve", guide_category_approve_path(@guide, category) if category.waiting? && can? :update, Category %>
<% end %>
答案 1 :(得分:0)
使用“Cancan”Gem并授权