I am also running into some issues with re-opening modules for some
reason so maybe the two issues are related. For example...
I add the xebec gem as a dependency to my gem/engine. xebec requires
that I put "helper Xebec::NavBarHelper" into my ApplicationController
so I create a file in the engine like this.
/app/controllers/application_controller
class ApplicationController < ActionController::Base
helper Xebec::NavBarHelper
end
When I do this nothing happens the controller code is not being
called. So I require the file explicitly in my gem but then all the
helpers in the application_helper of the parent app go away.
I think one way to solve this problem would be for the parent
ApplicationController to inherit from this one but I am wondering if
there a better way to deal with.
I'm not super experienced with engines, but here's my thoughts:
* Don't put ApplicationController in your engine - I think that should only be located in the application itself. What you can do to get your code into the app is make Xebec::ApplicationController a subclass of ActionController::Base, and then your app's ApplicationController a subclass of Xebec::ApplicationController (as you've hinted at the end of your email). This means you can avoid reopening the class.
* Also, with that custom superclass, you can include the helpers you want there, and they'll be loaded for every controller subclassing from it.
* Don't manually require anything that a Rails app would normally load itself (especially anything in app/models, app/controllers and app/helpers). That goes for the models, controllers and helpers in your engine as well as what's in the Rails app.
Cheers
--
Pat
> --
> You received this message because you are subscribed to the Google Groups "Ruby or Rails Oceania" group.
> To post to this group, send email to rails-...@googlegroups.com.
> To unsubscribe from this group, send email to rails-oceani...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/rails-oceania?hl=en.
>
I wanted to avoid creating superclasses (or even modules that you'd
have to load into your classes). Your email gives me one idea though.
I could add my code to the ActionController::Base. Although I am not
crazy about that idea I think it might work. I'll have to decide what
I find less objectionable :)
>
> * Don't manually require anything that a Rails app would normally load itself (especially anything in app/models, app/controllers and app/helpers). That goes for the models, controllers and helpers in your engine as well as what's in the Rails app.
I need to figure out what is going on with the gemfile and requires.
Nothing in the engine gemfile is loading up automatically and neither
are the dependencies specified in the engine.
Hi Tim,
Engines don't monkey patch classes, they override them. So, for example, if you bundle a User model in your Engine, it will replace (not enhance/extend/patch) the User model in the hosting application.
--
You received this message because you are subscribed to the Google Groups "Ruby or Rails Oceania" group.
To view this discussion on the web visit https://groups.google.com/d/msg/rails-oceania/-/J_odCSgjOdgJ.
>>
>> * Also, with that custom superclass, you can include the helpers you want there, and they'll be loaded for every controller subclassing from it.
>
> I wanted to avoid creating superclasses (or even modules that you'd
> have to load into your classes). Your email gives me one idea though.
> I could add my code to the ActionController::Base. Although I am not
> crazy about that idea I think it might work. I'll have to decide what
> I find less objectionable :)
Sometimes a simple include is better for long-term maintainability than automatically (and invisibly) injecting into a superclass.
>> * Don't manually require anything that a Rails app would normally load itself (especially anything in app/models, app/controllers and app/helpers). That goes for the models, controllers and helpers in your engine as well as what's in the Rails app.
>
> I need to figure out what is going on with the gemfile and requires.
> Nothing in the engine gemfile is loading up automatically and neither
> are the dependencies specified in the engine.
Are you adding the autoload paths in your Engine subclass? e.g.:
class Xebec::Engine < Rails::Engine
paths['app/controllers'] << 'app/controllers'
paths['app/views'] << 'app/views'
end
--
Pat
Mmm. I don't know if this is true in all cases. When I added the
ApplicationController into my engine it broke things in the app that
was using the engine because it seemed to override the apps
ApplicationController. Then again it was 2:00 AM in the morning on a
Sunday so maybe I was a bit loopy at that time.
I think the safest thing to do at this point is to put my libraries in
modules and then have the application include them.
On a related note I remember a couple of apps used
https://github.com/pivotal/desert as their plugin architecture and it
was rather nice. IIRC it mixed in the desert classes with yours.
First of all I should clarify that my engine is not called Xebec. I am
using the Xebec gem in my engine. Xebec is a gem to create menus in
your application. I was hoping that I could create menus (all of which
are helpers) in my engine and then have the parent apps make use of
those menus by calling <%= top_menu %> in their templates or views.
As for the gems here is the conundrum.
My gemspec says
s.add_dependency 'acts-as-taggable-on'
s.add_dependency 'pg'
s.add_dependency 'pg_search'
s.add_dependency 'simple_uuid'
s.add_dependency 'devise'
s.add_dependency 'rails_config'
s.add_dependency 'xebec'
The gemfile in the engine says
source "http://rubygems.org"
gemspec
So somewhere in my engine I have a call to simple_uuid but it doesn't
work because bundler did not include that gem (in the parent
application). It installed the gem but did not load it. As a result I
have to put this on top of my lib/engine_name.rb
require 'rubygems'
require 'acts-as-taggable-on'
require 'pg_search'
require 'pg'
require 'simple_uuid'
require 'devise'
require 'rails_config'
require 'xebec'
Ideally rails would process the Gemfile in the engine(s) and then the
Gemfile in the parent app but it doesn't seem to be doing that.
> First of all I should clarify that my engine is not called Xebec. I am
> using the Xebec gem in my engine. Xebec is a gem to create menus in
> your application. I was hoping that I could create menus (all of which
> are helpers) in my engine and then have the parent apps make use of
> those menus by calling <%= top_menu %> in their templates or views.
Okay - I just was using what I could guess for an example. Adapt as you need to.
> Ideally rails would process the Gemfile in the engine(s) and then the
> Gemfile in the parent app but it doesn't seem to be doing that.
Bundler is for packaging your gem, not for loading it when used elsewhere - so Rails isn't going to look at gems/engines it's using to see if they have a Gemfile. It's not guaranteed other gems would use Bundler to manage their dependencies. Manually requiring what you need in that engine is the way to go.
--
Pat
I think there is a bit of code in the Universe that randomizes a bunch
of stuff between 1:30 and 3:30 AM.
On 04/09/2011, at 11:26, Tim Uckun <timu...@gmail.com> wrote:
> Ideally rails would process the Gemfile in the engine(s) and then the
> Gemfile in the parent app but it doesn't seem to be doing that.
>
No, this is never going to be the case. You must specify your dependencies in your engine's gemspec file which will be loaded by Bundler because your application is treating your engine as if it were a gem. Or at least, it should be doing that.
If you've NOT specified your engine as a GEM DEPENDENCY of your application then things will not be loaded as normal.
If you'd like a better explanation why I can give you one over IM later this afternoon or I could write a blog post? :)
I am always eager to learn so if you have the inclination please feel
free to ping me I am @timuckun almost everywhere.
BTW I am specifying the engine as a gem in the gemfile
gem 'engine_name', :path => 'vendor/engines'