Amey
Amey

Reputation: 8548

Confused about rails 4 asset pipeline with respect to third party js libraries

I have two questions, but I am guessing they both lead to the same answer.

They both are related to the fact that static images, show up in development mode and not on production (heroku).

Case 1:

In my model.rb

has_attached_file :avatar, styles: {
    thumb: '32x32#',
    medium: '512x512#'
}, 
:default_url => ActionController::Base.helpers.asset_path('/assets/avatar_:style.png') ## <- This line (#1)

Case 2:

In my view.html.haml I have inline javascript

:javascript
 $('.star').raty({
    path: '/assets', ### <- This line (#2)
    readOnly: true,
    noRatedMsg : "I haven't been rated yet!",
    score: function() {
    return $(this).attr('data-score');
  }
});

In CASE 1, I am trying to implement a default image if a user does not upload a profile pic(using paperclip), with two images avatar_thumb.png and avatar_medium.png inside of /app/assets/images

In CASE 2, I am trying to implement 5star rating feature using a third party library raty, which requires the "star" images. I have placed three images that come with this library in /app/assets/images as well.

Question : In both the cases the images are seen in development mode, but not when i deploy to Heroku. How do i resolve this.

P.S.: I am absolutely new to rails, any help would be appreciated.

Upvotes: 3

Views: 266

Answers (2)

Frederick Cheung
Frederick Cheung

Reputation: 84114

The asset pipeline does not make your life easy here - Paperclip assumes that default_url is something where it can replace the :style portion with the required value, but this can't work since that would obviously change the fingerprint portion of the filename as well.

The easiest thing to do here is not use the asset pipeline for those images. You don't have to use the asset pipeline for anything really and the benefit for images is pretty minimal compared to javascript or css files.

To do this move the images into public/images. Then, for the first case change the default url to

/images/avatar_:style.png

and for the second case set the path to /images

You could make the second case work with the asset pipeline if you wanted to - something like

:javascript
  $('.star').raty({
    readOnly: true,
    starHalf: '#{asset_path('star-half.png')}',
    starOff: '#{asset_path('star-off.png')}',
    starOn: '#{asset_path('star-on.png')}',
    cancelOn: '#{asset_path('cancel-on.png')}',
    cancelOff: '#{asset_path('cancel-off.png')}',
    noRatedMsg : "I haven't been rated yet!",
    score: function() {
      return $(this).attr('data-score');
    }
  });

Upvotes: 1

Richard Peck
Richard Peck

Reputation: 76774

Since you're new, let me describe how it works for you:

--

Assets

When you deploy a Rails application, your assets will be part of what's known as the asset pipeline. In development, your asset files are stored in app/assets/...

When you use the asset path helpers, Rails will call the following paths for you:

  • app/assets/...
  • vendor/assets/...
  • public/...

The problem you have is in development, with all your assets present in app/assets, you'll be able to call all the files you wish indiscriminately

--

Production

When you run your app in production mode, things get a little trickier

Firstly, you can't rely on your assets being in app/assets any more - production mode generally (not always, but on Heroku for sure) means that you will have to precompile your assets:

In production, Rails precompiles these files to public/assets by default. The precompiled copies are then served as static assets by the web server. The files in app/assets are never served directly in production.

This means if you want to load assets in production, especially on Heroku, you will need to use the asset_paths correctly (mainly because Rails will fingerprint your production / compiled assets)

--

Fix

In reference to your question directly, I would do this:

1

:default_url => asset_path('avatar_:style.png') #-> not sure about the :style part here

2

:javascript
 $('.star').raty({
    path: asset_url, #-> will use the asset_url
    readOnly: true,
    noRatedMsg : "I haven't been rated yet!",
    score: function() {
    return $(this).attr('data-score');
  }
});

Upvotes: 1

Related Questions