0

Hi i have made some custom template views for scaffold generators and put the in

lib/templates/erb/scaffold/_form.html.erb
lib/templates/erb/scaffold/edit.html.erb
lib/templates/erb/scaffold/index.html.erb
lib/templates/erb/scaffold/new.html.erb
lib/templates/erb/scaffold/show.html.erb

Everything is great so far, now i want to replace the content in scaffolds.css.scss (which is generate by the scaffold instruction) file with some custom styling.

I have included the scaffolds.css.scss or scaffolds.css from the above lines and nothing happens.

I have read this http://guides.rubyonrails.org/generators.html, but there is only mentioned how to skip the css generator, NOT how to replace it

======== EDIT =========

Debugging i found out that the original scaffold file is beeing taken from

/home/jgutierrez/.rvm/gems/ruby-1.9.3-p484/gems/railties-3.2.13/lib/rails/generators/rails/scaffold/templates/scaffold.css

.

[6, 15] in /home/jgutierrez/.rvm/gems/ruby-1.9.3-p484/gems/sass-rails-3.2.4/lib/rails/generators/sass_scaffold.rb

   6      class ScaffoldBase < ::Rails::Generators::NamedBase
   7        def copy_stylesheet
   8          dir = ::Rails::Generators::ScaffoldGenerator.source_root
   9          file = File.join(dir, "scaffold.css")
   10          debugger
=> 11          puts    "-------------------------------------------------#{file.path}"
   12          converted_contents = ::Sass::CSS.new(File.read(file)).render(syntax)
   13          create_file "app/assets/stylesheets/scaffolds.css.#{syntax}", converted_contents
   14        end
   15      end

Is there anyway to replace the place from where it is beeing taken? like the way templates views are replaced?

JGutierrezC
  • 4,398
  • 5
  • 25
  • 42

2 Answers2

1

I am not sure, but I think it is not documented because the generator always copies the same stylesheet, on the same place. So once your general layout is a bit fixed, you better always skip this, because the scaffold.css.scss most of the times messes up the rest of css :)

Not sure if this will work, but according to the code, you need to call the file scaffold.css.

nathanvda
  • 49,707
  • 13
  • 117
  • 139
  • thanks to your answer i know where scaffold.css is beeing taken. Is there some way to replace that place without replacing the gem code? I don't know if by application.rb or something like that. – JGutierrezC Feb 13 '14 at 21:57
  • Are you building a gem, or are you doing this inside a rails project? – nathanvda Feb 14 '14 at 08:16
  • Inside a rails project. But after i have modified the default scaffold templates, i would like to build a gem that can replace it all with an easy implementation. Can you point me which way to go? where to start – JGutierrezC Feb 14 '14 at 17:57
  • Honestly, inside a rails project i do not see the added value. Inside a gem i would store the css in the assets of the gem, and include it in the project. And when doing the scaffolding i would just skip css (because the css does not change for different scaffolds). – nathanvda Feb 14 '14 at 22:05
1

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!

D.Fux
  • 376
  • 2
  • 12