Ruby on rails 3 检查控制器实例变量是否属于当前用户的before\u筛选器
目前,我有一个为餐馆设置的CRUD资源。一个老板有很多餐馆,一个餐馆属于他的老板。任何用户都可以访问餐厅的“索引”和“显示”视图。但是,为了创建一家新餐厅,店主必须登录。我实现了这个设计,效果很好。我的问题是,在能够编辑、更新或销毁餐厅之前,确保餐厅的当前所有者拥有该餐厅 我在创建before_筛选器时遇到问题,该筛选器将检查登录所有者(当前所有者)是否是登录所有者试图查看的餐厅的所有者 在设置Before_过滤器之前,我快速创建了一个#check_if_owner方法,并将其放置在编辑操作中。如果店主不拥有餐厅,则应将其重定向到上一页。但是,由于某些原因,我收到以下错误:Ruby on rails 3 检查控制器实例变量是否属于当前用户的before\u筛选器,ruby-on-rails-3,authentication,activerecord,devise,before-filter,Ruby On Rails 3,Authentication,Activerecord,Devise,Before Filter,目前,我有一个为餐馆设置的CRUD资源。一个老板有很多餐馆,一个餐馆属于他的老板。任何用户都可以访问餐厅的“索引”和“显示”视图。但是,为了创建一家新餐厅,店主必须登录。我实现了这个设计,效果很好。我的问题是,在能够编辑、更新或销毁餐厅之前,确保餐厅的当前所有者拥有该餐厅 我在创建before_筛选器时遇到问题,该筛选器将检查登录所有者(当前所有者)是否是登录所有者试图查看的餐厅的所有者 在设置Before_过滤器之前,我快速创建了一个#check_if_owner方法,并将其放置在编辑操作中。
ActiveRecord::RecordNotFound in RestaurantsController#edit
Couldn't find Restaurant with id=4 [WHERE "restaurants"."owner_id" = 1]
我不确定为什么会发生这种情况,因为当我在控制台中运行#check_ownership方法时,它返回false,这正是我希望在当前#u所有者不拥有餐厅的情况下该方法执行的操作。如果在控制台中返回false,用户不应该被重定向到上一页,而不是接收RecordNotFound错误吗?我不知道为什么会这样
发布的是代码的其余部分
class RestaurantsController < ApplicationController
before_filter :authenticate_owner!, except: [:index, :show]
# before_filter :check_if_owner, only: [:edit, :update, :destroy]
def index
@restaurants = Restaurant.all
end
def show
@restaurant = Restaurant.find(params[:id])
end
def new
@restaurant = current_owner.restaurants.new
end
def create
@restaurant = current_owner.restaurants.build(params[:restaurant])
if @restaurant.save
redirect_to restaurants_path
else
flash[:error] = "<ul>" + @restaurant.errors.full_messages.map{|o| "<li>" + o + "</li>" }.join("") + "</ul>"
redirect_to new_restaurant_path
end
end
def edit
check_if_owner(Restaurant.find(params[:id]))
@restaurant = current_owner.restaurants.find(params[:id])
end
def update
@restaurant = current_owner.restaurants.find(params[:id])
@restaurant.update_attributes(params[:restaurant])
redirect_to restaurant_path(@restaurant)
end
def destroy
@restaurant = current_owner.restaurants.find(params[:id])
@restaurant.destroy
redirect_to restaurants_path
end
private
def check_if_owner(restaurant)
debugger
if current_owner.check_ownership(restaurant)
return
else
redirect_to :back
end
end
end
class Owner < ActiveRecord::Base
# Include default devise modules. Others available are:
# :token_authenticatable, :confirmable,
# :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
# Setup accessible (or protected) attributes for your model
attr_accessible :email, :password, :password_confirmation, :remember_me, :name
# attr_accessible :title, :body
has_many :restaurants
validates :name, presence: true
validates :email, presence: true
def check_ownership(restaurant)
!self.restaurants.find_by_id(restaurant.id).nil?
end
end
class RestaurantController”+@restaurant.errors.full_messages.map{o}“”+o+“ ”}。加入(“”+”“)
重定向到新餐厅路径
结束
结束
定义编辑
检查所有者(Restaurant.find(params[:id]))
@restaurant=当前所有者.restaurants.find(参数[:id])
结束
def更新
@restaurant=当前所有者.restaurants.find(参数[:id])
@餐厅。更新_属性(参数[:餐厅])
重定向到餐厅路径(@restaurant)
结束
def销毁
@restaurant=当前所有者.restaurants.find(参数[:id])
@餐厅,毁灭
重定向到餐厅路径
结束
私有的
def检查业主(餐厅)
调试器
如果为当前所有者,请检查所有者(餐厅)
返回
其他的
重定向到:返回
结束
结束
结束
类所有者
用以下方法解决了这个问题:
class RestaurantsController < ApplicationController
before_filter :authenticate_owner!, except: [:index, :show]
before_filter :check_if_owner, only: [:edit, :update, :destroy]
private
def check_if_owner
if current_owner.has_ownership?(Restaurant.find(params[:id]))
return
else
flash[:error]= "You do not have permission to do that."
redirect_to :back
end
end
end
首先,我将把责任放在检查餐厅的所有权上,而不是所有者,特别是因为您正在RestaurantController中实施此检查 而且,你似乎在设计所有权检查。真的,你只需要检查一下餐厅的
restaurant.owner==current\u owner
餐厅.rb
def owned_by?(current_owner)
owner == current_owner
end
def manages?(object)
object.respond_to?(:owner) && object.owner == self
end
如果您认为将在其他地方重用此方法,则只需要在模型中使用此方法(而不是在过滤器之前在控制器中作为单行)
或者,如果您的所有者要管理许多不同种类的对象,您可以将权限检查保留在所有者模型中,使其更加灵活
owner.rb
def owned_by?(current_owner)
owner == current_owner
end
def manages?(object)
object.respond_to?(:owner) && object.owner == self
end
在ActiveRecord查询中,使用find和find_by_id时使用的方法是脆弱的,不是首选方法。具体地说,当没有结果时,find_by_*会抛出一个异常。另一方面,使用where(:id=>id)将返回空数组,如果没有结果,则返回nil
查看这些内容,以获得更多见解和最佳实践。谢谢卡洛斯!这非常有用。