Am I crazy?


#1

I swear this worked yesterday, but doesn’t work today.

I have a method in application.rb:

def img_types
[“jpeg”, “tiff”, “gif”, “eps”]
end

This is called from various controllers, e.g.,

if f.type in img_types

Shouldn’t that work?

Well, today it doesn’t. I changed it to

img_types = [“jpeg”, “tiff”, “gif”, “eps”]

No go. The only thing that works is

$IMG_TYPES =[“jpeg”, “tiff”, “gif”, “eps”]

Then I can say

if f.type in $IMG_TYPES

…but I didn’t have to do that yesterday.

Shouldn’t I be able to call the global method to return the array?

Am I crazy?


#2

I would expect the def case to work so long as it is not in the
private part of application_controller.rb. I would expect @img_types
= … to also work. I would not expect just img_types = … to work
as that is a local variable in the application_controller.rb object
and would quickly go out of scope when the class definition closes.

Michael

On May 2, 3:37 pm, Brian A. removed_email_address@domain.invalid


#3

How is it not working ?. Could you have defined a local variable/method
with the same name in your controller ?

Fred


#4

Frederick C. wrote:

How is it not working ?. Could you have defined a local variable/method
with the same name in your controller ?

Fred
I had img_types as a method. It worked (meaning I could call “img_types”
from controllers and it would return an the array). As of yesterday, it
doesn’t work. In fact, I have other “standalone” methods in
application.rb, and none of them work.

For example, I have a method that returns a modulo, which is used by
various controllers to determine a table name. Say that method is called
“bigweb_table_name”. It takes an integer and it returns a string. If I
fire up the console and enter

bigweb_table_name(255)

I get “undefined method”.

But I also have filter methods, like “check_user”. I can confirm that
they are running properly when called by controllers.

So, it seems that the methods in application.rb are not being loaded
when the application starts up.


#5

OK, so I created a new dummy app. Here’s the entire application.rb file:

class ApplicationController < ActionController::Base

Pick a unique cookie name to distinguish our session data from

others’
session :session_key => ‘_test_session_id’

def msg
return “msg”
end

$IMG_TYPE =“img_type”

end

I go into the console, and type

msg

and get

NameError: undefined local variable or method `msg’ for
#Object:0x1f69f4
from (irb):1

I type

$IMG_TYPE

and get

“img_type”

If I can’t put global methods in application.rb, where do I put them,
and how do I call them? And shouldn’t this work? Is there anyplace I can
see where Rails is looking for this method?


#6

On May 3, 4:28 pm, Brian A. removed_email_address@domain.invalid
wrote:

If I can’t put global methods in application.rb, where do I put them,
and how do I call them?

This is where helpers come in. Assuming you want this method to be
available to all of your controllers, you’d put it in app/helpers/
application_helper.rb

module ApplicationHelper
def msg
return “msg”
end
end

Once you’ve done that, you can call msg in any controller or view in
your app. Note that you’re still going to get an error if you type
“msg” at the console, but the method will be globally available from
within any controller or view. If you truly want the method to be
global you’ll need to put it in a library - but I don’t think that’s
really what you’re after.

-Bill


#7

Brian A. wrote the following on 03.05.2007 22:28 :

NameError: undefined local variable or method `msg’ for
#Object:0x1f69f4
from (irb):1

This should be your hint, try :
class Object
def msg
return “msg”
end
end
in environment.rb for example.

But this isn’t really what you want.


#8

On 3-May-07, at 4:28 PM, Brian A. wrote:

return "msg"

and get

“img_type”

If I can’t put global methods in application.rb, where do I put them,
and how do I call them? And shouldn’t this work? Is there anyplace
I can
see where Rails is looking for this method?

Brian, when you run the console, you’re not in a request/response
cycle - IE you don’t have access to Controllers.

If you wanted, you could test your settings within a functional test

  • which simulates the browser/server cycle.

The methods you place in application.rb will be available to other
controllers. Create another controller and action - then refer to them.

I may have come into this conversation late - as I don’t know what
you’re trying to do.

Cheers,
Jodi
General Partner
The nNovation Group inc.
www.nnovation.ca/blog


#9

Brian, when you run the console, you’re not in a request/response
cycle - IE you don’t have access to Controllers.

If you wanted, you could test your settings within a functional test

  • which simulates the browser/server cycle.

The methods you place in application.rb will be available to other
controllers. Create another controller and action - then refer to them.

I may have come into this conversation late - as I don’t know what
you’re trying to do.

Cheers,
Jodi
General Partner
The nNovation Group inc.
www.nnovation.ca/blog

I appreciate all the responses. I know that there’s a difference between
the console and the “live” app, but this all started because my live app
unexpectedly began throwing the ‘method undefined’ error. I will do some
testing via other means, but it’s unfortunate that the console
environment is unaware of methods defined in the global application
controller.


#10

On 5/3/07, Brian A. removed_email_address@domain.invalid wrote:

I appreciate all the responses. I know that there’s a difference between
the console and the “live” app, but this all started because my live app
unexpectedly began throwing the ‘method undefined’ error. I will do some
testing via other means, but it’s unfortunate that the console
environment is unaware of methods defined in the global application
controller.

Given your initial post I suspect you’re confused about class vs.
instance methods, and perhaps some other scoping rules as well.

If you’re new to ruby and/or oop, I suggest you sit down with a good
book, e.g. ‘programming ruby’ or ‘ruby for rails’.

HTH,
Isak


#11

Brian A. wrote the following on 03.05.2007 00:37 :

if f.type in img_types
$IMG_TYPES =[“jpeg”, “tiff”, “gif”, “eps”]

These image types should probably linked with a class. You probably have
an Image class or something like it with an attribute which should be
included in these values. The proper way to code this should be to have
:

