Less not compiling automatically with pow - ruby

I'm building an application with Padrino, and I've decided to use less for the stylesheet, mostly to use twitter bootstrap.
I am having some trouble getting less to automatically compile my less files when serving the app via pow.
When I run padrino start and use the embedded server, I get nice styling, but I don't really understand how. The application.css file that is generated is exactly how it should be, except there are no changes to the application.css file in my app's public dir.
When I run the app through pow, though, no changes made to the application.less file are reflected on the application.css file, which is the only one served.
I'm mostly trying to understand how and why less is only compiled when running webrick.
My less initializer is:
module LessInitializer
def self.registered(app)
# Enables support for Less template reloading for rack.
# Store Less files by default within 'app/stylesheets/'
# See http://github.com/kelredd/rack-less for more details.
require 'rack/less'
# optional - use as necessary
Rack::Less.configure do |config|
config.compress = true
config.cache = true
# other configs ...
end
app.use Rack::Less,
:root => Padrino.root,
:source => 'app/stylesheets',
:public => 'public',
:hosted_at => 'stylesheets'
end
end
And my application.less file is:
#import "bootstrap/bootstrap.less";
body {
padding-top: 60px;
padding-bottom: 40px;
}
.sidebar-nav {
padding: 9px 0;
}

I've just tried this with Padrino edge and Pow and it's working alright.
To be honest, it shouldn't really make a difference whether it's Pow or Webrick - as long as it's rack complaint it should just work.
You can try changing padrino's gem on your test project to point to:
gem 'padrino', :git => 'git://github.com/padrino/padrino-framework.git'
There's currently an unmet dependency for less on edge but it should be merged soon. So if the above didn't work, use this:
gem 'padrino', :git => 'git://github.com/padrino/padrino-framework.git', :branch => 'fix-less-dependencies'
If you keep on having a problem, would you mind opening an issue on Github?
Thanks!

Related

Using guard live reload and guard compass seems to conflict

I'm trying to use guard livereload and guard compass together. Here is my file
A sample Guardfile
# More info at https://github.com/guard/guard#readme
guard 'compass' do
watch('^sass/(.*)\.s[ac]ss')
end
guard 'livereload' do
watch(%r{.+\.(css|html|js)$})
end
# This will concatenate the javascript files specified in :files to public/js/all.js
#guard :concat, type: "js", files: %w(), input_dir: "public/js", output: "public/js/all"
#guard :concat, type: "css", files: %w(), input_dir: "public/css", output: "public/css/all"
#guard 'uglify', :destination_file => "public/javascripts/application.js" do
# watch (%r{app/assets/javascripts/application.js})
#end
When i begin to guard, without enabling the chrome live reload extension, my sass files are compiled and work well.
But when I enable the livereload extension, my terminal says that browser is connected, and then when i make changes in my sass files, nothing happens (neither the page reloads, nor the sass files are compiled).
Does anyone have any ideas ?
For the moment, I'm lauching two terminals in windows, one where I do compass watch, and one where I do guard (I commented the compass part of the GuardFile).
If someone has a better solution
This is how I do it and works perfectly.
puts "Using default guard file."
group :development do
if File.exists?("./config.rb")
# Compile on start.
puts `compass compile --time --quiet`
# https://github.com/guard/guard-compass
guard :compass do
watch(%r{(.*)\.s[ac]ss$})
end
end
guard :livereload, :host => '127.0.0.1', :port => '35729', :grace_period => 0.5 do
watch(%r{.+\.(css|js|html?|php|inc|theme)$})
end
end
All this does is tells Compass where my config.rb is... Which is in the base of my site where my Guardfile is kept. Then it has compass compile the SCSS.
Not sure about your situation but in mine I needed to set the host and port for it to work smoothly. But basically guard will watch for a change and once compass outputs the css file LiveReload notices the change and then reloads that file. Pretty simple.
Im sure you know already but add all the correct Gems to your Gemfile, run 'bundle' on your project and then initiate Guard using $ guard
In your browser make sure you hit the LiveReload button and it will tell you in the terminal that browser is connected and away you go.
Hope that helps.

