Forum: Rails Engines Rails 3 Engines

18a4cfd669d998263f9824ed5efeab41?d=identicon&s=25 Michael Rigart (damick)
on 2010-06-05 13:48
Hi,

I'm experimenting a bit with Rails3 and the Rails::Engine functionality.
But there are a fiew points where I get stuck:

application_helper.rb : it looks like it is not loaded. When I call some
method helpers in my application defined in my engines application
helper, I get an undefined method error

application_controller.rb : same problem like with the
application_helper.rb

assets like images, css, js that are stored in the engine are not loaded
into the application


I must be overseeing something, but since these are my first steps into
Rails Engine and Rails 3, I just can't figure out what it is. Everything
else like other controllers, helpers, views and routes are loaded
perfectly
Sincerely yours
18a4cfd669d998263f9824ed5efeab41?d=identicon&s=25 Michael Rigart (damick)
on 2010-06-05 16:35
It seems that the application_helper and controller are loaded. But once
you override them (just the files, not the methods) it take the
application files.
this means that you can't just override the application helper and
controller methods individualy. Is there a workaround for this? I guess
you could create a module to include or a class to inherit from?

Still no luck with the assets though. Any help would be great.
Ee01e594333a9e631173d0d8e4350214?d=identicon&s=25 Didier Did (did)
on 2010-06-12 01:55
Hi Michael,

First of all, finding good resources about Rails 3 engines is really
hard. I spent a lot of hours to figure out how it works. That being
said, back to your questions.

Michael Rigart wrote:
> It seems that the application_helper and controller are loaded. But once
> you override them (just the files, not the methods) it take the
> application files.
> this means that you can't just override the application helper and
> controller methods individualy. Is there a workaround for this? I guess
> you could create a module to include or a class to inherit from?
>

Take a look at Devise source code. They include helper methods within
the ActionView / Controller modules.
Another problem with helpers inside engine. In production, other helpers
than the one assigned to the current controller are not loaded. Which
means that if you have your PageController, you won't be able to use
methods defined in SitesHelper. The only solution I found is to include
them when you load your engine.rb file.

> Still no luck with the assets though. Any help would be great.

This one seems "obvious". For instance, how can Nginx do to serve assets
from an engine ? There is no way it can serve them, so we need to help
it. The reason I found after reviewing a lot of projects is to create a
generator inside your gem copying your assets file.

Good luck Michael :-)
18a4cfd669d998263f9824ed5efeab41?d=identicon&s=25 Michael Rigart (damick)
on 2010-06-17 11:04
Hi Didier

could you tell me how to include those helpers from my engine? I have
tried several methods like

      class Engine < Rails::Engine
          config.to_prepare do
              ApplicationController.helper(Admin::MetasHelper)
          end
      end


or

ActionView::Base.send :include, Admin::MetasHelper

but none seem to work :s


Secondly, I allready knew that accessing assets from gems would be
impossible. The only difference was, that I thought that their might be
a special helper like the rails_engine plugin for Rails 2.x .
But just for the info, how do I access files from my gem/engine? When I
create a generator, how does the filepath usualy work?
Ee01e594333a9e631173d0d8e4350214?d=identicon&s=25 Didier Did (did)
on 2010-06-17 11:20
> could you tell me how to include those helpers from my engine? I have
> tried several methods like
>
>       class Engine < Rails::Engine
>           config.to_prepare do
>               ApplicationController.helper(Admin::MetasHelper)
>           end
>       end
>

I spent some much time on this, trying all the different ways of
including those helpers (ie not related to controllers), without any
success (sometimes it worked in dev env but not in prod, ...etc).
So I came up with another approach.
Actually, my engine controllers inherit from a base controller. So
inside this base one, I added the following lines:

Dir[File.dirname(__FILE__) + "/../../helpers/**/*_helper.rb"].each do
|file|
   helper "admin/#{File.basename(file, '.rb').gsub(/_helper$/, '')}"
end

Even if it is not super clean, it does the trick for me. If anyone has a
better way of doing it, let me know :-)


> Secondly, I allready knew that accessing assets from gems would be
> impossible. The only difference was, that I thought that their might be
> a special helper like the rails_engine plugin for Rails 2.x .
> But just for the info, how do I access files from my gem/engine? When I
> create a generator, how does the filepath usualy work?

Take a look at my generator:

http://github.com/did/locomotive/blob/master/lib/g...
18a4cfd669d998263f9824ed5efeab41?d=identicon&s=25 Michael Rigart (damick)
on 2010-06-17 11:46
Hi Didier,

thanks for the info. I found another way to load the helpers.

