I'm trying to create a concern inside an engine in order to add/override this functions in the main application which is going to mount this engine. The problem is that I have had problems including the concern in the engine module. It seems that Rails can't find it.
This is my post.rb
file in app/models/blorgh/post.rb
:
module Blorgh
class Post < ActiveRecord::Base
include Blorgh::Concerns::Models::Post
end
end
And this is my post.rb
concern in lib/concerns/models/post.rb
:
require 'active_support/concern'
module Concerns::Models::Post
extend ActiveSupport::Concern
# 'included do' causes the included code to be evaluated in the
# conext where it is included (post.rb), rather than be
# executed in the module's context (blorgh/concerns/models/post).
included do
attr_accessible :author_name, :title, :text
attr_accessor :author_name
belongs_to :author, class_name: Blorgh.user_class
has_many :comments
before_save :set_author
private
def set_author
self.author = User.find_or_create_by_name(author_name)
end
end
def summary
"#{title}"
end
module ClassMethods
def some_class_method
'some class method string'
end
end
end
When I run the test/dummy, I got the this error: uninitialized constant Blorgh::Concerns
This is my blorgh.gemspec:
$:.push File.expand_path("../lib", __FILE__)
# Maintain your gem's version:
require "blorgh/version"
# Describe your gem and declare its dependencies:
Gem::Specification.new do |s|
s.name = "blorgh"
s.version = Blorgh::VERSION
s.authors = ["***"]
s.email = ["***"]
s.homepage = "***"
s.summary = "Engine test."
s.description = "Description of Blorgh."
s.files = Dir["{app,config,db,lib}/**/*"] + ["MIT-LICENSE", "Rakefile", "README.rdoc"]
s.test_files = Dir["test/**/*"]
s.add_dependency "rails", "~> 3.2.8"
s.add_dependency "jquery-rails"
s.add_development_dependency "sqlite3"
end
Can someone help me with this?
A Rails Concern is a module that extends the ActiveSupport::Concern module. Concerns allow us to include modules with methods (both instance and class) and constants into a class so that the including class can use them. The code inside the included block is evaluated in the context of the including class.
Rails looks first in the application's ( test/dummy ) app/views directory and then in the engine's app/views directory. When it can't find it, it will throw this error. The engine knows to look for blorgh/comments/_comment because the model object it is receiving is from the Blorgh::Comment class.
The well-known devise gem , for example, is based on Rails engines. But what is it exactly? Well, simply put a Rails engine is the miniature edition of a Rails application. It comes with an app folder, including controllers, models, views, routes, migrations...
When using engines, you need to keep track of the load order, especially when changing behavior of the main app. Suppose your engine is called "engine_name", you should have this file: engine_name/lib/engine_name/engine.rb. This is one place to include your Concerns.
Bundler.require
module EngineName
class Engine < ::Rails::Engine
require 'engine_name/path/to/concerns/models/post'
initializer 'engine_name.include_concerns' do
ActionDispatch::Reloader.to_prepare do
Blorgh::Post.send(:include, Concerns::Models::Post)
end
end
# Autoload from lib directory
config.autoload_paths << File.expand_path('../../', __FILE__)
isolate_namespace EngineName
end
end
This way you make sure everything is loaded alright, but be very careful using Concerns and maybe reconsider using dependency injection by refactoring Blorgh::Post to deal with different configurations.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With