New Ruby on Rails project installer.

This commit is contained in:
Chris Eppstein 2009-02-03 11:34:39 -08:00
parent 94f4471ad5
commit a7406659b6
8 changed files with 153 additions and 114 deletions

View File

@ -9,21 +9,29 @@ module Compass
include Compass::Installers include Compass::Installers
attr_accessor :installer
def initialize(working_directory, options) def initialize(working_directory, options)
super(working_directory, options) super(working_directory, options)
installer_args = [project_template_directory, project_directory, self.options]
@installer = case options[:project_type]
when :stand_alone
StandAloneInstaller.new *installer_args
when :rails
RailsInstaller.new *installer_args
else
raise "Unknown project type: #{project_type}"
end
end end
# all commands must implement perform # all commands must implement perform
def perform def perform
installer.init
installer.run(:skip_finalization => true) installer.run(:skip_finalization => true)
UpdateProject.new(working_directory, options).perform if installer.compilation_required? UpdateProject.new(working_directory, options).perform if installer.compilation_required?
installer.finalize(:create => true) installer.finalize(:create => true)
end end
def installer
@installer ||= StandAloneInstaller.new(project_template_directory, project_directory, options)
end
def project_template_directory def project_template_directory
File.join(framework.templates_directory, "project") File.join(framework.templates_directory, "project")
end end

View File