In my lib/my_engine.rb file I did the following:

      ActiveSupport::Dependencies.load_paths << File.dirname(__FILE__) +
"/../app/helpers"
      ActiveSupport::Dependencies.load_once_paths.delete
File.dirname(__FILE__) + "/../app/helpers"
      ActionController::Base.helper MetasHelper

so lib/my_engine.rb looks like this:

if defined?(Rails)
  require 'rails'

  module MyEngine
    module Meta
      class Engine < Rails::Engine
      end
    end
  end

  module Admin
      ActiveSupport::Dependencies.load_paths << File.dirname(__FILE__) +
"/../app/helpers"
      ActiveSupport::Dependencies.load_once_paths.delete
File.dirname(__FILE__) + "/../app/helpers"
      ActionController::Base.helper MetasHelper
      ActionController::Base.helper CategoriesHelper
      ActionController::Base.helper ThemesHelper
  end
end

I had to insert the ActiveSupport and ActionController within a Admin
module since its namespaced.
18a4cfd669d998263f9824ed5efeab41?d=identicon&s=25 Michael Rigart (damick)
on 2010-06-17 11:59
Seems like
ActiveSupport::Dependencies.load_once_paths.delete
File.dirname(__FILE__) + "/../app/helpers"

is not realy nessacary. It also works without that line.

What I'm woundering now is if It's possible to load all helpers without
specifying them individualy
Ee01e594333a9e631173d0d8e4350214?d=identicon&s=25 Didier Did (did)
on 2010-06-17 12:18
Your solution looks good ! Are you sure that even your first statement
(ActiveSupport::Dependencies.load_paths...) is needed ?


> What I'm woundering now is if It's possible to load all helpers without
> specifying them individualy

Something like that ?

module Admin
  # adjust path
  Dir[File.dirname(__FILE__) + "/../../helpers/**/*_helper.rb"].each do
|file|
     ActionController::Base.helper File.basename(file,
'.rb').classify.constantize
  end
end
18a4cfd669d998263f9824ed5efeab41?d=identicon&s=25 Michael Rigart (damick)
on 2010-06-17 13:01
Well, with my method it seemed like it was needed.

I tryed your way, but it doesn't seem to work.

/Library/Ruby/Gems/1.8/gems/activesupport-3.0.0.beta4/lib/active_support/inflector/methods.rb:103:in
`constantize': uninitialized constant MediasHelper (NameError)

Even when I add the loadpaths

  module Admin
      ActiveSupport::Dependencies.load_paths << File.dirname(__FILE__) +
"/../app/helpers"
      Dir[File.dirname(__FILE__) +
"/../app/helpers/**/*_helper.rb"].each do |file|
          ActionController::Base.helper File.basename(file,
'.rb').classify.constantize
      end
  end



Didier Did wrote:
> Your solution looks good ! Are you sure that even your first statement
> (ActiveSupport::Dependencies.load_paths...) is needed ?
>
>
>> What I'm woundering now is if It's possible to load all helpers without
>> specifying them individualy
>
> Something like that ?
>
> module Admin
>   # adjust path
>   Dir[File.dirname(__FILE__) + "/../../helpers/**/*_helper.rb"].each do
> |file|
>      ActionController::Base.helper File.basename(file,
> '.rb').classify.constantize
>   end
> end
Ee01e594333a9e631173d0d8e4350214?d=identicon&s=25 Didier Did (did)
on 2010-06-17 13:11
> Well, with my method it seemed like it was needed.

That's right but how can your engine know what helpers are not tied to
controllers ? mmmhh, that's definitely doable but it's not worth it.

> I tryed your way, but it doesn't seem to work.

I think that's because of namespacing. It expects Admin::MediasHelper
but that's weird since you call it from your Admin module.
Maybe you should try to force it ?

ActionController::Base.helper "admin/#{File.basename(file, '.rb')
".camelize.constantize

I'm thinking, maybe you could have the best of the two worlds.

%w{metas categories themes}.each do |name|
  ActionController::Base.helper
"Admin::#{name.camelize}Helper".constantize
end

What do you think about it ?


>
> 
/Library/Ruby/Gems/1.8/gems/activesupport-3.0.0.beta4/lib/active_support/inflector/methods.rb:103:in
> `constantize': uninitialized constant MediasHelper (NameError)
>
> Even when I add the loadpaths
>
>   module Admin
>       ActiveSupport::Dependencies.load_paths << File.dirname(__FILE__) +
> "/../app/helpers"
>       Dir[File.dirname(__FILE__) +
> "/../app/helpers/**/*_helper.rb"].each do |file|
>           ActionController::Base.helper File.basename(file,
> '.rb').classify.constantize
>       end
>   end
>
>
>
> Didier Did wrote:
>> Your solution looks good ! Are you sure that even your first statement
>> (ActiveSupport::Dependencies.load_paths...) is needed ?
>>
>>
>>> What I'm woundering now is if It's possible to load all helpers without
>>> specifying them individualy
>>
>> Something like that ?
>>
>> module Admin
>>   # adjust path
>>   Dir[File.dirname(__FILE__) + "/../../helpers/**/*_helper.rb"].each do
>> |file|
>>      ActionController::Base.helper File.basename(file,
>> '.rb').classify.constantize
>>   end
>> end
18a4cfd669d998263f9824ed5efeab41?d=identicon&s=25 Michael Rigart (damick)
on 2010-06-17 14:19
Ok, found a "solution"

  ActiveSupport::Dependencies.load_paths << File.dirname(__FILE__) +
