Подтвердить что ты не робот

Область поиска Rails с текущим пользователем

Я использую Rails 3 с Devise для auth пользователя. Скажем, у меня есть модель User, с включенным Devise и моделью продукта, и что пользователь has_many Products.

В моем контроллере продуктов я бы хотел, чтобы мой метод find был ограничен областью current_user, т.е.

@product = current_user.products.find(params[:id])

если пользователь не является пользователем admin, т.е. current_user.admin?

Сейчас я запускаю этот код почти по каждому методу, который кажется беспорядочным:

if current_user.admin?
  @product = Product.find(params[:id])
else
  @product = current_user.products.find(params[:id])
end

Есть ли более элегантный/стандартный способ сделать это?

4b9b3361

Ответ 1

Если вы используете этот код во многих своих контроллерах, вы, вероятно, должны сделать его перед фильтром и определить метод, который можно сделать в вашем ApplicationController:

before_filter :set_product, :except => [:destroy, :index]

def set_product
  @product = current_user.admin? ? Product.find(params[:id]) : current_user.products.find(params[:id]) 
end

Я не знаю, что вы используете, чтобы определить, является ли пользователь администратором или нет (роли), но если вы посмотрите на CanCan, он имеет accessible_by область, которая принимает способность (объект, который контролирует то, что пользователи могут и не могут сделать) и возвращает записи этот пользователь имеет доступ на основе разрешений, которые вы пишете сами. Вероятно, это действительно то, что вы хотите, но копирование вашей системы разрешений и ее замена могут быть или не могут быть вам полезны.

Ответ 2

Мне нравится делать это следующим образом:

class Product

  scope :by_user, lambda { |user|
    where(:owner_id => user.id) unless user.admin?
  }

end

это позволяет вам записать в контроллере следующее:

Product.by_user(current_user).find(params[:id])

Ответ 3

Вы можете добавить метод класса в Product с пользователем, отправленным в качестве аргумента.

class Product < ActiveRecord::Base
  ...

  def self.for_user(user)
    user.admin? ? where({}) : where(:owner_id => user.id)
  end

Затем вы можете вызвать его так:

Product.for_user(current_user).find(params[:id])

PS: Вероятно, лучший способ сделать where({}).