Ruby NoMethodError - ruby-on-rails

Ok, I'm a bit of a newb. I know this error is occuring because I don't properly understand something about how methods are called. So can you help me understand what is going wrong here?
NoMethodError in ThingController#index
undefined method `initialized?' for Thing::Backend:Class
From the erroring section of ThingController.rb:
class ThingController
def init_things
Backend.init_things unless Backend.initialized?
end
t = ThingController.new
t.init_things
end
inside Backend.rb
class Backend
# checks if the things hash is initialized
def initialized?
#initialized ||= false
end
# loads things
def init_things
puts "I've loaded a bunch of files into a hash"
#initialized = true
end
end
I'm not calling the method correctly and I cannot find any clear explanations for this error on the internet. Please help.
Thanks

It appears that the issue is that the initialized method that you have declared in Backend is an instance method. When you then call Backend.initialized? you are calling calling the class method initialized? for the Backend class. This method is not defined, and so it raises the NoMethodError. You can solve this by declaring the method using def self.initialized?. If you really want this to be a class method, you may need to consider how the rest of your code is organized.
You can find more information on class vs. instance methods at http://railstips.org/blog/archives/2009/05/11/class-and-instance-methods-in-ruby/

You've declared initialized? as an instance method but are calling it as if it were a class method. Here's an explanation of the difference between instance methods and class methods.

Related

How to create this model meta method?

I used to have the following model method, which I called upon using if #invitation.invite_expired? ...:
def invite_expired?
cycle_invite_sent_at < 2.hours.ago
end
Because I want to use this method for multiple expiration checks I have tried to create a "meta" method as follows:
def expired?(what)
check = send("#{what}_invite_sent_at")
check < 2.hours.ago #Also tried "self.check" but that made no difference.
end
I call upon this method using: if #invitation.expired?(cycle) .... However, now all sorts of tests fail with the message:
NameError: undefined local variable or method `cycle' for #<InvitationsController:0x0000000a5e8d50>
Does anyone see what I'm doing wrong here?
You should use it like:
if #invitation.expired?("cycle")
# some code here.
I assume this because undefined local variable or method 'cycle' raised in the controller code, it happens, when you try to use plain cycle instead of a string "cycle".

What does MyApp::Application.initialize! calling?

I am trying to figure out the initialization of rails 3. And i know that every application will calling the following function in environment.rb to initialize the whole app:
MyApp::Application.initialize!
From it we should expect that initialize! is a class method of Rails::Application. But after i red the source code, i found that instead initialize! is an instance method which is actually called:
def initialize!(group=:default) #:nodoc:
raise "Application has been already initialized." if #initialized
run_initializers(group, self)
#initialized = true
self
end
So why is the instance method called although we expect a class method? Is there some trick like method delegation or else?
Yes. there is a little trick delegation. if you look at file lib/rails/railtie/configurable.rb in railties gem you will see following code that delegates to instance.
def method_missing(*args, &block)
instance.send(*args, &block)
end
in case you are not aware of method_missing hook, you can read up more about it here: http://rubylearning.com/satishtalim/ruby_method_missing.html

