Rails 4: Asset Path #214

Closed
incorvia opened this Issue Sep 18, 2014 · 33 comments

Projects

None yet
@incorvia

The troubleshooting page says that to get image_tag to return "/assets/image.jpg" instead of "/images/image.jpg" you need to include: Sprockets::Helpers::RailsHelper. I believe this doesn't exist in newer versions of sprockets-rails, perhaps it is now: Sprockets::Rails::Helper? Anyways.. even including that I am still getting "/images/image.jpg" ...

class NavbarCell < Cell::ViewModel
  include Authable
  include Sprockets::Rails::Helper

  def show
    render
  end

end

What is the correct way to handle this now?

@incorvia

Just referencing this issue which seems to be related: carrierwaveuploader/carrierwave#1020

@apotonick
Collaborator

The correct way would be to change that in Rails and replace this incredibly fucked up URL helper system with something object-oriented and sustainable.

I absolutely have no clue how the sprocket paths stuff works in Rails > 3.2 but as soon as I run into it I'll let you know.

@incorvia

Ok, I think I have a bit of a handle on this now. When you call "image_tag" in the standard AssetTagHelper it calls a method path_to_image which calls a method asset_path in AssetUrlHeper which calls a method compute_asset_path. This method also in AssetUrlHelper is meant to be overridden and it is by sprockets-rails: https://github.com/rails/sprockets-rails/blob/master/lib/sprockets/rails/helper.rb#L65. This is the critical method. If the result of calling asset_digest_path is nil (which it will be if the Sprockets ENV is not set in the included class) then super is called and the default '/images' path is used. In order to set the Sprockets ENV in the included Cell I found you need to do the following:

class NavbarCell < Cell::ViewModel
 include Sprockets::Rails::Helper

  self.assets_prefix = Rails.application.config.assets.prefix
  self.assets_environment = Rails.application.assets

  def show
    render
  end
end

Maybe there is a better way to do this. I also don't know if there are other Sprocket Settings that need to be copied in lest there be unintended side effects.. Will probably just see how it goes for now.

@apotonick
Collaborator

Man, thanks for figuring this out. Ok, I understand, the problem is class settings that are not "copied" from the parent controller.

Your way looks ok to me - the better way would be to provide an object to the cell that already keeps all those values, but that'll mean Rails had to use objects instead of blindly copying PHP-like helper methods onto other helper methods, dear god, objects, unheard of! ๐Ÿ˜‰

@incorvia

Ha. ๐Ÿ‘ Thanks for making such an awesome library.

@incorvia

For future reference you also have to copy over whether digesting is turned on, otherwise the assets won't have the digest hash appended in production:

    self.digest_assets = Rails.application.config.assets[:digest]
@thetron
thetron commented Nov 4, 2014

@incorvia Life saver! This one was driving my crazy! ๐Ÿป

@gavinkflam

@incorvia Thanks! You saved my life!
@apotonick Would the helpers be included in future release?

@apotonick apotonick added a commit that referenced this issue Jun 5, 2015
@apotonick apotonick add tests from #214. 1473428
@apotonick
Collaborator

@incorvia I added a test for that here: https://github.com/apotonick/cells/blob/master/test/rails4.2/test/integration/url_helper_test.rb#L32

The cell sits here: https://github.com/apotonick/cells/blob/master/test/rails4.2/app/cells/song_cell.rb#L6

As you can see, this is a fully self-contained Rails app to test Cells. Could you make this test pass/fail? I don't know what your app setup is to make this /assets problem pop up. That'll be great for finding what's the problem.

@gavinkflam I can't include them per default since people might not use sprockets. Sorry!

@PikachuEXE
Contributor

I just delegate image_tag to ActionController::Base.helpers
It's not OO but it works.
I don't want to touch the rails screwed up helper system.

@apotonick
Collaborator

That is brillant, @PikachuEXE !!! Actually, the fix could be even simpler:

class Comment::Cell
  include Uber::Delegates
  delegates :image_tag, :parent_controller
@PikachuEXE
Contributor

parent_controller is a magic thing that I didn't know
I won't use it until this is properly documented :D

@apotonick
Collaborator

Goooood boy! It is a stable dependency in cells with Rails.

@PikachuEXE
Contributor

Still too "magical" for me. (Especially "rails only")
And these gem are meant to remove the "magic" right?

@apotonick
Collaborator

Hahaha! No magic, it's an explicit option getting passed into the cell via the #concept helper: https://github.com/apotonick/cells/blob/master/lib/cell/rails.rb#L10

@PikachuEXE
Contributor

Whatever I use, this is one of the "pitfalls" when using rails.
Worth documenting?

@bingxie
bingxie commented Dec 18, 2015

I tried: delegates :parent_controller, :image_tag

But it said: undefined method `image_tag' for #ProductsController:0x007ffce7c0f260

I am using Rails 4.2.5

@apotonick
Collaborator

In the controller, you might have to say

class ApplicationController < ..
  helper_method :image_tag

Please note that this is Rails-specific, and I do not support Rails anymore.

@bingxie
bingxie commented Dec 18, 2015

ok, ok, no rails! thanks for you quick response!

@apotonick
Collaborator

Haha, you're good, use Rails, but be prepared for problems like this! ๐Ÿ˜ฌ

Does the helper_method work for you? Should I add that to docs?

@bingxie
bingxie commented Dec 18, 2015

Actually, It doesn't work. :(

@anaumov
anaumov commented Dec 18, 2015

Sometimes it works, sometimes doesn't. Any suggestions?

@PikachuEXE
Contributor

I always use ::ActionController::Base.helpers.image_tag
Question/Blame rails for this.

@apotonick
Collaborator

Yepp! Suggestion is to open an issue on Rails- we can't do anything beyond providing a beautiful view layer. Sorry!

@bingxie
bingxie commented Dec 20, 2015

thanks @PikachuEXE

@AndreiMashkov

Unfortunately these hacks don't work for me starting from Rails 4.2.5 so I have to move Sprockets environment initialization to application.rb (or to the separate initializer). This snippet helps (after_initialize is crucial here):

    config.after_initialize do |app|
      Cell::ViewModel.send(:include, Sprockets::Rails::Helper)

      Cell::ViewModel.assets_prefix       = app.config.assets.prefix
      Cell::ViewModel.assets_environment  = app.assets
      Cell::ViewModel.digest_assets       = app.config.assets[:digest]
      Cell::ViewModel.assets_manifest     = app.assets_manifest
      Cell::ViewModel.resolve_assets_with = app.config.assets.resolve_with

      Cell::ViewModel.precompiled_asset_checker = -> logical_path { app.asset_precompiled?(logical_path) }
    end
@sebabouche

@AndreiMashkov ๐Ÿ‘ Thanks so much! I couldn't solve this and was sending the whole sprocketed url with options[:url]. Dirty dev ^^

@apotonick
Collaborator

We probably could extract a lot of code into a new gem cells-rails that takes care of all those nasty hacks?

@apneadiving

Would help to have something to replace asset_url as well.
I tend to agree with rails mess described here.
In the meantime I use:

  URI.join(
    my_method_to_retrieve_base_url, 
    ::ActionController::Base.helpers.asset_path('liner.png')
  )
@apotonick
Collaborator

Please all use the https://github.com/trailblazer/cells-rails gem, it fixes all of the above problems.

@PikachuEXE
Contributor

Why this project is not under trailblazer? :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment