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

Rails 3 devise, current_user недоступен в модели?

в моей модели project.rb, я пытаюсь создать область с динамической переменной:

scope :instanceprojects, lambda { 
    where("projects.instance_id = ?", current_user.instance_id)
} 

Я получаю следующую ошибку:

undefined local variable or method `current_user' for #<Class:0x102fe3af0>

Где в контроллере я могу получить доступ к current_user.instance_id... Есть ли причина, по которой модель не может получить к ней доступ и как получить доступ? Кроме того, это подходящее место для создания области, как указано выше, или же она принадлежит контроллеру?

4b9b3361

Ответ 1

Это не имеет большого смысла, как вы уже указали. Current_user вообще не относится к логике модели, его следует обрабатывать на уровне контроллера.

Но вы все равно можете создать такую ​​область, просто передайте ей параметр из контроллера:

scope :instanceprojects, lambda { |user|
    where("projects.instance_id = ?", user.instance_id)
} 

Теперь вы можете вызвать его в контроллере:

Model.instanceprojects(current_user)

Ответ 2

Уже принятый ответ обеспечивает действительно правильный способ достижения этого.

Но вот потокобезопасная версия трюка User.current_user.

class User
  class << self
    def current_user=(user)
      Thread.current[:current_user] = user
    end

    def current_user
      Thread.current[:current_user]
    end
  end
end

class ApplicationController
  before_filter :set_current_user

  def set_current_user
    User.current_user = current_user
  end
end

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

Ответ 3

Райан Бейтс предлагает довольно безопасный способ реализовать такую ​​стратегию в этом railscast

Это платный эпизод (не голосуйте!), но вы можете бесплатно просмотреть исходный код

Здесь он создает метод current_tenant, но вместо него вы можете легко заменить current_user.

Вот ключевые бит кода...

#application_controller.rb
around_filter :scope_current_tenant

private

def current_tenant
  Tenant.find_by_subdomain! request.subdomain
end
helper_method :current_tenant

def scope_current_tenant
  Tenant.current_id = current_tenant.id
  yield
ensure
  Tenant.current_id = nil
end

#models/tenant.rb

def self.current_id=(id)
  Thread.current[:tenant_id] = id
end

def self.current_id
  Thread.current[:tenant_id]
end

Тогда в модели вы можете сделать что-то вроде...

default_scope { where(tenant_id: Tenant.current_id) }

Ответ 4

Вам не нужно использовать области. Если вы установили соответствующие ассоциации в моделях, следующая часть кода, размещенная в контроллере, должна выполнить трюк:

@projects = current_user.instance.projects