class Image
VALID_TYPES = [ “jpeg”, “tiff”, “gif”, “eps”]
end

Then when you need to check a value, you’ll have to do:

Image::VALID_TYPES.include? value

If for example your Image class is derived from ActiveRecord::Base with
a image_type, you’ll probably want something like:

class Image < ActiveRecord::Base
VALID_TYPES = [ “jpeg”, “tiff”, “gif”, “eps”]

validates_inclusion_of :image_type, VALID_TYPES

end

VALID_TYPES is a constant defined in the Image class, in the Image
context you can use “VALID_TYPES”, in another context you need the
“Image::VALID_TYPES” syntax to enforce the proper context.

Lionel.


#12

If I can’t put global methods in application.rb, where do I put them,
and how do I call them? And shouldn’t this work? Is there anyplace I can
see where Rails is looking for this method?

Maybe you just need to give ruby an object to send this method to?

C:\rails\test>ruby script/console
Loading development environment.

self.class
=> Object

msg
NameError: undefined local variable or method `msg’ for #<Object:
0x284fa38>
from (irb):2

a = ApplicationController.new
=> #ApplicationController:0x48c3ad0

a.msg
=> “msg”


#13

Given your initial post I suspect you’re confused about class vs.
instance methods, and perhaps some other scoping rules as well.

If you’re new to ruby and/or oop, I suggest you sit down with a good
book, e.g. ‘programming ruby’ or ‘ruby for rails’.

HTH,
Isak

It may seem that way, but while not a pro by any means, I think I have a
fairly good grasp of all this. I’ve been working with Ruby for about two
years, and Rails for about 9 months.

The reason I asked “Am I crazy?” is because this makes no sense, and I’m
not sure if I understand it correctly. Whether my defining this method
in the application controller makes for good programming or not, the
question was, should it work? It seems the answers is, yes, it should,
regardless of my particular abuse of it.

I am (was?) sure this did work until 3 days ago. Suddenly, no. Am I
crazy?


#14

On 5/4/07, Brian A. removed_email_address@domain.invalid wrote:

Isak

I am (was?) sure this did work until 3 days ago. Suddenly, no. Am I
crazy?

It makes perfect sense. There’s no way it could have worked 3 days ago.

ggironda$ script/console
Loading development environment.

self.class
=> Object

IRB, and by extension, script/console boot you into the top level. Any
methods defined in individual classes are just that - defined in their
individual classes. It would make no sense for script/console to boot
you into the context of an instance of ApplicationController.

Something like what you want to achieve can be accomplished like this:

ggironda$ script/console
Loading development environment.

x = ApplicationController.new
=> #ApplicationController:0x380389c

irb x
self.class
=> ApplicationController

From that point, you’d be able to call the “msg” method. Not being
able to access that method by default makes complete sense - it’s an
instance method on a class that doesn’t have an instance around yet,
and even when instantiated, you need to force IRB to be in the context
of that instance.

For “msg” to be available “everywhere”, you want to define it on
module Kernel or class Object:

class Object; def msg; “msg” end; end
=> nil

msg
=> “msg”

module Kernel; def other_msg; “other” end; end
=> nil

other_msg
=> “other”

This, however, is of questionable programming practice. Hope that
cleared things up.

  • Gabriel

#15

I’ve had similar issues. I’ve noticed that actually explicitly
calling “return” often fixes the issue:

def img_types
return [“jpg”,“png”,“gif”]
end

HTH,
Michael

On May 2, 6:37 pm, Brian A. removed_email_address@domain.invalid


#16

Hi –

On 5/2/07, MichaelLatta removed_email_address@domain.invalid wrote:

I would expect the def case to work so long as it is not in the
private part of application_controller.rb. I would expect @img_types
= … to also work. I would not expect just img_types = … to work
as that is a local variable in the application_controller.rb object
and would quickly go out of scope when the class definition closes.

The first two cases actually work the other way around :slight_smile: A private
instance method of ApplicationController will be callable by the
subclasses (the other controllers). If you define an instance variable
out in the open:

class AC < AC::Base
@img_types = [a,b,c]
end

that won’t be visible to the other classes (since they’re different
objects and instance variables are per-object).

David


Upcoming Rails training by Ruby Power and Light:
Four-day Intro to Intermediate
May 8-11, 2007
Edison, NJ
http://www.rubypal.com/events/05082007


#17

On May 2, 5:37 pm, Brian A. removed_email_address@domain.invalid
wrote:

if f.type in img_types

Shouldn’t that work?

if foo in bar is not valid syntax.

defining an instance method in Application Controller should make it
available in the child controllers.

However, as this information is constant and probably related to your
data model rather than your presentation, I would suggest using a
constant in the appropriate model.

For instance, if you have an Image model, you would do:

class Image

FILE_TYPES = %w( jpeg tiff gif eps ).freeze

and then use it as:

Image::FILE_TYPES.include? f.type


#18

Brian: Stay cool, you are okay.

Others: Jesus, why in the hell most guys out there are not listening
careful to a simple, reasonable and important question?? This is not
about IRB, or how to do it in a different way. And suggestions like
“read a good book” are not helpful at all, btw. This is about name
scopes, and what we need is a precise definition here.

David: What you say matches the documentation and it makes sense.
Furthermore, you WROTE a good book.

In the Rails application I am currently working on I have created a
method in the application controller. I cannot call it in any other
controller, neither as a private nor as a public method.

After having created a completely new Rails application I did the same
thing. Now I could call it successfully. Private or public, it does
not make any different.

With other words: Rails is behaving inconsistent. Bad news. And it
might very well explain why it worked the other day in Brians
application but stopped doing so 3 days later.