开发者

How to set in a middleware a variable accessible in all my application?

I am using Ruby on Rails 3 and I am trying to use middlewares in order to set a variable @variable_name accessible later in controllers.

For example my middleware is

  class Auth

    def initialize(app)
      @app = app
    end

    def call(env)
      @account ||= Account.find(1)

      @app.call(env)
    end
  end

The above code set properly the @account variable, but that isn't available in my application (in controllers, models, views, ...). So,开发者_如何学JAVA how can I accomplish that?


I seen this answer that is a way to do what I need, but I would like to have the @account variable "directly accessible". That is, without use that way but making that available, for example in my views, like this:

<%= debug @account %>


You can use 'env' for that. So in your middleware you do this:

def call(env)
  env['account'] = Account.find(1)
  @app.call(env)
end

You can get the value by using 'request' in your app:

request.env['account']

And please don't use global variables or class attributes as some people suggest here. That's a sure way to get yourself into troubles and really is a bad habit.


I don't know if this can be done with a Middelware. My suggestion would be this:

class ApplicationController < ActionController::Base

  protect_from_forgery

  before_filter :set_my_var

private
  def set_my_var
    @account ||= Account.find(1)
  end

end

This way all your controllers and views have access to @account


Rails 5.2 added ActiveSupport::CurrentAttributes for this kind of globally relevant request context data. You inherit from it to create a singleton class accessible from anywhere, which is automatically reset between requests. So now you can do something like:

class RequestContext < ActiveSupport::CurrentAttributes
  attribute :account
end

and then...

class Auth
  ...
  def call(env)
    RequestContext.account ||= Account.find(1)

    @app.call(env)
  end
end

I've never used it from a middleware - you may have to experiment with when the CurrentAttributes instance gets reset for each request (somewhere in the middleware stack? after the middleware stack?)


You can have a cattr_accessor :my_var in any model and set this variable from middleware by

  MyModel.my_var = 'something'

And you can access this anywhere in the application.


Have you tried creating a Ruby global variable?

def call(env)
  $account ||= Account.find(1)

  @app.call(env)
end

and

<%= debug $account %>
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