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 %>
精彩评论