18
$request = request

When I write this in controller, it will work. But if i need this variable in Model or Application controller, How can i ?

Sreeraj
  • 2,690
  • 6
  • 26
  • 37
  • You have said you want to know the URI in all your classes. Usually it's a bad idea and it may be a sign of bad design decisions. Of course, it is possible, but why do you want this? – Arsen7 Jun 10 '11 at 14:58
  • Do you want to record what page is being accessed at what time by which user, or something like that? – bpaulon Jun 11 '11 at 06:33
  • Hi i got and posted the answer – Sreeraj Jun 11 '11 at 06:44

6 Answers6

16

Models exist outside the context of a web request. You can instantiate them in irb, you can instantiate them in a delayed job, or a script, etc. If the model depended on the request object, none of these things would be possible.

As tsdbrown says, you have to somehow pass in that information from the context that uses the model.

aNoble
  • 7,033
  • 2
  • 37
  • 33
DGM
  • 26,629
  • 7
  • 58
  • 79
  • i am planning catch it in a global varaible. Is tha t possible with out DRY? – Sreeraj Jun 10 '11 at 14:11
  • That's not the recommended way... better to just have a setter method on the model that the controller can call to set it. – DGM Jun 10 '11 at 14:13
  • Check out this article: http://www.zorched.net/2007/05/29/making-session-data-available-to-models-in-ruby-on-rails/ – DGM Jun 10 '11 at 14:15
  • is there any way to know the running url inside Lib class? – Sreeraj Jun 10 '11 at 14:24
  • 1
    no. It's only available inside controller objects, and views that the controller sets up. – DGM Jun 10 '11 at 14:30
14

I got it

class ApplicationController < ActionController::Base
  protect_from_forgery

  before_filter :beforeFilter

  def beforeFilter
     $request = request
  end  
end

Now we can use the $request global variable anywhere in the code

Sreeraj
  • 2,690
  • 6
  • 26
  • 37
  • 1
    Brilliant. This is a nice solution. Models can access it when modified from a request, and it's nil when modified from console/background process. This is exactly what I was looking for and is the DRYest approach I think. – Brian Armstrong Jul 18 '12 at 09:23
  • 1
    Found another approach to this - http://stackoverflow.com/questions/5197154/how-to-get-the-actual-http-request-from-a-model-in-rails-3 - Any ideas which one is better? – jesal Aug 02 '12 at 22:38
  • 4
    Definitely the Thread[:current] one. It's very possible that Rails could be executing multiple threads per request, especially in the j-ruby environment where there's no GIL. – John K. Chow Mar 12 '13 at 23:11
  • Tried this and it is only setting the $request variable to nil. any ideas on what's going on? – afxjzs Mar 26 '13 at 20:54
  • 20
    Although this works it is not brilliant. Global variables are dangerous. It would be better to follow the other advice in this thread and have the controller pass information about the current request directly to other levels. – gerryster Aug 08 '13 at 14:15
  • 1
    This is exactly opposite of brilliant. Do not use global variables. Consider making a new presenter object that does whatever you need done, passing in both the request context and the model instance. This presenter class can then have the sole responsibility of presenting whatever it is that needs elements of the request and model. – DGM Jan 31 '14 at 02:02
  • How can You use global variable this way ? – Benjamin Harel Feb 16 '16 at 14:11
8

You do not have access to the request object in your models, you will have to pass the request.request_uri in.

Perhaps via a custom method. e.g. @object.custom_method_call(params, request.request_uri)

Another option would be add an attr_accessor :request_uri in your model and set/pass that in:

@object.update_attributes(params.merge(:request_uri => request.request_uri))
tsdbrown
  • 5,038
  • 3
  • 36
  • 40
5

if you use rails > 5.0, you can do below

add a module in models/concern

module Current
  thread_mattr_accessor :actor
end

in applicaton_controller do

around_action :set_thread_current_actor

  private

  def set_thread_current_actor
    Current.actor = current_user
    yield
  ensure
    # to address the thread variable leak issues in Puma/Thin webserver
    Current.actor = nil
  end

then in thread anywhere get current_user

Current.actor
wuyuedefeng
  • 61
  • 1
  • 4
1

you will need to do a hack to get request.uri in the model. which is not recommended. You should pass it as a params in the method which is defined in the model.

Manish Puri
  • 422
  • 4
  • 6
1

For Rails 5, you need to use before_action instead.

Robert Columbia
  • 6,313
  • 15
  • 32
  • 40
William
  • 61
  • 3