Extend model in plugin with has_many using a module
I think this should work
module Qwerty
module Core
module Extensions
module User
# Instance Methods Go Here
# Class Methods
module ClassMethods
def relate
has_many :hits, :uniq => true # no method found
before_validation_on_create :generate_code # no method found
end
def something # works!
"something"
end
end
def self.included(base)
base.extend(ClassMethods).relate
end
end
end
end
end
The old code is wrong cause the validation and the association are called upon module loading, and this module knows nothing about ActiveRecord. That's a general aspect of Ruby, code inside class or module bodies is called directly when loaded. You don't want that. To get around that you can use the above solution. Polymorphic :has_many, :through as module in Rails 3.1 plugin
It turns out that adding :class_name to both :has_many definitions will actually work (someone commented on that, but they deleted their comment). It didn't work in my non-simplified program because of something else in my program that was causing a cascading error that SEEMED to be local to the :has_many definition.
Short story: It was a lot of trouble for something that wasn't actually a problem. Blech
How do I extend a model in Rails?
The problem you have now is that you are extending your class, not including a module into it, so the Sicada::Extensions::UbiquoUser#included
method never gets called.
To fix this, change this line:
UbiquoUser.send(:extend, Sindicada::Extensions::UbiquoUser)
to UbiquoUser.send(:include, Sindicada::Extensions::UbiquoUser)
How to extend a model in a Rails engine from another Rails engine?
Turns out I can do the following in the tickets_engine:
# contrived_app/vendor/plugins/tickets_engine/config/initializers/concert_extensions.rb
# or
# contrived_app/config/initializers/concert_extensions.rb
Rails.logger.info "\n~~~ Loading extensions to the Concert model from #{__FILE__}\n"
Concert.class_eval do
has_many :tickets
end
Personally, my preferred method is to extend the concert model from the tickets_engine, but load order and dependencies are important. i.e. tickets_engine would need to add a dependency on the concerts_engine in it's gemspec, and concert_engine would need to be loaded before tickets_engine. How to extend a class from an initializer and have it reload in development environment?
environment.rb
config.to_prepare do
User.send :include, Qwerty::Core::Extensions::User
end
The code is the block is run before every request in development mode and once in production mode. Extend instance method of model
include
is a private method and cannot have an explicit receiver. You can get around this limitation by using send
:
MyModel.send(:include, InstanceMethods)
Related Topics
How to Catch an "Undefined Method '[]' for Nil:Nilclass" Error
How to Stub/Mock a Call to The Command Line with Rspec
Filtering Sensitive Data with Vcr
Rails How to Tell If a Sidekiq Worker Is Done with Perform_Async
Parsing a CSV File Using Different Encodings and Libraries
How to Validate Overlapping Times in Rails with Postgresql
More Ruby Way of Doing Project Euler #2
Puzzled Over Palindromic Product Problem
How to Handle Serialized Edit Fields in an Active Admin Resource
How to Fix a Deadlock in Join() in Ruby
Ruby Interpreter (Cui) 1.9.2P180 [I386-Mingw32] Has Stopped Working (I Am Not Using MySQL )
Regex That Matches Valid Ruby Local Variable Names
Server Sent Events and Rails Streaming
How to Handle Single Table Inheritance in Simpleform So a Single Helper Handles All Models