Rails app template is running code and thowing fits - ruby-on-rails

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 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).

Related

Rails- upgrading to ruby 2.2.2 - no implicit conversion of Array into String (TypeError)

very new to ruby and rails.. Ive been working on a project, that simply reads in files and parses them to store into a database. Project was running fine, however running the code after an update to ruby 2.2.2 , I received an error that wasn't previously there:
in `foreach': no implicit conversion of Array into String (TypeError)
Here is the snippet of the foreach thats causing an error: (let me know if more code is necessary).
def parse(file_name)
File.foreach(file_name).with_index do |line, line_num|
puts "\nLine #{line_num}: #{line}"
Does anyone know whats going on?
Thank you
EDIT: Sorry it was a snippet! Im calling this ruby code into my rails Test called "parse_log_file_test"
require File.dirname(__FILE__) + '/../test_helper'
class ParseLogFileTest < ActiveSupport::TestCase
filename = Array.new
Dir.glob('database/oag-logs/*.log').each do |log_file|
filename.push(log_file)
end
parser = ParseLogFile.new
parser.parse(filename)
test 'parse' do
parser = ParseLogFile.new
filename.each do |log_file|
begin
parser.parse(log_file)
rescue
puts"ERROR: Unable to parse line #{log_file}"
end
end
assert true
end
end
I'm guessing you omitted the end to your function, but if you don't have it, you need it.
This error indicates that the argument passed to parse as file_name is an array instead of a string.
However, if that's the case, it fails the same on e.g. Ruby 1.8.4:
File.foreach([]).with_index do |line, line_num|
puts "\nLine #{line_num}: #{line}"
end
Output:
TypeError: can't convert Array into String
from (irb):1:in `foreach'
from (irb):1:in `with_index'
from (irb):1
from :0
Thus my guess is that the code that produces the value you pass to parse returned a string in your previous Ruby version and returns an array in 2.2.2.
In your case, the error is caused by the first invocation of parser.parse(...), right above the test 'parse' do line, not by the invocation inside the test method. I guess you put that invocation there after the migration, probably to debug a problem. But you are passing a different argument to the first invocation than to the invocation inside the test method, so it fails for a different reason than the one in the test method.
To see what Error is caused inside your test, simply remove the lines
rescue
puts"ERROR: Unable to parse line #{log_file}"
(Keep the end or you'll have to remove the begin, too.)
This way, an Error will hit the test runner, which will usually display it including message and stack trace.
Agreed with the poster above that you are most likely missing quotation marks. It should have nothing to do with 2.2.2 though, probably you are copy-pastying your file name differently this time around.
So apparently this is an issue with upgrading to ruby 2.2.2 on windows. After getting past this error, I only encountered more errors.. nokogiri..etc
I have recently got a mac and the errors went away.

String with a semicolon results in "unterminated string meets end of file" in RubyMine

In the RubyMine debugger, just type this into the watches:
';'
or
";"
and I am getting the error:
"unterminated string meets end of file"
Why is this? It doesn't happen in the Rails console, and it doesn't have anything to do with RubyMine, as far as an I can tell.
This is the result of the Ruby debugger having different parsing rules from the Ruby interpreter. In fact, the regular Ruby debugger, invoked from irb or the ruby command exhibits this same behaviour. The workaround, however, is straightforward: to create a string literal consisting of a single semicolon, just escape it with a backslash:
$ irb
> require 'debugger'
=> true
> debugger
(rdb:1) ';'
*** SyntaxError Exception: /usr/local/rvm/rubies/ruby-1.9.3-p286/lib/ruby/1.9.1/irb/context.rb:166: unterminated string meets end of file
(rdb:1) '\;'
";"
It's important to note that the Ruby debugger command-line parser is not the same as the parser used by the irb or ruby interpreter: it is designed around parsing debugger commands such as backtrace, break etc. and not for parsing the Ruby language (with shell-like extensions in the case of irb). It has limited support for evaluating Ruby (or Ruby-style) expressions. This is, of course, crucial to effective debugging of Ruby programs. However, you should not expect it to be able to parse everything that irb or the ruby command itself would be able to parse or to parse things in exactly the same way. In some cases, like this, it can handle certain expressions but they need to be escaped subject to the parsing rules of the debugger as opposed to the Ruby language itself.
The Rails console is built on top of irb and is, thus, a Ruby shell and respects the parsing rules of the Ruby language just like irb and ruby.
I had the same problem with the Ruby CSV library parsing a CSV with a Semicolon as delimiter. I added the col_sep ';' but it always resulted in the following error: unterminated string meets end of file
Correct way of doing it:
CSV.open(file.path, col_sep: '\;', &:readline)
Added this as documentation for anybody else.

Why URI.escape fails when called on ActionView::OutputBuffer?

I'm upgrading an application from Rails 2 to Rails 3. Apparently, calling render() now returns ActionView::OutputBuffer and not String. I need to pass the results of render() to URI.escape(), and this fails with exception...
Here is my brief testing in the console
ob = ActionView::OutputBuffer.new("test test")
URI.escape(ob)
`NoMethodError: undefined method 'each_byte' for nil:NilClass`.
from /opt/ruby19/lib/ruby/1.9.1/uri/common.rb:307:in `block in escape'
from ..../ruby/1.9.1/gems/activesupport-3.2.1/lib/active_support/core_ext/string/output_safety.rb:160:in `gsub'
from ..../ruby/1.9.1/gems/activesupport-3.2.1/lib/active_support/core_ext/string/output_safety.rb:160:in `gsub'
from /opt/ruby19/lib/ruby/1.9.1/uri/common.rb:304:in `escape'
from /opt/ruby19/lib/ruby/1.9.1/uri/common.rb:623:in `escape'
Moreover, calling to_s on OutputBuffer returns same OutputBuffer class, so I cannot even convert this buffer into a honest string?
ob.to_s.class
ActionView::OutputBuffer
Of course, calling URI.escape("test test") returns "test%20test" as expected, so this is not URI problem.
Environment:
ruby 1.9.3p125 (2012-02-16 revision 34643) [i686-linux]
Rails 3.2.1
My question is: Why does this happen and how can I work around this issue?
Update: Apparently, using '' + ob as a form of ob.to_s converts OutputBuffer to String, which effectively works around the problem... But my question 'why does this happen' still remains, e.g. is this a bug, should I report it, or I'm doing something wrong?
This is a bug in Rails:
When calling gsub with a block on an ActiveSupport::SafeBuffer the global variables $1, $2, etc. for referencing submatches are not always properly set (anymore?) when the block is called.
This is why URI.escape (and any other function that uses gsub() will fail on ActiveSupprt::Safebuffer.
There are several discussions about this, apparently the safest route right now is to call to_str before passing SafeBuffer to anything that can call gsub, e.g. URI.encode, escape_javascript and similar functions.
My other quesion about to_s returning the same class - obviously safe buffer will return itself and not a bare String, this is by design. In order to get a true String, .to_str can be used.
This is due to the fact that Rails 3 introduced the concept of safe buffers
In Rails3 your Views are protected by XSS by default by making all rendering be safely escaped unless you explicitly use the raw() helper or html_safe
This is a dumb bug that i'm currently encountering in Rails 5. My stupid workaround was to do something like
ob = ActionView::OutputBuffer.new("test test")
URI.escape(ob.to_sym.to_s)
Again it works, but i'm still looking for a cleaner solution.

Rails production environment breaks with cycle

Have a rails app (3.0.9) using HAML, local development server runs fine. But when I run rails s -e production, my page gives this error:
NoMethodError: undefined method `+#' for #<String:0x00000006331098>
The error says it is on this line (from the view, written in HAML):
%tr{:class=> cycle("even","odd")}
I'm not finding anything about why this is happening. Please help.
Does the cycle method do any sort of string concatenation?
I encountered this error recently during a code review.
The code was something like this:
anObject.instance_method +string_var
The instance_method was returning a string which was to be appended with the string value present in variable string_var.
Changing the code to this worked
anObject.instance_method + string_var # Note the space after the +
Without space the unary + method is invoked on the string_var, but no unary + method is defined on the String class. Hence the exception.
Note that the unary + method is defined as def +#, hence the exception message says "Method +# not found".
This gist makes it clear : https://gist.github.com/1145457
Anyways, in your case, the method cycle (do not know whether it is defined by you or is part of a gem) is probably doing some string concatenation without proper spacing OR the exception backtrace is not pointing to the right line of code.
Hope this helps.

Ruby 1.9 doesn't support Unicode normalization yet

I'm trying to port over some of my old rails apps to Ruby 1.9 and I keep getting warnings about how "Ruby 1.9 doesn't support Unicode normalization yet." I've tracked it down to this function, but I'm getting about 20 warning messages per request:
rails-2.3.5/activesupport/lib/active_support/inflector.rb
def transliterate(string)
warn "Ruby 1.9 doesn't support Unicode normalization yet"
string.dup
end
Any ideas how I should start tracking these down and resolving it?
If you are aware of the consequences, i.e. accented characters will not be transliterated in Ruby 1.9.1 + Rails 2.3.x, place this in config/initializers to silence the warning:
# http://stackoverflow.com/questions/2135247/ruby-1-9-doesnt-support-unicode-normalization-yet
module ActiveSupport
module Inflector
# Calling String#parameterize prints a warning under Ruby 1.9,
# even if the data in the string doesn't need transliterating.
if Rails.version =~ /^2\.3/
undef_method :transliterate
def transliterate(string)
string.dup
end
end
end
end
Rails 3 does indeed solve this issue, so a more future-proof solution would be to migrate towards that.
The StringEx Gem seems to work pretty well. It has no dependency on Iconv either.
It adds some methods to the String class, like "to_ascii" which does beautiful transliteration out of the box:
require 'stringex'
"äöüÄÖÜßë".to_ascii #=> "aouAOUsse"
Also, the Babosa Gem does a great job transliterating UTF-8 strings, even with language support:
"Jürgen Müller".to_slug.transliterate.to_s #=> "Jurgen Muller"
"Jürgen Müller".to_slug.transliterate(:german).to_s #=> "Juergen Mueller"
Enjoy.
That method definition is wrapped in an if-statement for Ruby 1.9. Right above it, you will find the regular definition, which shows a bit more of what this is doing. It's a method used to convert accented characters into their regular variants. E.g.: á => a, or ë => e
But this method is only used in parameterize, which is in turn defined right above transliterate. This is all still in ActiveSupport. I can't find anything that is directly calling parameterize.
So perhaps you're using parameterize or transliterate yourself, somewhere in your Rails application?
Common usage (according to the parameterize documentation) is for creating friendly permalinks from arbitrary strings, much like SO does, for example:
http://stackoverflow.com/questions/2135247/ruby-1-9-doesnt-support-unicode-normalization-yet
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Replace the body of the method with
raise "transliterate called"
and observe a backtrace which will show you where the stuff is coming from at the first call. Your app will of course collapse as well but that will likely give you the culprit from the first try.
I appreciate that this is a dirty way to solve the problem, but having read the error message I'm aware of the issue. So I want to get rid of the warnings. I dropped this code in environment.rb:
module ActiveSupport
module Inflector
# Calling String#parameterize prints a warning under Ruby 1.9,
# even if the data in the string doesn't need transliterating.
# Maybe Rails 3 will have fixed it...?
if RAILS_GEM_VERSION =~ /^2\.3/
undef_method :transliterate
def transliterate(string)
string.dup
end
end
end
end
If you'd rather not monkey patch the Inflector module, you can also do this...
Both of the following worked for me to silence this annoying "Ruby 1.9 doesn't support Unicode normalization yet" warning:
silence_stream(STDERR) {
whatever_code_caused_transliterate_to_be_called
}
or
silence_warnings {
whatever_code_caused_transliterate_to_be_called
}
This does have the disadvantage that it requires cluttering up your calling code, but it is a technique you can use generally whenever you don't want to see warnings or other output.
activesupport provides silence_stream and silence_warnings in activesupport-2.3.11/lib/active_support/core_ext/kernel/reporting.rb
String#unicode_normalize, String#unicode_normalize!, String#unicode_normalized? will be introduced in Ruby 2.2. Sample code and implementation can be seen in test case, lib/unicode_normalize.rb and lib/unicode_normalize/normalize.rb.
// U+00E1: LATIN SMALL LETTER A WITH ACUTE
// U+U+0301: COMBINING ACUTE ACCENT
puts "\u00E1" == "a\u0301".unicode_normalize(:nfc)
puts true == "a".unicode_normalized?(:nfc)

Resources