konradstrack
konradstrack

Reputation: 3002

Exclude *.spec.js files in Rails asset pipeline (application.js)

I'm attempting to follow John Papa's AngularJs 1.x styleguide (organising tests) and place *.spec.js files (to be executed using Karma) next to client code, which results in files such as some.filter.js and some.filter.spec.js being place next to one another.

However, what I need to avoid, is including the *.spec.js files in the assets pipeline.

The only options I see for now are either avoiding using //= require_tree . in the application.js file and specifying every single file explicitly, or giving up on keeping spec files next to the code.

Is there any better way of achieving the desired behaviour?

(I'm using sprockets 3.5.2 and rails 4.2.6)

Upvotes: 10

Views: 622

Answers (2)

konradstrack
konradstrack

Reputation: 3002

Please note: this answer is based on the defsprite's one, because it pointed me in the right direction, but reality turned out to be a bit harsher.

Place the following in config/initializers/sprockets.rb to register a new sprockets processor:

class DirectiveProcessor < Sprockets::DirectiveProcessor
  def process_require_glob_directive(glob)
    each_file(glob) { |fn| process_require_directive(fn) }
  end

  def process_stub_glob_directive(glob)
    each_file(glob) { |fn| process_stub_directive(fn) }
  end

  private

  def each_file(glob)
    glob_pattern = "#{@dirname}/#{glob}"
    path_prefix = Pathname.new(@dirname)

    Dir[glob_pattern].sort.each do |path|
      yield Pathname.new(path).relative_path_from(path_prefix).to_s
    end
  end
end

Rails.application.config.assets.configure do |env|
  env.register_processor('application/javascript', DirectiveProcessor)
end

The most notable changes with respect to the original answer include converting absolute paths returned by Dir to relative ones (absolute paths are not accepted by sprockets) and different registration method (Rails.application.assets is nil in my case).

Then, within your application.js (before any require_tree statements) add:

//= stub_glob angular/**/*.spec.js

Upvotes: 1

defsprite
defsprite

Reputation: 613

Sprockets itself does not implement file globbing (yet) - this can only achieved by providing a custom DirectiveProcessor. Luckily, there is already a gem providing exactly what you want: https://github.com/backupify/sprockets-glob

From the documentation:

# config/initializers/sprockets.rb
require 'sprockets/glob'
Rails.application.assets.register_processor('application/javascript', Sprockets::Glob::DirectiveProcessor)

# application.js
//= require_glob features/**/*.js
//= stub_glob features/**/*test.js

Upvotes: 4

Related Questions