Hobo / hobo

The web app builder for Rails (moved from tablatom/hobo)
http://hobocentral.net
103 stars 39 forks source link

Incompatibility with current version of sprocket rails (3.0.0.) #175

Closed haslinger closed 8 years ago

haslinger commented 8 years ago

There is a discussion at the google group including a fix going on already: https://groups.google.com/forum/#!topic/hobousers/AIyOVTdkrLE

Fixing it's version to

gem 'sprockets-rails', '2.3.3'

resolves it for the moment.

enwood commented 8 years ago

I confirm the same thing. See also discussion in Hobo Users:

https://groups.google.com/forum/#!topic/hobousers/AIyOVTdkrLE

Tim

iox commented 8 years ago

Yep, I have reproduced it too. It seems like a lot of things changed with sprockets 3.0. We'll need to fix our side, or at least we need to ask Hobo to depend on sprockets rails 2.3.3.

Thanks for the great bug report!

tacid commented 8 years ago

Here is the guide to upgrade from Sprockets 2.x to 3.x https://github.com/rails/sprockets/blob/master/UPGRADING.md

tacid commented 8 years ago

What I've found when investigating the problem

  1. In console Sprockets helper is working
> helper.stylesheet_path 'front'
=> "/assets/front-284197b690fc10d3af05478766231b23dd41c594ac528d2b50aca918c66b74e3.css"

but in dryml view this code generate "/stylesheet/front.css"

  1. problem is with the Sprockets::Rails::Helper resolve_assets_with attribute. It is defined in https://github.com/rails/sprockets-rails/blob/v3.0.3/lib/sprockets/rails/helper.rb
VIEW_ACCESSORS = [
        :assets_environment, :assets_manifest,
        :assets_precompile, :precompiled_asset_checker,
        :assets_prefix, :digest_assets, :debug_assets,
        :resolve_assets_with
      ]
... later ...
attr_accessor(*VIEW_ACCESSORS)

Once is set inside https://github.com/rails/sprockets-rails/blob/v3.0.3/lib/sprockets/railtie.rb on

ActiveSupport.on_load(:action_view) do
   include Sprockets::Rails::Helper

   # Copy relevant config to AV context
   self.debug_assets      = config.assets.debug
   self.digest_assets     = config.assets.digest
   self.assets_prefix     = config.assets.prefix
   self.assets_precompile = config.assets.precompile

   self.assets_environment = app.assets
   self.assets_manifest = app.assets_manifest

   self.resolve_assets_with = config.assets.resolve_with

   # Expose the app precompiled asset check to the view
   self.precompiled_asset_checker = -> logical_path { app.asset_precompiled? logical_path }
end

and once is called again in https://github.com/rails/sprockets-rails/blob/v3.0.3/lib/sprockets/rails/helper.rb

# List of resolvers in `config.assets.resolve_with` order.
def asset_resolver_strategies
  @asset_resolver_strategies ||=
    Array(resolve_assets_with).map do |name|
      HelperAssetResolvers[name].new(self)
    end
end

And here between setting and getting the value of resolve_assets_with bag appears. In the console values were setted in railie.rb will not change till getting them inside the helper, so inside resolve_assets_with will be array [:enviroment] but when I get it value inside view - there will be nil. So, I think somhow this helper is recreated but not initialized in hobo views layer.

That's what I have found till now

tacid commented 8 years ago

And I have found it!

So, there is https://github.com/Hobo/hobo/blob/master/dryml/lib/dryml/template_environment.rb file that extnded ::Sprockets::Rails::Helper but do not copies all needed attributes

def initialize(view=nil)                                                                                                                                                                                                                                                      
  unless view.nil?                                                                                                                                                                                                                                                            
    @view = view                                                                                                                                                                                                                                                              
    @_erb_binding = binding                                                                                                                                                                                                                                                   
    @_part_contexts = {}                                                                                                                                                                                                                                                      
    @_scoped_variables = ScopedVariables.new                                                                                                                                                                                                                                  
    @_polymorphic_tag_cache = {}                                                                                                                                                                                                                                              

    # Make sure the "assigns" from the controller are available (instance variables)                                                                                                                                                                                          
    if view                                                                                                                                                                                                                                                                   
      view.assigns.each do |key, value|                                                                                                                                                                                                                                       
        instance_variable_set("@#{key}", value)                                                                                                                                                                                                                               
      end                                                                                                                                                                                                                                                                     

      # copy view instance variables over                                                                                                                                                                                                                                     
      view.instance_variables.each do |iv|                                                                                                                                                                                                                                    
        instance_variable_set(iv, view.instance_variable_get(iv))                                                                                                                                                                                                             
      end                                                                                                                                                                                                                                                                     

      # Copy some class attributes needed for Sprockets to work correctly                                                                                                                                                                                                     
      self.extend ::Sprockets::Rails::Helper                                                                                                                                                                                                                                  
      self.assets_prefix = view.try(:assets_prefix)                                                                                                                                                                                                                           
      self.assets_environment = view.try(:assets_environment)                                                                                                                                                                                                                 
      self.assets_manifest = view.try(:assets_manifest)                                                                                                                                                                                                                       
      self.digest_assets = view.try(:digest_assets)                                                                                                                                                                                                                           
    end                                                                                                                                                                                                                                                                       
  end                                                                                                                                                                                                                                                                         
end

So I have just copied all attributes settings from railties.rb of sprockets-rails gem and it is now working

tacid commented 8 years ago

Here my patch #180

iox commented 8 years ago

Very nice work @tacid!

haslinger commented 8 years ago

Just a small sidenote: Updating to sprockets-rails 3.0.3, in development I get:

Asset was not declared to be precompiled in production.
Add `Rails.application.config.assets.precompile += %w( front.css )` to `config/initializers/assets.rb` and restart your server

This can easily be resolved by following the suggestion by moving the statement corresponding to the one in the error message to it's own assets.rb file.

tacid commented 8 years ago

There is configuration of assets.precompile in config/application.rb, in example my configuration there is:

      # Hobo: the admin subsite loads admin.css & admin.js
      config.assets.precompile += %w(admin.css admin.js)
      # Hobo: the front subsite loads front.css & front.js
      config.assets.precompile += %w(front.css front.js ajax-loader.gif)

Thats all you need, I think

tacid commented 8 years ago

I found some little problem there, as we can read in official documentation https://github.com/rails/sprockets-rails there is config.assets.resolve_with option that defines the way sprockets serve the assets. There is said that by default this option set this way:

    # Dev where debug is true, or digests are disabled
    %i[ environment ]

    # Dev default, or production with compile enabled.
    %i[ manifest environment ]

    # Production default.
    %i[ manifest ]

But in my application, there was nil in production and [ :environment] in development, so in the production environment sprockets just doesn't work at all

I've just add config.assets.resolve_with = [ :manifest ] to my config/environments/production.rb and this resolves the problem.