erb gives me - undefined local variable or method for main:Object (NameError) - ruby

erb gives me undefined local variable or method for main:Object (NameError) unless the variable used in erb template is a global variable.
Is that correct? on ruby 1.8.7 (2010-01-10 patchlevel 249) [i486-linux]
Below is code that works. If I remove $ from the variable name ($db, $db_root, $db_root_password) I get the error.
$db = get_single_argument("database name")
$db_root = get_single_argument("database root user name")
$db_root_passwd = get_single_argument("database root user password")
mysql_commands = get_conf_file("installer_mysql.erb")
puts mysql_commands.result #gives me the error
and get_conf_file procedure
def get_conf_file(file)
return_array = Array.new
if (File.exists?(file))
return_array = ERB.new File.read(file)
end
return_array
end

Ruby has a concept called a binding, which you might think of as the local variables, value of self, block etc. that a piece of code might have. You might also think of a binding as the code's context.
Erb's result method takes an optional second method which is the binding with which to evaluate the code you give it, so you can do stuff like
x = 1
ERB.new('x=<%= x %>').result(binding) #=> "x=1"

You're not passing in the binding of the caller, and you should be:
puts mysql_commands.result(binding)
The binding contains all the variable references in the current scope.

Related

How to use let variables in rails console?

using
rspec 2.6.4
rails 3.1.6
How to use let variables in rails test console?
1.9.3-p0 :032 > let(:user) { create(:user) }
NoMethodError: undefined method `let' for main:Object
Please advise, which library should be required here?
For example: below is executed in console to use stub methods in console.
require 'rspec/mocks/standalone'
Is it possible, to define and call let variables in rails console?
If you are fine with let just creating globals, you can polyfill it like this:
def let(name)
Object.send :instance_variable_set, "##{name}", yield
Object.send :define_method, name do
Object.send :instance_variable_get, "##{name}"
end
end
Usage is the same as rspec:
irb(main):007:0> let(:foo) { 1 }
=> :foo
irb(main):008:0> foo
=> 1
though you really shouldn't be pasting your test code into console to debug it. It's much better to use a breakpoint tool like pry or byebug.
let in rspec is not much more than a lazily executed and memoized method definition. If you must have in the irb you could define it like this:
$ cat let.rb
def let(sym)
$let ||= {}
define_method sym do
$let[sym] ||= yield
end
end
require './let in irb or place it in .irbrc and you have your rspec-like let. Note, that rspec reevaluates let in each new example (it or specify block). Since you don't have them in irb you may need to clear your let cache manually ($let = {}) to force re-evaluation.

Undefined local variable or method `translator' for main:Object (NameError)

