我必须在 routes.rb 中指定操作吗?
Do I have to specify actions in routes.rb?
当我阅读 Rails 4 in Action 时,我正在尝试实现我自己的应用程序,因此它看起来与书中的不一样。
本书对应的提交是Section 7.2.3: Only admins can create or delete projects
在我的例子中,管理员只能删除项目(item
对应书中的project
)。
我的回购 https://github.com/tenzan/shop and deployed 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
两个地方指定操作时,我是否违反了 DRY 概念?
如果您指出其他地方需要改进以满足最佳实践,我会很高兴。
PS: 主题可能比较模糊,欢迎编辑。
Do I have to specify actions in the routes.rb, as I already have
specified who can use what actions in their corresponding controllers?
是的。例如,如果您在 items_controller.rb
控制器中只有一个操作(比如说 show
),然后离开
resources :items do # no specified actions
#...
end
在 routes.rb
中它会为项目控制器生成所有路由(对于 new
、create
、edit
、destroy
、update
ETC)。但是在 routes.rb
中指定操作会将生成的路由限制为仅需要。
Am I violating DRY concept, when I specify actions in 2 places, i.e.
in the routes.rb and controllers/items_controllers.rb ?
没有。因为你实际上在控制器中指定了动作,所以在 routes.rb
中你只指定了 routes.
I'll be happy if you point out other places to improve to meet best
practice.
这一行:
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 是否为管理员。如果你有更多的,不止一个只允许管理员执行的操作,你可以在控制器中创建 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。
即使您没有直接违反 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
当我阅读 Rails 4 in Action 时,我正在尝试实现我自己的应用程序,因此它看起来与书中的不一样。 本书对应的提交是Section 7.2.3: Only admins can create or delete projects
在我的例子中,管理员只能删除项目(item
对应书中的project
)。
我的回购 https://github.com/tenzan/shop and deployed 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
两个地方指定操作时,我是否违反了 DRY 概念?
如果您指出其他地方需要改进以满足最佳实践,我会很高兴。
PS: 主题可能比较模糊,欢迎编辑。
Do I have to specify actions in the routes.rb, as I already have specified who can use what actions in their corresponding controllers?
是的。例如,如果您在 items_controller.rb
控制器中只有一个操作(比如说 show
),然后离开
resources :items do # no specified actions
#...
end
在 routes.rb
中它会为项目控制器生成所有路由(对于 new
、create
、edit
、destroy
、update
ETC)。但是在 routes.rb
中指定操作会将生成的路由限制为仅需要。
Am I violating DRY concept, when I specify actions in 2 places, i.e. in the routes.rb and controllers/items_controllers.rb ?
没有。因为你实际上在控制器中指定了动作,所以在 routes.rb
中你只指定了 routes.
I'll be happy if you point out other places to improve to meet best practice.
这一行:
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 是否为管理员。如果你有更多的,不止一个只允许管理员执行的操作,你可以在控制器中创建 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。
即使您没有直接违反 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