开发者

Rails app template is running code and thowing fits

开发者 https://www.devze.com 2023-03-12 17:16 出处:网络
I\'m trying to create a Rails app template I have this block of code in there file \'config/sass.rb\', <<-RUBY

I'm trying to create a Rails app template I have this block of code in there

file 'config/sass.rb', <<-RUBY

  Sass::Engine::DEFAULT_OPTIONS[:load_paths].tap do |load_paths|
    load_paths << "#{Rails.root}/app/assets/stylesheets"
    load_paths << "#{Gem.loaded_specs['compass'].full_gem_path}/frameworks/compass/stylesheets"
  end

RUBY

When I run 'rails new' with this template I get the following error:

undefined method `root' for Rails:Module (NoMethodError)

I'm new to app templates as well as this code block syntax. (What do you even call that <<-RUBY block? It's really hard to search for on google). It was my impression that it wouldn't be running any of the code inside the block so it开发者_Python百科 shouldn't be causing errors. What gives?

UPDATE: Let me add some more context:

I'm trying to modify the app template here: https://github.com/leshill/rails3-app/blob/master/app.rb I want add the code from this blog post: http://metaskills.net/2011/05/18/use-compass-sass-framework-files-with-the-rails-3.1-asset-pipeline/ so that I can have compass support in rails3.1


To elaborate on mu's point.

The <<-SOMESTIRING syntax defines the beginning of a string. The string is terminated with SOMESTRING (at the start of the line)

For example you see this a lot

  string = <<-EOF
    Hey this is a really long string

    with lots of new lines
  EOF
  string # => "  Hey this is a really long string\n\n  with lots of new lines\n"

In this case the RUBY is to signify that this is ruby code (that will be evaluated). You have to remember that when inside a string the #{ruby_code} escape syntax will evaluate the ruby_code given and insert the result into the string.

So to get around this you can do something like,

    irb >> s = <<-RUBY
      "#{'#{Rails.root}'}/app/assets/stylesheets"
    RUBY
    #=> ""\#{Rails.root}/app/assets/stylesheets"\n"

Here we break out of the string using #{} and then use the single quotes to tell ruby that we don't want the #{Rails.root} evaluated.

EDIT: I was thinking more about this, and realized this is equivalent and a little cleaner

  irb >> s= <<-RUBY
    Rails.root.to_s + "/app/assets/stylesheets"
  RUBY #=> "Rails.root.to_s + "/app/assets/stylesheets"\n"

This way we don't have to worry about escaping at all : )


You are asking the "rails new" command to create a file and passing a block of content using a "heredoc" (signaled by the <<-SOMESTRING syntax). More about heredoc:

http://en.wikipedia.org/wiki/Here_document#Ruby

The parser will treat the content just like a Ruby string surrounded by doublequotes and attempt to substitute any string enclosed by #{}. It fails because it can't find a variable named Rails.root.

You can avoid the substitution behavior (have the content treated like a Ruby string surrounded by singlequotes) by using single-quote-style-heredoc. Surround the heredoc signal with singlequotes:

file 'config/sass.rb', <<-'RUBY'

Sass::Engine::DEFAULT_OPTIONS[:load_paths].tap do |load_paths| load_paths << "#{Rails.root}/app/assets/stylesheets" load_paths << "#{Gem.loaded_specs['compass'].full_gem_path}/frameworks/compass/stylesheets" end

RUBY

Since you're creating Rails app template for a starter app, it might be helpful to look at the

Rails 3.1 Application Templates from the Rails Apps project on GitHub.

The project provides good examples of app templates plus documentation (be sure to take a look at Thor::Actions and Rails::Generators::Actions).

0

精彩评论

暂无评论...
验证码 换一张
取 消