Service to compile SASS online: is it safe to allow users manually import Compass extensions?

I'm creating another HTML/CSS fiddle web app. It is based on Sinatra and supports SASS with Compass extensions.
Here's how it works.
1) Require Compass and extensions:
require 'compass'
require 'singularitygs'
require 'breakpoint-slicer'
2) Add Compass load paths into Sass class:
Compass.sass_engine_options[:load_paths].each do |path|
Sass.load_paths << path
end
This code is borrowed from SassMeister.
3) Receive an AJAX request with SASS, compile and return CSS:
post '/compile-sass' do
sass = params[:sass]
begin
sass(sass.chomp, {:style => :nested, :quiet => true})
rescue Sass::SyntaxError => e
status 200
e.to_s
end if sass
end
Kinda very simple functionality. A user has to provide SASS code where manually he #imports any of supported Compass extensions:
#import breakpoint-slicer
html
+from(3)
background-color: pink
Questions:
Is it safe to let users import anything? When an extension outside of SASS load paths is being imported, SASS won't compile and throws an error. But JedFoster, the author of SassMeister, considers such behavior a performance and security hole and has made SassMeister comment out manual imports. Why?
Is there anything that i can improve in the given code?

Ruby on Rails 3.1 assets:precompile and images

I can't get the Rails 3.1 asset pipeline precompilation to work in production mode. It always fails on images referenced within SCSS with an error like:
$ bundle exec rake assets:precompile RAILS_ENV=production
rake aborted!
rails.png isn't precompiled
(in /home/florian/AssetTest/app/assets/stylesheets/application.css.scss)
But when I look in the public/assets directory, the image is there, so it is precompiled:
$ ls public/assets | grep rails
rails-dd352fc2630e5f9aa5685ef1d7fe5997.png
The SCSS file in this case just contains some test code:
/*
* This is a manifest file that'll automatically include all the stylesheets available in this directory
* and any sub-directories. You're free to add application-wide styles to this file and they'll appear at
* the top of the compiled file, but it's generally better to create a new file per style scope.
*= require_self
*= require_tree .
*/
body {
background: #ffffff image-url('rails.png') no-repeat 0 center;
}
If I don't use the image-url helper in SCSS, but just url('/assets/rails.png'), precompilation works fine, and a manifest.yml file is generated in public/assets.
The interesting thing is: if I change the SCSS back to image-url('rails.png') and run another precompilation, it still works (I guess because the image is now already listed in the manifest file).
What am I doing wrong here? I don't really want to disregard the helper methods (as using them is The Way You Should Do It, right?), and I definitely don't want to create the manifest file manually...
I've run into the same problem myself. This is apparently a bug in Rails 3.1.0, and will hopefully be fixed in short order...
In any event, in production.rb, you can try this:
config.assets.compile = true
You likely have it set to false, which it should be. However, having it set to false causes issues when you use asset helpers in SCSS as you're trying to do. Setting that value to true seems to properly allow compilation while using those helpers.
Take a look at this issue on github for some details.

Broken precompiled assets in Rails 3.1 when deploying to a sub-URI