"/../app/helpers"
  Dir[File.dirname(__FILE__) + "/../app/helpers/**/*_helper.rb"].each do
|file|
      ActionController::Base.helper
"Admin::#{File.basename(file,'.rb').camelize}".constantize
  end

not wrapped inside my Admin module. This seems to work fine. Tried
without the ActiveSupport::Dependencies, but then it didn't work out:
uninitialized constant error for my helper.

Anyway, nice working with you Didier to get working and dynamic solution
for this problem.
Ee01e594333a9e631173d0d8e4350214?d=identicon&s=25 Didier Did (did)
on 2010-06-17 14:36
> Anyway, nice working with you Didier to get working and dynamic solution
> for this problem.

Thanks ! Same thing :-)
C2cf6f047cdb0590f03ad59a78181aa1?d=identicon&s=25 Matthew Crouch (mobilezilla)
on 2010-07-24 12:23
Michael Rigart wrote:
> Ok, found a "solution"
>
>   ActiveSupport::Dependencies.load_paths << File.dirname(__FILE__) +
> "/../app/helpers"
>   Dir[File.dirname(__FILE__) + "/../app/helpers/**/*_helper.rb"].each do
> |file|
>       ActionController::Base.helper
> "Admin::#{File.basename(file,'.rb').camelize}".constantize
>   end
>
> not wrapped inside my Admin module. This seems to work fine. Tried
> without the ActiveSupport::Dependencies, but then it didn't work out:
> uninitialized constant error for my helper.
>
> Anyway, nice working with you Didier to get working and dynamic solution
> for this problem.

I think the best way to load your helpers would be to use the new
initializer method, for my themes engine I used this:

initializer 'themes.helper' do |app|
    ActionView::Base.send :include, ThemesHelper
end

Hope this helps.

Matt
18a4cfd669d998263f9824ed5efeab41?d=identicon&s=25 Michael Rigart (damick)
on 2010-07-31 19:43
Hi Matt,

where exactly do you put that initializer?
C2cf6f047cdb0590f03ad59a78181aa1?d=identicon&s=25 Matthew Crouch (mobilezilla)
on 2010-07-31 19:46
(Received via mailing list)
This goes in your main engines class:

module SomeModule
  class SomeClass < ::Rails::Engine
    initializer 'some_class.helper' do |app|
      ActionView::Base.send :include, SomeHelper
    end
  end
end

Cheers

Matt

On 31 Jul 2010, at 18:43, Michael Rigart wrote:

> Hi Matt,
>
> where exactly do you put that initializer?
>
> --
> Posted via http://www.ruby-forum.com/.
> _______________________________________________
> Engine-Users mailing list
> Engine-Users@lists.rails-engines.org
> http://lists.rails-engines.org/listinfo.cgi/engine...

--

Matthew Crouch
Mobilezilla

Telephone:    +44 (0) 7958 592 326
Email:             mcrouch@mobilezil.la
Web:               http://www.mobilezil.la
Skype:            mobilezilla

Please consider the environment before printing out this email.

The contents of this email are confidential to the addressee
and are intended solely for the recipients use. If you are not
the addressee, you have received this email in error.
Any disclosure, copying, distribution or action taken in
reliance on it is prohibited and may be unlawful.

Any opinions expressed in this email are those of the author
personally.

All email communications are recorded for monitoring purposes.
18a4cfd669d998263f9824ed5efeab41?d=identicon&s=25 Michael Rigart (damick)
on 2010-07-31 19:54
thx, just got it ;). stupid question . Thx for the hint though. My
earlier solution broke down when upgrading from Beta4 to RC1
This topic is locked and can not be replied to.