当我正在阅读Rails 4 in Action时,我正在尝试实现自己的应用程序,因此它与书中的内容不同。 该书的相应提交是Section 7.2.3: Only admins can create or delete projects
就我而言,管理员只能删除该项(item
对应于图书中的project
。)。
我的回购https://github.com/tenzan/shop并部署了http://ichiba-demo.herokuapp.com/
我想申请的规则是:
staff@example.com/password
登录)可以执行除destroy
操作之外的所有操作。admin@example.com/password
)只能destroy
。意识到我有:
在admin/items_controller.rb
:
class Admin::ItemsController < Admin::ApplicationController
def destroy
@item = Item.find(params[:id])
@item.destroy
flash[:notice] = 'Item has been deleted.'
redirect_to items_path
end
private
def item_params
params.require(:item).permit(:name, :quantity)
end
end
在controllers/items_controller.rb
:
class ItemsController < ApplicationController
before_action :set_item, only: [:show, :edit, :update]
def index
@items = Item.all
end
def new
@item = Item.new
end
def create
@item = Item.new(item_params)
if @item.save
flash[:notice] = 'Item has been created.'
redirect_to @item
else
flash.now[:alert] = 'Item has not been created.'
render 'new'
end
end
def show
end
def edit
end
def update
if @item.update(item_params)
flash[:notice] = 'Item has been updated.'
redirect_to @item
else
flash.now[:alert] = 'Item has not been updated.'
render 'edit'
end
end
private
def set_item
@item = Item.find(params[:id])
rescue ActiveRecord::RecordNotFound
flash[:alert] = 'The item could not be found.'
redirect_to items_path
end
def item_params
params.require(:item).permit(:name, :quantity)
end
end
在routes.rb
:
Rails.application.routes.draw do
namespace :admin do
root 'application#index'
resources :items, only: :destroy
end
devise_for :users
root 'items#index'
resources :items, only: [:index, :show, :edit, :update, :new, :create] do
resources :comments
end
end
问题:
routes.rb
中指定操作,因为我已经指定谁可以在相应的控制器中使用哪些操作?当我从routes.rb
... routes.rb
和controllers/items_controllers.rb
?如果你指出其他地方需要改进以满足最佳实践,我会很高兴。
PS:主题可能含糊不清,请随时编辑。
答案 0 :(得分:2)
我是否必须在routes.rb中指定操作,就像我已经拥有的那样 指定谁可以在相应的控制器中使用哪些操作?
是。例如,如果您在items_controller.rb
控制器中只有一个操作(假设show
),则离开
resources :items do # no specified actions
#...
end
在routes.rb
中会生成项目控制器的所有路由(new
,create
,edit
,destroy
,update
等) 。但是在routes.rb
中指定操作,只会将生成的路由限制为仅需要。
当我在2个地方指定行动时,我是否违反DRY概念,即 在routes.rb和controllers / items_controllers.rb?
中
没有。由于您实际在控制器中指定了操作,因此在routes.rb
中您只需指定路由。
如果你指出其他地方需要改进以达到最佳状态,我会很高兴的 实践。
这一行:
resources :items, only: [:index, :show, :edit, :update, :new, :create] # better to use %i() notation, eg only: %i(index show edit update new create)
可以写成:
resources :items, except: :destroy
关于您的管理员用户 - 只允许他destroy
,只需检查current_user是否为admin。如果您只有一个允许仅由admin执行的操作,则可以在控制器中创建before_action:
before_action :check_admin?, only: %i(destroy another_action)
private
def check_admin?
# your logic to check, if user is admin
end
您也可以通过Ruby style guide感兴趣。
答案 1 :(得分:1)
即使您没有直接违反DRY,您也可以通过将单个实体的操作移动到不同的控制器来混淆REST架构。管理员不需要特定的控制器或命名空间 - 您只需在继续执行删除操作之前断言用户是管理员。
由于您已将admin
列添加到设计模型,因此可以将删除操作移至ItemsController
def destroy
if current_user.try(:admin?)
@item = Item.find(params[:id])
@item.destroy
flash[:notice] = 'Item has been deleted.'
else
flash[:alert] = 'Only admins can delete items.'
end
redirect_to items_path
end
您的路由会更干净,因为您的管理命名空间仅用于用户审核。项目的唯一途径是:
resources :items do
resources :comments
end