NameError: undefined local variable or method `desired_preferences'

I have created a module with a method
module Adding_preferences
def desired_preferences
#preference = %w(motabilitySpecialist newCars bodyshop filter8 filter7).each do |selection|
#browser.label(:for, selection ).click
end
end
end
I have included this module into a class:
class Pages
include Adding_preferences
attr_accessor :browser, :preference
def initialize
#browser = Watir::Browser.new :ff
end
end
World do
Pages.new
end
I am calling this method in a Cucumber scenario
When /^I select a desired preference$/ do
desired_preferences
end
But at runtime I receive an error, "NameError: undefined local variable or method `desired_preferences'". Where am i going wrong?
When you include a module to a class you can use this method in the instance methods of this class. You cant call the included method in a View that displays the data from the model that includes the module. For me it looks like you just dont use the desired_preferences method in an instance method.
Please show us the peace of code you try to call the method if this still doesnt help you out.
// The naming of the Module is not conventional. You should call it module AddingPreferences isntead ofmodule Adding_preferences and the file should be named adding_preferences.rb then try to include AddingPreferences
It's a good idea for you to spend some time getting more familiar with Ruby's Class/Module/Object/Method inheritance model, because the way you're structuring your code there is a little bit messy.
However, a simple thing to try (and I'm not going to guarantee that it will work flawlessly) is the following modifications:
Assign your instantiated Pages class to a class instance variable:
World do
#page = Pages.new
end
...and then use that instance variable in your step definition...
When /^I select a desired preference$/ do
#page.desired_preferences
end
I hope that helps!

How can I stub a before_filter in a super class in Rails?

I'm using RR for mocking and stubbing in RSpec, and I've run across a situation where I'd like to stub a method from a super class of a controller that sets some instance variables. I can work out how to stub the method call and if I debug I can see that my stubbed block is called, but I cannot get the instance variables in the block to propagate into the class I'm testing.
Just to break it down :
class A < ApplicationController
before_filter :bogglesnap
def bogglesnap
#instancevar = "totally boggled"
end
end
class B < A
def do_something_with_instance
if #instancevar
....
else
....
end
end
end
That's the basic setup, and so then in my tests for controller B I'd like to stub out the bogglesnap method from A to set #instancevar to something I want. I just can't figure out how to do it.
I've tried RR's instance_of stubbing and just stubbing out the controller definition :
stub.instance_of(A).bogglensap { #instancevar = "known value" }
stub(controller).bogglesnap { #instancevar = "known value" }
but neither of these seem to work, well, they don't work :)
Does anyone have any pointers on how you should be able to stub that method call out and have it set instance variables? I'm assuming it has to do with the context in which the block is run but am hoping someone has run across something like this before.
Thanks
You can use instance_variable_set method by calling on the object instance and set it to whatever you want, like so
controller.instance_variable_set("#instancevar", "known value")
and similarly, if you ever want to fetch the value of an instance variable in your spec or debug or do something else from outside the class then you can get the value by doing
controller.instance_variable_get("#instancevar")
Mind you, instance_variable_set and instance_variable_get methods are available not only to controllers but all objects as it is provided by ruby. Infact, these two methods play an important role in rails magic :)

Can I define_method in rails models?

My rails model has code that is attempting to define_method(method_name) inside the model.
I keep getting:
NoMethodError: undefined method `define_method'
What am I doing wrong? Am I doing this in the wrong place. I need this method attached to this model. Where else can I define this method?
EDIT:
For those asking to see the code:
for field in rdev_fields
next if self.attributes.include?(field)
count = count + 1
rdev_hash[field.to_sym] = self.attributes["attribute#{count}"]
if !self.respond_to?(field) then
define_method("#{field}") do
self.send("attribute#{count}".to_sym)
end
end
end
There's nothing magical or about a rails model, it's just a normal class with a bunch of pre-existing methods,
So, the question is "can I define_method in a class"?
Part 1: Yes you can.
The important distinction is than you can define method in a class not in an instance method
For example:
class Cow
define_method "speak" do
"MOOOO"
end
end
Cow.new.speak
=> "MOOOO"
This should work fine. Note you're defining it on the class Cow, so any other Cows that you already have will automatically get that method added.
Part 2: What do you do if you want to define a method from within an instance method?
You can't define methods from an instance method, so you have to grab the class, and use that to define the method. Like this:
class Cow
def add_speak
self.class.send(:define_method, :speak) do
"MOOOO added"
end
end
end
Cow.new.speak
NoMethodError: undefined method 'speak' for #<Cow:0xb7c48530>
Cow.new.add_speak
Cow.new.speak
=> "MOOOO added"
Problem solved. Astute readers will note that in this example I'm using send(:define_method) - this is needed because define_method is private, and private methods are only accessible to the thing they're in. In this case, define_method is in the class, we are in the instance, so we can't directly access it.
As above though, we're adding the method directly to the class, so all other Cows which already exist will automatically also get the speak method added.
Part 3: What do you do if you want to define a method for only 1 object, not all objects of that class?
Example:
class Cow
def add_speak_just_me
class << self
define_method "speak" do
"MOOOO added for just me"
end
end
end
end
Cow.new.speak
NoMethodError: undefined method 'speak' for #<Cow:0xb7c72b78>
c = Cow.new
c.add_speak_just_me
c.speak
=> "MOOOO added for just me" # it works, hooray
Cow.new.speak # this new cow doesn't have the method, it hasn't been automatically added
NoMethodError: undefined method `speak' for #<Cow:0xb7c65b1c>
How does this work? Down the rabbithole you go!
Read this: http://dannytatom.me/metaid/ and good luck. It helps when you realise that 'adding a method' to an instance isn't actually adding it to the instance at all :-)
If you came here searching for how to dynamically define a CLASS method, because define_method wasn't working (because it defines INSTANCE methods), here is your answer:
Use define_singleton_method :)
was able to cobble this together. Very little understanding of what's actually going on though.
My instance method foo is opening the class and defining bar on it so that I can then call that on my instance. More experienced folks will let us know if this is opening a can of worms at the same time.
Would be useful to know your specific use for this though.
class User < ActiveRecord::Base
def foo
(class << self; self; end).class_eval do
define_method(:bar) {puts "bar"}
end
end
end
u = User.first
u.foo
u.bar #=> "bar"
The answer to your question is "yes, you can". As for why it's not working for you - it's impossible to say for sure why, if you don't provide some context for the code.

Resources