@ -1,97 +0,0 @@
require File.join(File.dirname(__FILE__), 'base')
require File.join(File.dirname(__FILE__), 'create_project')
module Compass
module Commands
class InstallRails < CreateProject
def initialize(*args)
super
end
def perform
set_install_location
set_output_location
directory options[:stylesheets_location]
framework_templates.each do |t|
template "project/#{t}", "#{options[:stylesheets_location]}/#{t}", options
end
write_file 'config/initializers/compass.rb', initializer_contents
if has_application_layout?
next_steps
else
write_file 'app/views/layouts/application.html.haml', application_layout_contents
end
end
def initializer_contents
%Q{require 'compass'
# If you have any compass plugins, require them here.
Sass::Plugin.options[:template_location] = {
"\#{RAILS_ROOT}#{File::SEPARATOR}#{options[:stylesheets_location]}" => "\#{RAILS_ROOT}#{File::SEPARATOR}#{options[:css_location]}"
}
Compass::Frameworks::ALL.each do |framework|
Sass::Plugin.options[:template_location][framework.stylesheets_directory] = "\#{RAILS_ROOT}#{File::SEPARATOR}#{options[:css_location]}"
end
}
end
def application_layout_contents
%Q{!!! XML
!!!
%html{:xmlns => "http://www.w3.org/1999/xhtml", "xml:lang" => "en", :lang => "en"}
%head
%meta{'http-equiv' => "content-type", :content => "text/html;charset=UTF-8"}
%title= @browser_title || 'Default Browser Title'
= stylesheet_link_tag '#{stylesheet_prefix}screen.css', :media => 'screen, projection'
= stylesheet_link_tag '#{stylesheet_prefix}print.css', :media => 'print'
/[if IE]
= stylesheet_link_tag '#{stylesheet_prefix}ie.css', :media => 'screen, projection'
%body
%h1 Welcome to Compass
= yield
}
end
def next_steps
puts <<NEXTSTEPS
Congratulations! Your project has been configured to use Compass.
Next add these lines to the head of your application.html.haml:
%head
= stylesheet_link_tag '#{stylesheet_prefix}screen.css', :media => 'screen, projection'
= stylesheet_link_tag '#{stylesheet_prefix}print.css', :media => 'print'
/[if IE]
= stylesheet_link_tag '#{stylesheet_prefix}ie.css', :media => 'screen, projection'
(you are using haml, aren't you?)
NEXTSTEPS
end
def has_application_layout?
File.exists?(projectize('app/views/layouts/application.rhtml')) ||
File.exists?(projectize('app/views/layouts/application.html.erb')) ||
File.exists?(projectize('app/views/layouts/application.html.haml'))
end
def stylesheet_prefix
if options[:css_location].length >= 19
"#{options[:css_location][19..-1]}/"
else
nil
end
end
def set_install_location
print "Compass recommends that you keep your stylesheets in app/stylesheets/ instead of the Sass default location of public/stylesheets/sass/.\nIs this OK? (Y/n) "
answer = gets
self.options[:stylesheets_location] = separate(answer.downcase[0] == ?n ? 'public/stylesheets/sass' : 'app/stylesheets')
end
def set_output_location
print "\nCompass recommends that you keep your compiled css in public/stylesheets/compiled/ instead the Sass default of public/stylesheets/.\nHowever, if you're exclusively using Sass, then public/stylesheets/ is recommended.\nEmit compiled stylesheets to public/stylesheets/compiled? (Y/n) "
answer = gets
self.options[:css_location] = separate(answer.downcase[0] == ?n ? 'public/stylesheets' : 'public/stylesheets/compiled')
end
end
end
end

View File

@ -79,6 +79,7 @@ module Compass
self.options[:command] ||= self.options[:project_name] ? :create_project : :update_project self.options[:command] ||= self.options[:project_name] ? :create_project : :update_project
self.options[:environment] ||= :production self.options[:environment] ||= :production
self.options[:framework] ||= :compass self.options[:framework] ||= :compass
self.options[:project_type] ||= :stand_alone
end end
def trim_trailing_separator(path) def trim_trailing_separator(path)
@ -133,8 +134,8 @@ END
require library require library
end end
opts.on('--rails', "Install compass into your Ruby on Rails project found in the current directory.") do opts.on('--rails', "Sets the project type to a rails project.") do
self.options[:command] = :install_rails self.options[:project_type] = :rails
end end
opts.on('-q', '--quiet', :NONE, 'Quiet mode.') do opts.on('-q', '--quiet', :NONE, 'Quiet mode.') do

View File

@ -13,4 +13,5 @@ end
require File.join(File.dirname(__FILE__), 'installers', 'manifest') require File.join(File.dirname(__FILE__), 'installers', 'manifest')
require File.join(File.dirname(__FILE__), 'installers', 'base') require File.join(File.dirname(__FILE__), 'installers', 'base')
require File.join(File.dirname(__FILE__), 'installers', 'stand_alone') require File.join(File.dirname(__FILE__), 'installers', 'stand_alone')
require File.join(File.dirname(__FILE__), 'installers', 'rails')

View File

@ -15,17 +15,21 @@ module Compass
@options = options @options = options
@manifest = Manifest.new(manifest_file) @manifest = Manifest.new(manifest_file)
configure_option_with_default :logger configure_option_with_default :logger
configure
end end
def manifest_file def manifest_file
@manifest_file ||= File.join(template_path, "manifest.rb") @manifest_file ||= File.join(template_path, "manifest.rb")
end end
# Initializes the project to work with compass
def init
end
# Runs the installer. # Runs the installer.
# Every installer must conform to the installation strategy of configure, prepare, install, and then finalize. # Every installer must conform to the installation strategy of prepare, install, and then finalize.
# A default implementation is provided for each step. # A default implementation is provided for each step.
def run(options = {}) def run(options = {})
configure
prepare prepare
install install
finalize unless options[:skip_finalization] finalize unless options[:skip_finalization]
@ -36,9 +40,13 @@ module Compass
# It can be overridden it or augmented for reading config files, # It can be overridden it or augmented for reading config files,
# prompting the user for more information, etc. # prompting the user for more information, etc.
def configure def configure
[:css_dir, :sass_dir, :images_dir, :javascripts_dir].each do |opt| unless @configured
configure_option_with_default opt [:css_dir, :sass_dir, :images_dir, :javascripts_dir].each do |opt|
configure_option_with_default opt
end
end end
ensure
@configured = true
end end
# The default prepare method -- it is a no-op. # The default prepare method -- it is a no-op.

View File

@ -0,0 +1,117 @@
module Compass
module Installers
class RailsInstaller < Base
def configure
configuration_file = targetize('config/initializers/compass.rb')
if File.exists?(configuration_file)
open(configuration_file) do |config|
eval(config.read, nil, configuration_file)
end
end
end
def init
set_sass_dir unless sass_dir
set_css_dir unless css_dir
directory css_dir
directory sass_dir
write_file 'config/initializers/compass.rb', initializer_contents
end
def prepare
end
def finalize(options = {})
if options[:create]
puts <<-NEXTSTEPS
Congratulations! Your rails project has been configured to use Compass.
Sass will automatically compile your stylesheets during the next
page request and keep them up to date when they change.
Make sure you restart your server!
Next add these lines to the head of your layouts:
NEXTSTEPS
end
puts stylesheet_links
puts "\n(You are using haml, aren't you?)"
end
def sass_dir
Compass.configuration.sass_dir
end
def css_dir
Compass.configuration.css_dir
end
def images_dir
separate "public/images"
end
def javascripts_dir
separate "public/javascripts"
end
def set_sass_dir
recommended_location = separate('app/stylesheets')
default_location = separate('public/stylesheets/sass')
print %Q{Compass recommends that you keep your stylesheets in #{recommended_location}
instead of the Sass default location of #{default_location}.
Is this OK? (Y/n) }
answer = gets.downcase[0]
Compass.configuration.sass_dir = answer == ?n ? default_location : recommended_location
end
def set_css_dir
recommended_location = separate("public/stylesheets/compiled")
default_location = separate("public/stylesheets")
puts
print %Q{Compass recommends that you keep your compiled css in #{recommended_location}/
instead the Sass default of #{default_location}/.
However, if you're exclusively using Sass, then #{default_location}/ is recommended.
Emit compiled stylesheets to #{recommended_location}/? (Y/n) }
answer = gets.downcase[0]
Compass.configuration.css_dir = answer == ?n ? default_location : recommended_location
end
def initializer_contents
%Q{require 'compass'
# If you have any compass plugins, require them here.
Compass.configuration do |config|
config.project_path = RAILS_ROOT
config.sass_dir = "#{sass_dir}"
config.css_dir = "#{css_dir}"
end
Compass.configure_sass_plugin!
}
end
def stylesheet_prefix
if css_dir.length >= 19
"#{css_dir[19..-1]}/"
else
nil
end
end
def stylesheet_links
html = "%head\n"
manifest.each_stylesheet do |stylesheet|
ss_line = " = stylesheet_link_tag '#{stylesheet_prefix}#{stylesheet.to.sub(/\.sass$/,'.css')}'"
if stylesheet.options[:media]
ss_line += ", :media => '#{stylesheet.options[:media]}'"
end
if stylesheet.options[:ie]
ss_line = " /[if IE]\n " + ss_line
end
html << ss_line + "\n"
end
html
end
end
end
end

View File

@ -12,10 +12,13 @@ module Compass
super super
end end
def prepare def init
directory "" directory ""
directory css_dir directory css_dir
directory sass_dir directory sass_dir
end
def prepare
directory images_dir if manifest.has_image? directory images_dir if manifest.has_image?
directory javascripts_dir if manifest.has_javascript? directory javascripts_dir if manifest.has_javascript?
end end

View File

@ -47,15 +47,13 @@ class CommandLineTest < Test::Unit::TestCase
within_tmp_directory do within_tmp_directory do
generate_rails_app("compass_rails") generate_rails_app("compass_rails")
Dir.chdir "compass_rails" do Dir.chdir "compass_rails" do
compass "--rails" do |responder| compass("--rails", ".") do |responder|
responder.respond_to "Is this OK? (Y/n) ", :with => "Y" responder.respond_to "Is this OK? (Y/n) ", :with => "Y"
responder.respond_to "Emit compiled stylesheets to public/stylesheets/compiled? (Y/n) ", :with => "Y" responder.respond_to "Emit compiled stylesheets to public/stylesheets/compiled/? (Y/n) ", :with => "Y"
end end
# puts @last_result # puts @last_result
assert_action_performed :create, "app/stylesheets/screen.sass" assert_action_performed :create, "./app/stylesheets/screen.sass"
assert_action_performed :create, "config/initializers/compass.rb" assert_action_performed :create, "./config/initializers/compass.rb"
assert_action_performed :create, "app/views/layouts/application.html.haml"
assert_action_performed :create, "config/initializers/compass.rb"
end end
end end
rescue LoadError rescue LoadError