Recently I encountered a similar problem and google took me here. What I want is to replace the default scss of generated view. Finally I solved it so I'd like to share the workaround for anyone who would come here later. My enviroment is Ruby 2.3.0 with Rails 5.0, and I think this also work on Rails 4+ at least.
As JGutierrezC's debugging, the .scss file is generated by sass-rails gem rather than the original railties gem. And if you have a look at the sass-rails's code, you will find that it just source the file under ../template
:
https://github.com/rails/sass-rails/blob/5-0-stable/lib/rails/generators/scss/assets/assets_generator.rb#L6
require "rails/generators/named_base"
module Scss
module Generators
class AssetsGenerator < ::Rails::Generators::NamedBase
source_root File.expand_path("../templates", __FILE__)
def copy_scss
template "stylesheet.scss", File.join('app/assets/stylesheets', class_path, "#{file_name}.scss")
end
end
end
end
So it will not work if you only put a .css under your template directory because the generator always searches the template file in the directory ../template
, which doesn't follow the conversion described in the rails guide. Well, what we need to do is to override this behavior. Let's walk into the main generator code of rails:
https://github.com/rails/rails/blob/5-0-stable/railties/lib/rails/generators.rb#L354
def self.lookup(namespaces) #:nodoc:
paths = namespaces_to_paths(namespaces)
paths.each do |raw_path|
["rails/generators", "generators"].each do |base|
path = "#{base}/#{raw_path}_generator"
begin
require path
return
rescue LoadError => e
raise unless e.message =~ /#{Regexp.escape(path)}$/
rescue Exception => e
warn "[WARNING] Could not load generator #{path.inspect}. Error: #{e.message}.\n#{e.backtrace.join("\n")}"
end
end
end
end
When you insert one line after the assignment of path
to print it value and invoke the rails g scaffold ...
, you may get things like below:
...
"rails/generators/rails/scss/scss_generator"
"generators/rails/scss/scss_generator"
"rails/generators/rails/scss_generator"
"generators/rails/scss_generator"
"rails/generators/scss/assets/assets_generator"
invoke scss
...
These line shows the generator finding process of rails. The being-resuce block does one thing--Finding the first directory by such order which contains the generator and require it, then return. So if we create our generator in directory before the last one, it could been reqired by rails rather than the original one. Simply copy the original files to your application workspace:
(your ruby install path)/ruby-2.3.0/gems/sass-rails-5.0.5/lib/rails/generators/scss/assets/*
to
(your app path)/lib/generators/rails/scss/
and rename the assets_generator.rb
to scss_generator.rb
.
Then run the scaffold command again, you'll find output is different:
...
"rails/generators/rails/scss/scss_generator"
"generators/rails/scss/scss_generator"
invoke scss
...
Rails finds the generator we created and requires it, nice! And now the scss_generator will use the template (your app path)/lib/generators/rails/scss/template/stylesheet.scss
. So the last thing to do is to custom it and the changes will reflect to the scaffold's view scss.
And if you want to replace the default scaffold.scss, there will be a little more things to do. You need to copy related methods to scss_generator.rb as you have changed the original finding path and rails won't reuqire them in original files.
require "rails/generators/named_base"
module Scss
module Generators
class AssetsGenerator < ::Rails::Generators::NamedBase
source_root File.expand_path("../templates", __FILE__)
def copy_scss
template "stylesheet.scss", File.join('app/assets/stylesheets', class_path, "#{file_name}.scss")
end
end
end
end
# ruby-2.3.0/gems/sass-rails-5.0.5/lib/rails/generators/scss/scaffold/scaffold_generator.rb
require "sass/css"
module Sass
module Generators
class ScaffoldBase < ::Rails::Generators::NamedBase
def copy_stylesheet
dir = "#{::Rails.application.config.root}/lib/templates/erb/scaffold/"
file = File.join(dir, "scaffold.css")
converted_contents = ::Sass::CSS.new(File.read(file)).render(syntax)
create_file "app/assets/stylesheets/scaffolds.#{syntax}", converted_contents
end
end
end
end
# ruby-2.3.0/gems/sass-rails-5.0.5/lib/rails/generators/scss/scaffold/scaffold_generator.rb
module Scss
module Generators
class ScaffoldGenerator < ::Sass::Generators::ScaffoldBase
def syntax() :scss end
end
end
end
And change the value of variable dir
in copy_stylesheet method to where you put your scaffold.scss, such as:
dir = "#{::Rails.application.config.root}/lib/templates/erb/scaffold/"
.
Now you can use your own scaffold.css as you wish!