Ruby on Rails - переменная контроллера доступа из модели

Я пытаюсь получить доступ к переменной экземпляра, установленной в контроллере модели. Контроллер - это контроллер продуктов, а модель - это модель продуктов. Переменная экземпляра - это экземпляр другой модели с именем account.

Переменная экземпляра @current_account

Когда я запускаю код, ничего не происходит, я не получаю ошибку. Кто-нибудь знает, где я могу найти что-нибудь о переменных экземпляра доступа, установленных в контроллере из модели?

Спасибо

Eef


person RailsSon    schedule 10.03.2010    source источник
comment
Итак, вы пытаетесь получить доступ к переменной @current_account в модели? Переменная @current_account устанавливается в контроллере?   -  person Steve    schedule 11.03.2010


Ответы (5)


Обычно вам не следует пытаться получить доступ к контроллеру из модели из-за серьезных проблем, которые я не буду вдаваться в подробности.

Решил аналогичную проблему так:

class Account < ActiveRecord::Base
  cattr_accessor :current
end

class ApplicationController < ActionController::Base
  before_filter :set_current_account
  def set_current_account
    #  set @current_account from session data here
    Account.current = @current_account
  end
end

Затем просто войдите в текущую учетную запись с помощью Account.current

person jeem    schedule 10.03.2010
comment
Разве переменные класса не являются общими для всех запросов ?! - person vise; 11.03.2010
comment
Я не понимаю, как получить значение переменной из символа: current в модели? Я пробовал Account.current и current. - person djburdick; 28.05.2010
comment
В чем разница между cattr_accessor и attr_accessor? - person user94154; 22.06.2010
comment
cattr_accessor прикреплен к классу, как self.value, а не к методу value. - person Garrett; 23.06.2010
comment
@vise мне также кажется однопользовательским веб-приложением. Мне было интересно, может ли thread_cattr_accessor помочь. Если мы уверены, что один поток не будет переключаться между запросами туда и обратно. - person akostadinov; 15.06.2021

ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ: следующий код нарушает соглашения MVC, что говорит ...

Использование атрибутов класса, вероятно, может привести к проблемам с безопасностью потоков. Я бы использовал Thread.current + around_filter для хранения данных, связанных с контроллером, на уровне потока и обеспечения его очистки непосредственно перед завершением запроса:

class ApplicationController < ActionController::Base

  around_filter :wrap_with_hack

  def wrap_with_hack
    # We could do this (greener solution): 
    # http://coderrr.wordpress.com/2008/04/10/lets-stop-polluting-the-threadcurrent-hash/
    # ... but for simplicity sake:
    Thread.current[:controller] = self
    begin
      yield
    ensure
     # Prevent cross request access if thread is reused later
     Thread.current[:controller] = nil
    end
  end
end

Теперь текущий экземпляр контроллера будет доступен глобально во время обработки запроса через Thread.current [: controller]

person ibaixas    schedule 06.04.2012
comment
Привет, @ibaixas, спасибо за это. Но не могли бы вы объяснить, как атрибут class приводит к проблеме безопасности потоков. Я новичок. И присутствует ли эта проблема и в Rails 4? - person Akshat; 13.11.2014
comment
Переменные класса распределяются между потоками. Это означает, что при использовании многопоточного сервера приложений, такого как puma, разные потоки, обрабатывающие разные запросы, сохранят экземпляр контроллера в одной и той же переменной, перезаписывая друг друга. Используя хэш Thread.current, вы гарантируете, что переменная устанавливается только текущим потоком. Извините за задержку (2 года) ... - person ibaixas; 24.11.2016

Если вам нужен доступ к переменной контроллера из модели, это обычно означает, что ваш дизайн неправильный, потому что контроллер служит мостом между представлением и моделью (по крайней мере, в Rails), контроллер получает информацию от моделей, а модели не должны Я ничего не знаю о контроллерах, но если вы все равно хотите это сделать, вы можете сделать это так, как сказал Джим, но я бы предпочел:

 class << self

    attr_accessor :current

 end

instead of

cattr_accessor :current

вы можете понять, почему здесь => cattr_accessor не работает ' т работать как надо

person raf    schedule 12.03.2010
comment
Это ненамного лучше, потому что он по-прежнему распределяется между запросами, не говоря уже о потокобезопасности. Он должен быть либо атрибутом в User instance, либо вы должны передать его методам, которым необходимо его знать. - person gtd; 19.08.2011

Я не могу комментировать напрямую, поэтому опубликую здесь: принятый ответ не кажется правильным. Как отмечает @vise, переменные класса совместно используются в запросах. Поэтому, если для всего приложения не будет только одна текущая учетная запись, это не будет вести себя так, как ожидалось.

Для получения дополнительной информации см. Принятый ответ @molf здесь: Rails ничего не разделяет или отдельные запросы могут обращаться к одним и тем же переменным времени выполнения?

person Jacob    schedule 07.08.2010

Я не уверен, что правильно понимаю вопрос, но я возьму удар.

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

person ghoppe    schedule 10.03.2010