I am trying to include a module into my resque worker but I keep getting this error -
failed: #<NoMethodError: undefined method `build_page' for RefreshEventCache:Class>
The worker - /app/worker/refresh_event_cache.rb
require File.dirname(__FILE__) + '/../../lib/locomotive/render.rb'
class RefreshEventCache
include Resque::Plugins::UniqueJob
include Locomotive::Render
#queue = :events_queue
def self.perform(url)
build_page(url)
end
end
The Module - /lib/locomotive/render.rb
module Locomotive
module Render
extend ActiveSupport::Concern
module InstanceMethods
def build_page(full_path)
Rails.logger.debug "BUILDING PAGE"
end
end
end
end
Any ideas ?
Have you tried to add the extend ActiveSupport::Concern to the main module Locomotive like this:
module Locomotive
extend ActiveSupport::Concern
module Render
module InstanceMethods
def build_page(full_path)
Rails.logger.debug "BUILDING PAGE"
end
end
end
end
Just guessing,... Ive used the extension with single modules but this seems to be logical for me.
Related
I'm writing a Rails plugin to extend a Rails engine. Namely MyPlugin has MyEngine as a dependency.
On my Rails engine I have a MyEngine::Foo model.
I'd like to add new methods to this model so I created a file in my plugin app/models/my_engine/foo.rb which has the following code:
module MyEngine
class Foo
def sayhi
puts "hi"
end
end
end
If I enter the Rails console on the plugin dummy application I can find MyEngine::Foo, but runnning MyEngine::Foo.new.sayhi returns
NoMethodError: undefined method `sayhi'
Why MyPlugin cannot see the updates to MyEngine::Foo model? Where am I wrong?
Ok, found out. To make MyPlugin aware and able to modify MyEngine models the engine must be required on the plugin engine.rb like so:
require "MyEngine"
module MyPlugin
class Engine < ::Rails::Engine
isolate_namespace MyPlugin
# You can also inherit the ApplicationController from MyEngine
config.parent_controller = 'MyEngine::ApplicationController'
end
end
In order to extend MyEngine::Foo model I then had to create a file lib/my_engine/foo_extension.rb:
require 'active_support/concern'
module FooExtension
extend ActiveSupport::Concern
def sayhi
puts "Hi!"
end
class_methods do
def sayhello
puts "Hello!"
end
end
end
::MyEngine::Foo(:include, FooExtension)
And require it in config/initializers/my_engine_extensions.rb
require 'my_engine/foo_extension'
Now from MyPlugin I can:
MyEngine::Foo.new.sayhi
=> "Hi!"
MyEngine::Foo.sayhello
=> "Hello!"
See ActiveSupport Concern documentation for more details.
I have a module in lib folder. Where I have created a InstanceMethods module.
require 'memoist'
extend Memoist
module MyStudentMethods
def self.included base
base.send :include, InstanceMethods
end
module InstanceMethods
def find_student(user_id)
self.student.find{|student| student.user_id == user_id }
end
memoize :find_student
end
end
I am using this module in my model.
require_dependency 'my_student_methods'
class Student < ActiveRecord::Base
# previously I was using memoize like below commented out code
# require 'memoist'
# extend Memoist
include MyStudentMethods
end
But when I start rails server it through an error:
/home/Projects/school/lib/my_student_methods.rb:12:in `<module:InstanceMethods>': undefined method `memoize' for MyStudentMethods::InstanceMethods:Module (NoMethodError)
Issue: How can I memoize the module method?.
Try moving extend Memoist into your module. Like this:
module InstanceMethods
extend Memoist
...
module InstanceMethods
extend Memoist
...
I am trying to create a gem to extend Rails ActionView Renderer to print an HTML comment with the partial view name bring rendered.
I tried the normal way:
module MyGem
class Engine < ::Rails::Engine
initializer 'mygem.initialize' do
::ActiveSupport.on_load(:action_view) do
::ActionView::Renderer.send :include, MyGem::ViewRenderer
end
end
end
end
And then in mygem/lib/view_renderer.rb:
module MyGem
module ViewRenderer
module InstanceMethods
def render(context, options)
puts "here" # Just to test it was included and it doesn't print
if options.key?(:partial)
render_partial(context, options)
else
render_template(context, options)
end
end
end
def self.included(base)
base.send :include, InstanceMethods
end
end
end
However, when I use render from my views, the test line added doesn't work.
Any idea what am I doing wrong?
This is how I have done it in the past, maybe it will help.
module MyModule
def self.included(base)
def render
#do stuff
end
end
end
ActionController::Base.send :include, MyModule
Then just require the file
I have developed two plugins and they both modify the same method of the same class via alias_method_chain that result into stack level too deep error.
first plugin:
Rails.configuration.to_prepare do
require 'issue_patch'
Issue.send :include, IssuePatch
end
module IssuePatch
module InstanceMethods
def editable_custom_field_values_with_sort(user=nil)
editable_custom_field_values_without_sort(user).sort
end
end
def self.included(receiver)
receiver.send :include, InstanceMethods
receiver.class_eval do
alias_method_chain :editable_custom_field_values, :sort
end
end
end
Second plugin modify the class same way but with different feature:
Rails.configuration.to_prepare do
require 'issue_patch'
Issue.send :include, IssuePatch
end
module IssuePatch
module InstanceMethods
def editable_custom_field_values_with_some_stuff(user=nil)
editable_custom_field_values_without_some_stuff(user).select { |c| c.have_stuff? }
end
end
def self.included(receiver)
receiver.send :include, InstanceMethods
receiver.class_eval do
alias_method_chain :editable_custom_field_values, :some_stuff
end
end
end
When I trying to call this method I got:
ActionView::Template::Error (stack level too deep):
plugins/my_plugin/lib/issue_patch.rb:8
One possible but hack solution is simple monkey patch the redmine code with first plugin feature so the second plugin can alias it without any error.
So how I can fix this error?
The problem was:
I define two modules with the same name IssuePatch so the first module overwrites the second but
Issue.send :include, IssuePatch
still exists in 2 places (for each plugin) and the same module (doesn't matter which one overwrites the other) so the same module were included 2 times and the same alias_method_chain were called 2 times.
The solution: I just add separate module for each plugin and included them like this:
Issue.send :include, FirstPlugin::IssuePatch
Issue.send :include, SecondPlugin::IssuePatch
I have a custom plugin (I didn't write it) that is not working on rails 3, however it did work with rails 2. It is for a custom authentication scheme, here is what the main module looks like:
#lib/auth.rb
module ActionController
module Verification
module ClassMethods
def verify_identity(options = {})
class_eval(%(before_filter :validate_identity, :only => options[:only], :except => options[:except]))
end
end
end
class Base
#some configuration variables in here
def validate_identity
#does stuff to validate the identity
end
end
end
#init.rb
require 'auth'
require 'auth_helper'
ActionView::Base.send(:include, AuthHelper)
AuthHelper contains a simple helper method for authenticating, base on a group membership.
When I include 'verify_identity' on an actioncontroller:
class TestController < ApplicationController
verify_identity
....
end
I get a routing error: undefined local variable or method `verify_identity' for TestController:Class. Any ideas how I can fix this? Thanks!
It worked in 2.3 because there was an ActionController::Verification module back there. It's not working in 3.0 because this module doesn't exist. Rather than relying on Rails to have a module that you can hook into, define your own like this:
require 'active_support/concern'
module Your
module Mod
extend ActiveSupport::Concern
module ClassMethods
def verify_identity(options = {})
# code goes here
end
end
end
end
and use:
ActionController::Base.send(:include, Your::Mod)
To make its functions available. ActiveSupport::Concern supports you having a ClassMethods and InstanceMethods module inside your module and it takes care of loading the methods in these modules into the correct areas of whatever the module is included into.