I've used a gem and tried to create a method (trans) in my code.
require 'yandex-translator'
translator = Yandex::Translator.new(api_key)
def trans(text)
a = translator.translate text, to: "ru"
return a
end
puts trans("stack")
When I run the code, I get this error:
'trans': undefined local variable or method `translator' for main:Object (NameError)
Why did I get this error, and how can I solve this?
translator variable in this code is defined on class level, hence it’s a local variable in main context (since the whole code is executed in main context.)
You are trying to call it from the instance context, where it is obviously not defined. The easiest way to overcome it, would be to define #translator as being a class’ instance variable:
#translator = Yandex::Translator.new(api_key)
def trans(text)
#translator.translate text, to: "ru"
end
Because in this way you are looking for a local variable translator and you have not. Some solutions:
make translator global
$translator = Yandex::Translator.new(api_key)
or pass translator to trans method
def trans(translator, text)
translator.translate text, to: "ru"
end

Ruby unknown + on trying to join 2 strings

So, I'm learning Ruby and immediately, have stumbled upon something rater peculiar when trying to concatenate 2 strings to one. Here's the code, with irrevelant parts stripped, lets just say Sinatra runs it:
class CMS
# Set the site path root.
#sitePath = "./site"
get '/' do
renderCache = File.readlines(#sitePath + "index.liquid")
end
end
And on loading the page, I am greeted with
NoMethodError at /
undefined method `+' for nil:NilClass
on the renderCache = File.readlines(#sitePath + "index.liquid") line. Why is it refusing to concatenate the strings?
You can't set instance variables at the class level. You need to set them in an instance method.
Look's like you're using sinatra so you can do this:
See here for how to make a "before filter" like one does in Rails apps. This solution is for the modular style of Sinatra app.
To show an example:
class CMS < Sinatra::Base
before do
#sitePath = "./site"
end
get '/' do
renderCache = File.readlines(#sitePath + "index.liquid")
end
end
CMS.run!
You could also keep your existing code if you use a constant instead of an instance variable:
class CMS
# Set the site path root.
SitePath = "./site"
get '/' do
renderCache = File.readlines(CMS::SitePath + "index.liquid")
end
end
To explain how I read your error and looked for the error:
undefined method '+' for nil:NilClass means you're calling + on something which is nil. Referencing the code shows that the nil variable is #sitePath. Undefined instance variables will evaluate to nil. This is different than standard variables, which will raise an undefined variable error.

undefined method `at_css' for #<String:0x007fe9ac5ae310> (NoMethodError)

I'm trying to get all of my prices in my array of URLS, getting the values with a CSS selector.
The thing is, the method at_css is giving me the following error:
undefined method `at_css' for string (NoMethodError)
Can anyone help me? Thanks
test = ["www.myweb.com/1", "www.myweb.com/2"]
test.each do |item|
Nokogiri::HTML(open(item))
puts item.at_css('.itemprice').text
puts item.at_css('.description').text
puts "Empty Line"
end
The item variable in your block is a string i.e. an element from your test array variable. And strings don't have a to_css method in Ruby. You probably wanted to call the to_css on some Nokogiri-related object.
I think you need the following:
some_var = Nokogiri::HTML(open(item))
some_var.at_css('.itemprice').text

Why do undeclared Ruby local, instance, class, & global variables have different behavior?

Some undeclared variables are nil, some throw an error. How come?
$ irb
1.9.3p0 :001 > asdf # local
NameError: undefined local variable or method `asdf' for main:Object
from (irb):1
from /Users/saizai/.rvm/rubies/ruby-1.9.3-p0/bin/irb:16:in `<main>'
1.9.3p0 :002 >#asdf # instance
=> nil
1.9.3p0 :003 >##asdf # class
NameError: uninitialized class variable ##asdf in Object
from (irb):3
from /Users/saizai/.rvm/rubies/ruby-1.9.3-p0/bin/irb:16:in `<main>'
1.9.3p0 :004 > $asdf # global
=> nil
Class variables must always be assigned or else they will return a NameError when you attempt to use them. I do not currently have the details as to why this is.
Instance and Global variables will return nil even if they are not assigned. However, they will raise a warning if you run the script with the -w flag.
I do, however, have the answer in regards to the local variables. The reason local variables act like this comes in the fact that they do not have any punctuation in front of them. This means the variable could be either a variable or a method call (since Ruby does not require () after a method call with no parameters).
something # could be a variable named 'something' or a method called 'something()'
If there is no value assigned to something variable then the Ruby interpreter assumes it is a method invocation. If there is no method by that name then it raises NameError. That is why you will get this message:
NameError: undefined local variable or method 'something' for main:Object
from (irb):1
from path/to/Ruby/bin/irb:12 in '<main>'
So, it is important for the Ruby interpreter to treat local variables in this manner just in case it is actually a method you are referring to.
As an interesting side note:
There is one quirk—a variable comes into existence when the Ruby
interpreter sees an assignment expression for that variable. This is
the case even if that assignment is not actually executed. A variable
that exists but has not been assigned a value is given the default
value nil.
Which means that:
if false
z = "Something"
end
z.nil? #=> true
never_assigned.nil? #=> NameError
The above quote is from The Ruby Programming Language by David Flanagan and Yukihiro Matsumoto section 4.2

Resources