Forum: Ruby on Rails How do I access a variable defined in application.rb from within application.rhtml?

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Eric M. (Guest)
on 2009-02-21 22:46
(Received via mailing list)
Title pretty much explains it.  I'd like to set a variable the stores
a single Model object inside of application.rb since it will be used
on every single page.  I've tried both class and instance variables,
but to no avail.  The only thing that worked so far was using a global
($) variable.
Eric (Guest)
on 2009-02-21 23:42
(Received via mailing list)
So why not use that, then? Whatever works...

Also, you might brush up on MVC and beginner's Ruby as far as "setting
variables in models" go:
http://wiki.rubyonrails.org/rails/pages/Understand...
Eric M. (Guest)
on 2009-02-22 02:29
(Received via mailing list)
I don't generally follow the "whatever works..." approach because
there is usually a best practice.  That said, I want to avoid the
global variable because having $tidbit = Tidbit.random declared in my
application.rb broke my migrations.  Running migrations from version 0
when the Tidbits database doesn't exist caused the db:migrate to fail
because the line of code was still being executed and the Model was
attempting to access a table that didn't exist.

I'll keep reading, but I'm sure there is a logical way of
accomplishing this that I'm just not yet seeing.  Thanks.
bill walton (Guest)
on 2009-02-22 18:51
(Received via mailing list)
Hi Eric,

On Sat, 2009-02-21 at 12:45 -0800, ericindc wrote:
> Title pretty much explains it.  I'd like to set a variable the stores
> a single Model object inside of application.rb since it will be used
> on every single page.  I've tried both class and instance variables,
> but to no avail.  The only thing that worked so far was using a global
> ($) variable.

It sounds like, maybe you're setting it once in application.rb rather
than once per request/response cycle?  Instance variables (and IIRC
class variables too) have a one-cycle lifetime.  That would explain why
a global 'works'.

The 'typical' approach to setting an instance variable that's needed for
every render would be to add a before_filter in all your controllers
that invokes the application.rb method.

HTH,
Bill
Jeff B. (Guest)
on 2009-02-23 02:26
(Received via mailing list)
To initialize some db-read var (tidbit in your example) that would
survive and be callable for each subsequent app request, you'll want
to do so via lazy-initialization using a before_filter (mentioned by
bill) in application.rb.

How you store such lazy-init vars between requests depends on the
scope/use of such vars by users/requests of the app:

If the var that you're setting is specific to some user alone, and
should not be shared by all users' requests, then you could store that
var in the user's session:

# in ./app/controller/application.rb
  ...
  before_filter :do_lazy_init

  ...
  private

  def do_lazy_init
    session[:tidbit] = Tidbit.random if not session[:tidbit]
    @tidbit = session[:tidbit]
  end

which all of your app controller meths and view templates could then
use via @tidbit.

Note that such session vars can survive app restarts.  So if you
really want the var to be set at app start/restart, and/or you change
the structure/content of tidbit in the db, you'll want to clear such
session data first before re-starting your app.

If var that you're setting really is global in scope, intended to be
shared by all users' requests and is read-only, then you could store
it in a global var:

# in ./app/controller/application.rb
  ...
  before_filter :do_lazy_init

  ...
  private

  def do_lazy_init
    $global_tidbit = Tidbit.random if not $global_tidbit
    @tidbit = $global_tidbit
  end

Beware of issues surrounding use of global vars tho, and definitely
don't use mutable global vars, due to potential data incongruity
issues, especially when running production environment (assuming more
than one process-/thread-instance of your app in prod env).

If you're interested in Matz's opinion on use of global vars, per
quote in Ruby Pocket Ref (http://books.google.com/books?
id=KZU_HUYJ5yMC&pg=PA13&dq=ruby+matz+global+variables): "They're ugly,
so don't use them."

Jeff
Sarah Mei (Guest)
on 2009-02-23 05:38
(Received via mailing list)
For actual read-only data that is an instance of a model class, I'd
set up a class method instead. So for a default location, in
Location.rb,

def self.default_location
  @@default_location ||= Location.find_by_name("San Francisco")
end

This fixes your migration problem, doesn't reload it with every page,
and also works with testing.

On Sun, Feb 22, 2009 at 4:24 PM, Jeff L. <removed_email_address@domain.invalid>
wrote:
[...]
> If var that you're setting really is global in scope, intended to be
> shared by all users' requests and is read-only, then you could store
> it in a global var:
[...]
Tonypm (Guest)
on 2009-02-25 10:26
(Received via mailing list)
hi,
Ruby pocket reference looks useful, think I'll order a copy.
Regarding the class method, just wondering when/how this method should
get called.

Tonypm
Eric M. (Guest)
on 2009-02-27 22:08
(Received via mailing list)
Thanks, this sounds like what I need.
This topic is locked and can not be replied to.