diff --git a/Gemfile.lock b/Gemfile.lock index a84fa58..49dc976 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,14 +1,15 @@ PATH remote: . specs: - guard-rails-assets (0.0.3) + guard-rails-assets (0.0.4) guard + rake GEM remote: http://rubygems.org/ specs: diff-lcs (1.1.2) - guard (0.4.2) + guard (0.5.1) thor (~> 0.14.6) rake (0.9.2) rspec (2.6.0) diff --git a/guard-rails-assets.gemspec b/guard-rails-assets.gemspec index f3e7b3e..c947485 100644 --- a/guard-rails-assets.gemspec +++ b/guard-rails-assets.gemspec @@ -14,6 +14,7 @@ Gem::Specification.new do |s| s.rubyforge_project = "guard-rails-assets" s.add_dependency 'guard' + s.add_dependency 'rake' s.add_development_dependency 'rspec' s.files = `git ls-files`.split("\n") diff --git a/lib/guard/rails-assets.rb b/lib/guard/rails-assets.rb index 58c0132..a8a4cfc 100644 --- a/lib/guard/rails-assets.rb +++ b/lib/guard/rails-assets.rb @@ -1,5 +1,6 @@ require 'guard' require 'guard/guard' +require 'rake/dsl_definition' module Guard class RailsAssets < Guard @@ -8,11 +9,23 @@ module Guard @options = options || {} end + def create_rails_runner + @rails_runner = RailsRunner.new + end + + def rails_runner + @rails_runner ||= create_rails_runner + end + def start + create_rails_runner + compile_assets if run_for? :start end def reload + rails_runner.restart_rails + compile_assets if run_for? :reload end @@ -26,7 +39,8 @@ module Guard def compile_assets puts 'Compiling rails assets' - result = system "bundle exec rake assets:clean assets:precompile" + result = rails_runner.compile_assets + if result Notifier::notify 'Assets compiled' else @@ -42,3 +56,5 @@ module Guard end end end + +require 'guard/rails-assets/rails_runner' \ No newline at end of file diff --git a/lib/guard/rails-assets/rails_runner.rb b/lib/guard/rails-assets/rails_runner.rb new file mode 100644 index 0000000..f94f5a2 --- /dev/null +++ b/lib/guard/rails-assets/rails_runner.rb @@ -0,0 +1,64 @@ +module Guard + + # Keeps rails loaded in a thread waiting to run the asset pipeline compiler + class RailsAssets::RailsRunner + + def initialize + boot_rails + end + + # Methods to run the asset pipeline + # Taken from - https://github.com/rails/rails/blob/master/actionpack/lib/sprockets/assets.rake + module AssetPipeline + extend self + extend Rake::DSL + + def clean + assets = Rails.application.config.assets + public_asset_path = Rails.public_path + assets.prefix + rm_rf public_asset_path, :secure => true + end + + def precompile + Sprockets::Helpers::RailsHelper + + assets = Rails.application.config.assets.precompile + # Always perform caching so that asset_path appends the timestamps to file references. + Rails.application.config.action_controller.perform_caching = true + Rails.application.assets.precompile(*assets) + end + end + + def run_compiler + begin + @failed = false + AssetPipeline.clean + AssetPipeline.precompile + rescue => e + puts "An error occurred compiling assets: #{e}" + @failed = true + end + end + + def boot_rails + require "#{Dir.pwd}/config/environment.rb" + end + + # Runs the asset pipeline compiler. + # + # @return [ Boolean ] Whether the compilation was successful or not + def compile_assets + run_compiler + + !failed? + end + + def failed? + @failed + end + + def restart_rails + fail "Not implemented" + end + end +end \ No newline at end of file diff --git a/spec/guard/rails-assets/rails_runner_spec.rb b/spec/guard/rails-assets/rails_runner_spec.rb new file mode 100644 index 0000000..506f245 --- /dev/null +++ b/spec/guard/rails-assets/rails_runner_spec.rb @@ -0,0 +1,69 @@ +require 'spec_helper' + +describe Guard::RailsAssets::RailsRunner do + + describe ".compile_assets" do + + let(:asset_pipeline) { Guard::RailsAssets::RailsRunner::AssetPipeline } + + before do + described_class.class_eval do + def boot_rails + end + end + end + + context "successful compile" do + before do + asset_pipeline.stub(:clean) + asset_pipeline.stub(:precompile) + end + + it "clean's the assets" do + asset_pipeline.should_receive(:clean) + subject.compile_assets + end + + it "runs the compiler" do + asset_pipeline.should_receive(:precompile) + subject.compile_assets + end + + it "returns true" do + subject.compile_assets.should be_true + end + end + + context "with a compilation error" do + + before do + asset_pipeline.stub(:clean) + asset_pipeline.should_receive(:precompile).and_raise(StandardError) + @output = capture(:stdout) do + @result = subject.compile_assets + end + end + + it "outputs the error" do + @output.should include("An error occurred") + end + + it "returns false" do + @result.should be_false + end + + context "on next successful compile" do + + it "works" do + asset_pipeline.should_receive(:clean) + asset_pipeline.should_receive(:precompile) + subject.compile_assets.should be_true + end + + end + + end + + end + +end diff --git a/spec/guard/rails-assets_spec.rb b/spec/guard/rails-assets_spec.rb index 597587e..fe336f0 100644 --- a/spec/guard/rails-assets_spec.rb +++ b/spec/guard/rails-assets_spec.rb @@ -3,8 +3,14 @@ require 'guard/rails-assets' describe Guard::RailsAssets do let(:options) { {} } + let(:rails_thread) { mock(Guard::RailsAssets::RailsThread) } subject { Guard::RailsAssets.new(['watchers'], options) } + before do + Guard::RailsAssets::RailsThread.stub(:new => rails_thread) + rails_thread.stub(:compile_assets => true, :restart_rails => true) + end + describe '#start' do it_behaves_like 'guard command', :command => :start, :run => true end @@ -37,7 +43,7 @@ describe Guard::RailsAssets do describe 'asset compilation using CLI' do def stub_system_with result - subject.should_receive(:system).with("bundle exec rake assets:clean assets:precompile").and_return result + rails_thread.should_receive(:compile_assets).and_return result end it 'should notify on success' do diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index b611c8c..40e995e 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,6 +1,7 @@ require 'rspec' require 'guard/rails-assets' require 'support/shared_examples' +require 'support/stdout_helper' RSpec.configure do |config| config.color_enabled = true @@ -15,5 +16,7 @@ RSpec.configure do |config| config.after(:each) do ENV["GUARD_ENV"] = nil end + + config.include(Helpers) end diff --git a/spec/support/stdout_helper.rb b/spec/support/stdout_helper.rb new file mode 100644 index 0000000..7a6cf8c --- /dev/null +++ b/spec/support/stdout_helper.rb @@ -0,0 +1,17 @@ +require 'stringio' + +module Helpers + + def capture(*streams) + streams.map! { |stream| stream.to_s } + begin + result = StringIO.new + streams.each { |stream| eval "$#{stream} = result" } + yield + ensure + streams.each { |stream| eval("$#{stream} = #{stream.upcase}") } + end + result.string + end + +end \ No newline at end of file