I'm in the process of updating a Rails 3 app to use Rails 3.1 and as part of that, am making use of the new asset pipeline. So far, I've got everything working apart from one rather annoying problem I can't solve.
The application and all its assets works fine in development, but in production it is deployed to a sub-URI using Passenger (http://the-host/sub-uri/). The problem with this is that the assets are pre-compiled during deployment and one of my CSS (well, it's a .css.scss file) files is making use of the image-url helper from the sass-rails gem. Since during the pre-compilation process, the paths are hard-coded into the precompiled CSS file, the sub-uri is not taken account of:
In my .css.scss file:
body { background-image: image-url("bg.png"); }
The result in the compiled application-<md5-hash-here>.css file:
body { background-image: url(/assets/bg.png); }
What it should be to make it work correctly:
body { background-image: url(/sub-uri/assets/bg.png); }
Is this scenario just asking too much? If so, I'll have to switch back to the old non-asset-pipelined way and just serve my images and CSS from public. However it seems like something which should have been thought about and solved...? Am I missing the solution?
Edit 1: I should note that using the erb solution instead yields the same result, as one would expect.
Edit 2: in response to Benoit Garret's comment
No, the problem isn't related to the config.assets.prefix. I tried setting that (to /sub-uri/assets rather than the default of /assets) but it turned out that was the wrong thing to do - it seems like this setting is already in relation to the root of the Rails app, not the server. Removing that (and thus returning to the default) has fixed all the weird issues that caused (and there were many, all the assets ended up in /sub-uri/sub-uri/assets - it was all very strange). The only problem is that the image-url helper and friends do not pick up the sub-URI when they are pre-compiled. Needless to say, this is logical since when it is pre-compiled, it couldn't possibly know that when it's running under Passenger, it'll be configured in this way. My question is how to inform it of this and thus end up with the correct paths in the precompiled result. If indeed it can be done.
My current workaround is to reference the iamge in the CSS like this: url(../images/bg.png) and place it in the non-pipelined public/images location. Hardly ideal since it doesn't benefit from the fingerprinting and everything which the pipeline provides.
Finally I've worked out a couple of workarounds/solutions.
1) From https://github.com/rails/sass-rails/issues/17 it looks like this could get fixed in sass-rails. I've monkey-patched helpers.rb myself along the lines of the proposed patch in the link above. I simply set the required environment variable in the asset precompile line in deploy.rb.
I do all my monkey patching in a single file config/initializers/gem_patches.rb. In this file I patched this method as:
module Sass
module Rails
module Helpers
protected
def public_path(asset, kind)
path = options[:custom][:resolver].public_path(asset, kind.pluralize)
path = ENV['PRODUCTION_URI'] + path if ENV['PRODUCTION_URI']
path
end
end
end
end
2) Alternatively if you are ok to embed images in the CSS, changing the stylesheet to have a .erb extension, and replacing the image-url("bg.png") with url(<%= asset_data_uri "bg.png" %>) will work without any need to change sass-rails. asset-data-uri doesn't exist as a pure Sass function so you have to use the Rails helper asset_data_uri.
In the latest Rails 3.1.3 you need to monkey patch a different module now, for it to work
This is what I did
module Sprockets
module Helpers
module RailsHelper
def asset_path(source, options = {})
source = source.logical_path if source.respond_to?(:logical_path)
path = asset_paths.compute_public_path(source, asset_prefix, options.merge(:body => true))
path = options[:body] ? "#{path}?body=1" : path
if !asset_paths.send(:has_request?)
path = ENV['RAILS_RELATIVE_URL_ROOT'] + path if ENV['RAILS_RELATIVE_URL_ROOT']
end
path
end
end
end
end
And in my deploy.rb I have:
desc "precompile the assets"
namespace :assets do
task :precompile_assets do
run "cd #{release_path} && rm -rf public/assets/* && RAILS_ENV=production bundle exec rake assets:precompile RAILS_RELATIVE_URL_ROOT='/my_sub_uri'"
end
end
before "deploy:symlink", "assets:precompile_assets"
I'm using Rails 3.1.3 and deploying to a sub-URI successfully.
I have NOT monkey-patched anything.
The key problems with this setup have been better discussed here. As you can see, the solution was applied to Rails 3.2 and never backPorted to 3.1.4.
But, I have came to a solution using Rails 3.1.3 that works for my setup.
Try this: (I'm no expert, just trying to contribute to solve a problem that hassled me for hours...)
environment.rb:
#at top:
ENV['RAILS_RELATIVE_URL_ROOT'] = '/rais'
production.rb:
config.assets.prefix = ENV['RAILS_RELATIVE_URL_ROOT'] ? ENV['RAILS_RELATIVE_URL_ROOT'] + '/assets' : '/assets'
routes.rb:
Rais::Application.routes.draw do
scope ENV['RAILS_RELATIVE_URL_ROOT'] || '/' do #see config/environment.rb
<<resources here>>
end
end
As you can see, I've put assets.prefix inside production.rb, not in application.rb
After that you do:
rake assets:clear
rake assets:precompile
and than, test with the console:
RAILS_ENV=production rails console
Results:
foo = ActionView::Base.new
foo.stylesheet_link_tag 'application'
=> "<link href=\"/rais/assets/layout.css?body=1\" media=\"screen\" rel=\"stylesheet\" type=\"text/css\" />\n<link href=\"/rais/assets/application.css?body=1\" media=\"screen\" rel=\"stylesheet\" type=\"text/css\" />"
foo.image_tag('arrow-up.png')
=> "<img alt=\"Arrow-up\" src=\"/rais/assets/arrow-up-ca314ad9b991768ad2b9dcbeeb8760de.png\" />"
After a bit of digging around, I have found the issue. The issue is in Rails, specifically Sprockets::Helpers::RailsHelper::AssetPaths#compute_public_path. Sprockets::Helpers::RailsHelper::AssetPaths inherits from ActionView::AssetPaths and overrides a number of methods. When compute_public_path is called through the Sass::Rails::Resolver#public_path method is sass-rails, the rails sprocket helper picks up the task of resolving the asset. Sprockets::Helpers::RailsHelper::AssetPaths#compute_public_path defers to super which is ActionView::AssetPaths#compute_public_path. In this method there is a condition of has_request? on rewrite_relative_url_root as seen below:
def compute_public_path(source, dir, ext = nil, include_host = true, protocol = nil)
...
source = rewrite_relative_url_root(source, relative_url_root) if has_request?
...
end
def relative_url_root
config = controller.config if controller.respond_to?(:config)
config ||= config.action_controller if config.action_controller.present?
config ||= config
config.relative_url_root
end
If you look at the internals of rewrite_relative_url_root it relies on a request to be present and the ability to derive it from the controller variable in order to resolve the relative url root. The issue is that when sprockets resolves these assets for sass it does not have a controller present and therefore no request.
The solution above didn't work in development mode for me. Here is the solution that I am using to make it work for now:
module Sass
module Rails
module Helpers
protected
def public_path(asset, kind)
resolver = options[:custom][:resolver]
asset_paths = resolver.context.asset_paths
path = resolver.public_path(asset, kind.pluralize)
if !asset_paths.send(:has_request?) && ENV['RAILS_RELATIVE_URL_ROOT']
path = ENV['RAILS_RELATIVE_URL_ROOT'] + path
end
path
end
end
end
end

rack-offline in sinatra

I am trying to setup rack-offline in Sinatra, but I am having trouble setting it up. In rails it is prettty easy, but have no found any examples in Sinatra...
Basically, in your config.ru, map /application.manifest to Rack::Offline. (If you're not familiar with using config.ru with your Sinatra application, check out this part of Sinatra docs.) Here's an example, which caches all the files under directory public:
require 'your-app'
require 'rack/offline'
map "/application.manifest" do
offline = Rack::Offline.new :cache => true, :root => "public" do
# Cache all files under the directory public
Dir[File.join(settings.public, "**/*")].each do |file|
cache file.sub(File.join(settings.public, ""), "")
end
# All other files should be downloaded
network '/'
end
run offline
end
map "/" do
run Sinatra::Application
end
Remember to set manifest="/application.manifest" in your html tag and you should be good to go. You should take a look at rack-offline's README for more documentation and explanation of how it works.

Resources