ruby attr_accessor missing method - ruby-on-rails

New to RoR, I'm using the Carmen gem, running a rake gives me the error:
Failed: NoMethodError: undefined method `excluded_states=' for Carmen:Module
but the gem includes the attr_accessor method with :excluded_states in the args.
Doesn't the attr_accessor method automagically create the `excluded_states=' setter method?

You can't call attr_accessor within a module, that's something that should only work within a class. What you want instead is the mattr_accessor variant:
module MyModule
mattr_accessor :excluded_states
end
It's also possible it is defined correctly but you're referencing it incorrectly, as in you should be calling that on an instance of something.

Related

How to include a module in a class

A module in my gem is included in a class in another gem, which is extended by a custom class in a Rails app:
My gem:
module MyGem
def my_method
end
end
AnotherGem.send :include, MyGem
Another gem:
class AnotherGem
end
Class in Rails app:
class ClassInRailsApp < AnotherGem
end
Running this leads to the following behavior:
$ rails c
Loading development environment (Rails 5.1.4)
irb(main):004:0> MyGem.method_defined? :my_method
=> true
irb(main):005:0> AnotherGem.method_defined? :my_method
=> true
irb(main):006:0> ClassInRailsApp.method_defined? :my_method
NoMethodError: undefined method `my_method' for ClassInRailsApp:Class
How can I make sure my module is included before the class is extended?
EDIT:
I tried to directly include MyGem in ClassInRailsApp and the specified instance method is still not available. Could the issue be related to that?
In your thinking, you're just calling a method, e.g. #object.my_method. In reality, you're calling Class level method, e.g. Object.my_method, but have it defined as an instance level method. The correct way to do what you're trying would be Object.new.my_method, however, don't do that.
To call a method like this you'd have to define it as a method on the class. See this page, for a better understanding. Specifically the section "A Common Idiom" on how to define Class level methods via a module.

Calling a module's methods on a Gem's object?

I've generated an object via a ruby gem (Koala) and I've written a few modules with helper methods. What do I need to do in order to be able to use the methods within the modules on the object?
If I, model_object = Model.new, model_object will have access to all the instance variables but object does not (see below).
Ruby 2.1, Rails 4.1
config/application.rb - Autoloading modules in folder
config.autoload_paths << Rails.root.join('lib/module_folder')
Model
class Model < ActiveRecord::Base
include Module
include Module::Module2
include Module::Module3
def self.create_account(token)
object = Module.module_class_method(token) #this works and generates the Koala object
ERROR: object.module2_instance_method # Error: NoMethodError Exception: undefined method
end
end
Module
module Module
extend ActiveSupport::Concern
end
Module2
module Module
module Module2
def module2_instance_method
end
end
end
SOLVED MYSELF
- the issue was the include statements being within the class, if I moved them outside it worked.
I believe if you include your modules somewhere under the app/ directory - they will be included automatically. Otherwise, you actually have to require them in your rails code explicitly with a require statement
Without seeing the actual code, I think the problem with Module2 in your code snippet is the self. method.
Because you are calling module2_instance_method on an instance of your object, the method in the module cannot have the self. because that designates a class method and, as such, would have to be called as Module::Module2.module2_instance_but_not_really_because_I_am_a_class_method.
I believe if you change def self.module2_instance_method ... end to def module2_instance_method ... end, you should no longer receive the NoMethodError exception.
Apologies if I've misread or misunderstand the OP.
Moved the include statements from inside to above the class declaration and all methods began to work. My assumption is that when they are within the statement they are only available to objects of that class.

Why alias_method fails in Rails model

class Country < ActiveRecord::Base
#alias_method :name, :langEN # here fails
#alias_method :name=, :langEN=
#attr_accessible :name
def name; langEN end # here works
end
In first call alias_method fails with:
NameError: undefined method `langEN' for class `Country'
I mean it fails when I do for example Country.first.
But in console I can call Country.first.langEN successfully, and see that second call also works.
What am I missing?
ActiveRecord uses method_missing (AFAIK via ActiveModel::AttributeMethods#method_missing) to create attribute accessor and mutator methods the first time they're called. That means that there is no langEN method when you call alias_method and alias_method :name, :langEN fails with your "undefined method" error. Doing the aliasing explicitly:
def name
langEN
end
works because the langEN method will be created (by method_missing) the first time you try to call it.
Rails offers alias_attribute:
alias_attribute(new_name, old_name)
Allows you to make aliases for attributes, which includes getter, setter, and query methods.
which you can use instead:
alias_attribute :name, :langEN
The built-in method_missing will know about aliases registered with alias_attribute and will set up the appropriate aliases as needed.

Auto-create the containing module of a class

In Rails you can create a model under app/foo/bar.rb, with bar.rb containing:
class Foo::Bar
def some_method
puts "I work fine"
end
end
If you try to do this in a pure ruby app you'd get a NameError: uninitialized constant Foo unless you've already initialized a module Foo.
What is Rails doing that allows it to create classes without first initializing their containing module? Is it possible to import this behavior through something like activesupport, or are we left to implement on our own?
Rails modifies the Class class to include a const_missing method which gets called when an undefined class is used. It then loads things to try and load the requested class.
The implementation of this in ActiveSupport is in lib/active_support/dependencies.rb.
actually model class created is extend to < ActiveRecord::Base

rails models

i have a model named test.rb and when i use #tests=Test.new in my controller i get the following error. Can someone temme how can i resolve this?
"undefined method `new' for Test:Module"
Looks like test is already the name of a module called Test if would seem that you have naming conflict. Try placing your own model in a module ie
module MyModule
class Test < ActiveRecord::Base
end
end
and then calling it like so
#test = MyModule::Test.new

Resources