Search code examples
eclipseantjrubycompass-sasssusy-compass

Cleanest way to run susy, compass, and sass within jruby-complete?


why can jruby find require 'susy' in my compass config.rb, but @import 'susy' within *.scss files produces the issue:

 [java]     error Web Content/common/sass/base/foundation_de_DE.scss (Line 9: File to import not found or unreadable: susy.
        [java] Load paths:
        [java]   <removed>/Web Content/common/sass

My existing application wants to start using a responsive design on the front end. However, installing ruby / compass on all the developer's machines, integration environments, performance environments and production would kill the initiative.

per this question, and this simplified tutorial I used our current Ant build.xml to make some targets using jRuby.

gems in a jar trick to so that I don't need to install ruby everywhere: downloaded jruby-complete-1.6.8.jar per latest jruby has relative path issue as of 2013.03.20

java -jar jruby-complete-1.6.8.jar -S gem install -i ./susy susy  
jar uf jruby-complete-1.6.8.jar -C susy .  
java -jar jruby-complete-1.6.8.jar -S gem list

ant target used during the build process:

 <target name="compass.compile">
     <java classname="org.jruby.Main" fork="true" failonerror="true" classpathref="jruby.classpath">  
                <arg line="${basedir}/compile.rb ${basedir} compile ${basedir}"/>   
            </java>
     </target>

ant target used by Eclipse based IDE to 'auto-compile' when a user saves a scss file. Instructions to have Eclipse 'auto-build' scss files (start at step #5)

<target name="compass.dev">
        <path id="jruby.classpath">
            <fileset dir="../../../release/lib/arch/jruby">
                <include name="jruby-complete.jar"/>
            </fileset>            
        </path>
        <java classname="org.jruby.Main" fork="true" failonerror="true" classpathref="jruby.classpath">  
            <arg line="${basedir}/compile.rb ${basedir} compile ${basedir}"/>  
        </java>
    </target>

Finally, here is the 'compile.rb' used by the ant target:

Dir.entries(ARGV[0]).each do |lib|  
    $LOAD_PATH.unshift "#{ARGV[0]}/#{lib}/lib"  
end

require 'rubygems'
require 'compass' 
require 'susy'
require 'compass/exec'  

exit Compass::Exec::SubCommandUI.new([ARGV[1], ARGV[2], "-q"]).run!

and the config.rb used by compass:

 # Require any additional compass plugins here.  
# Set this to the root of your project when deployed:
require 'susy'

http_path = "./Web Content/"  
css_dir = "./Web Content/common/sass-output-css/"  
sass_dir = "./Web Content/common/sass/"
add_import_path  "./Web Content/sass"  
images_dir = "./Web Content/common/images/"  
javascripts_dir = "./Web Content/common/js/widgets"  
# To enable relative paths to assets via compass helper functions. Uncomment:  
#relative_assets = true  

and finally, trying to use susy in an scss file:

@import 'reset'; 
@import 'utilities';
@import 'baseColorVariables'; 
@import 'font';  
@import 'susy'; 


$total-columns: 12; 
$column-width: 4em; 
$gutter-width: 1em; 
$grid-padding: 1em;
.magic-container { @include container; } 

Solution

  • update as of 2013.03.20, this works. but it may not be the cleanest way to get Susy / compass on 'rubyless' machines. does anyone have anything cleaner?

    found it. compass is not in the sass load path, nor is susy actually while running under a 'gems in a jar' jruby solution. Thank you Henning Petersen, and your post
    specifically:

    JRuby has quite a brilliant abstraction from the file-based way of all things Ruby, so most things keep working when packaged into a JAR. A file inside a JAR has a path roughly like this: /path/to/jar/gems.jar!file/in/jar/script.rb. JRuby keeps relative files and everything working when using JARs, with one great BUT: There is no way to do such a thing as a directory listing inside a JAR file. That's right, everything that reads directory listings is now broken.

    I altered compass's frameworks.rb (not a fan) so it's directory listing call failure does not stop compass from loading itself into the sass load path:

    Compass::Frameworks.discover(:defaults)
    Compass::Frameworks.register_directory(File.join(Compass.base_directory, 'frameworks/compass'))
    Compass::Frameworks.register_directory(File.join(Compass.base_directory, 'frameworks/blueprint'))
    

    which changes a *.scss auto-compile request to:

    Syntax error: File to import not found or unreadable: susy.
                  Load paths:
                    <removed>/Web Content/common/sass
                    file:<removed>/release/lib/arch/jruby/jruby-complete.jar!/gems/compass-0.12.2/frameworks/compass/stylesheets
                    file:<removed>/release/lib/arch/jruby/jruby-complete.jar!/gems/compass-0.12.2/frameworks/blueprint/stylesheets
    

    ok, now we need to get susy into the load path. adding this line to compass's config.rb does not work, though I wish it did: add_import_path "../../../release/lib/arch/jruby/jruby-complete.jar!gems/susy-1.0.7/sass"

    Henning Petersen also caught this, and it was again because of directory listing calls withing the jruby jar altered compass's configuration/adapters.rb and Sass's importers/filesystem.rb. Altering all those files is dirtier to maintain than I am comfortable with, and already the posting is out of date regarding compass && sass.

    So I pulled the sass directory out of the jar, which let the compass's add_import_path work as intended. The cleanest solution I have so far is manually appending to the gem/compass-0.12.2/lib/frameworks.rb:

    Compass::Frameworks.register_directory(File.join(Compass.base_directory, 'frameworks/compass'))
    Compass::Frameworks.register_directory(File.join(Compass.base_directory, 'frameworks/blueprint'))
    

    and then adding this line to the compass project's config.rb (whole file provided):

     # Require any additional compass plugins here.  
    # Set this to the root of your project when deployed:
    require 'susy'
    
    http_path = "./Web Content/"  
    css_dir = "./Web Content/common/sass-output-css/"  
    sass_dir = "./Web Content/common/sass/"
    add_import_path  "./Web Content/susy-1.0.7-read-only"  
    images_dir = "./Web Content/common/images/"  
    javascripts_dir = "./Web Content/common/js/widgets"  
    # To enable relative paths to assets via compass helper functions. Uncomment:  
    #relative_assets = true  
    

    which led to the RAD / eclipse builder scss auto-compile ant target to spit out:

    compass.dev:
    BUILD SUCCESSFUL
    Total time: 16 seconds