Is there any issues to have `end` as a method name? - ruby

I am working on a RoR project, and I want to know if I can use end as a method name. It seems to work fine, but I would like to know if this method will bring any issues in the future. I tried and it works:
class Dany
def end
puts 'Hola'
end
end
and this is the output:
Dany.new.end # => Hola

Ruby let's you do this, but you're going to run into all sorts of issues.
# end.rb
class Dany
def end
puts "Hola"
end
def other
end # should puts Hola
end
end
Instead, you will get
end.rb:10: syntax error, unexpected keyword_end, expecting end-of-input
Bottom line: don't do this. Don't use any keywords as a method name.

It is not a good idea to use a keyword as a method name, but as long as you disambiguate the token as a method call, you can use it. It is not practical though.
Dany.new.instance_eval{self.end} # => Hola
Dany.new.send(:end) # => Hola
Dany.new.method(:end).call # => Hola
Dany.new.instance_eval{end} # => syntax error, unexpected keyword_end
The usual disambiguation using () does not seem to work for this case, making it complicated.
Dany.new.instance_eval{end()} # => syntax error, unexpected keyword_end

Related

I am unable to execute this program

error:C:\Users\RR\Desktop\ruby_sandbox>ruby classes.rb classes.rb:44:
syntax error, unexpected end-of-input, expecting keyword_end
my code is:
class Animal
attr_accessor :name,:age,:sex,:location
def initialize(age=18,sex="not available",location="not specified")
puts "details of animal"
#age=age
#sex=sex
#location=location
end
def condition(age,name)
if animal.age>animal1.age
puts "#{animal.name } is older than #{animal1.name}"
else
puts "animals age are in increasing order"
end
end
Please take care about your indentation while writing ruby you will see where you missed the end keyword.
But in your case the problem is not only about the indentation before start to fix it. You can check some documentation about Class and Instance Methods in Ruby or this tutorial can help you in your case.
Good luck.

rspec expectations on block

I have the below code under test:
class MethodCache
##methods=Hash.new
def self.add_method(name, &block)
##methods[name]=block
end
def self.get_method(name)
##methods[name]
end
end
Now my spec looks like this:
describe MethodCache do
subject {MethodCache}
foo_block = ->{ puts "foo"}
it ".get_method" do
subject.add_method "foo", &foo_block
# does not work
# expect(subject.get_method("foo").to be &foo_block
# should syntax works
subject.get_method("foo").should be foo_block
end
end
I am trying to stay away from should syntax and use the expect syntax of RSpec. However it does not work in this case.
expect(subject.get_method("foo").to be &foo_block fails saying wrong number of arguments. I guess this is because the expectation block is treated as a block argument.
expect(subject.get_method("foo").to be foo_block (without the '&') does not work either. It says, the matcher expects a value and not argument.
What am I missing here?

ruby *args syntax error

I found this weirdness that I would like to understand. If I define these two methods in pry...
def test(*args)
puts args
end
def test=(*args)
puts args
end
they both work.But if I put the above code in a module and include that module in another class (say, class Job), the following
j=Job.last
j.test=(1,2,3)
throws the following error...
SyntaxError: (irb):3: syntax error, unexpected ',', expecting ')'
j.test=(1,2,3)
^
The following work as expected...
j.test=[1,2,3]
j.test=(1)
So, it looks like inside the module, a method defined with an '=' always expects one arg. That doesn't make sense to me.
What am I missing
Parsing of the Ruby interpreter. Try
j.send :test=, 1, 2, 3
use directly
j.test = 1,2,3
or
j.test= ([1,2,3])
or `
j.send('test=',[1,2,3])

Using class_eval to overwrite an association

I have a Message model that has the following relationships:
belongs_to :sender, Class: "User"
belongs_to :recipient, Class: "User"
I'm attempting to use class_eval to overwrite the recipient method in certain cases.
This works:
def update_recipient(message, recipient_addition = nil)
message.class_eval <<-EVAL
def recipient
"test"
end
EVAL
end
message.recipient => "test"
However, this doesn't:
def update_recipient(message, recipient_addition = nil)
message.class_eval <<-EVAL
def recipient
[#{message.recipient}, #{recipient_addition}]
end
EVAL
end
(eval):3: syntax error, unexpected keyword_end, expecting ']'
The first # is misinterpreted as a comment character, discarding the rest of the line. The #{} are expected to be interpolated inside double quotes, though there doesn't seem to be a reason to put these in #{} right now as they are just simple string values.
["#{message.recipient}", "#{recipient_addition}"]
... unless you're planning something like:
["To: #{message.recipient}", "CC: #{recipient_addition}"]

Regex error inside class-eval block

I've got some code to add methods to a module from simple definitions for talking to remote resources via a wrapper class around a REST client.
def service_function(function_name, method, uri, parameters)
class_eval <<-RUBY
def #{function_name}(params)
if !(#{function_name}_required_params - params.keys).empty? || \
!(params.keys - #{function_name}_params).empty?
raise Errors::InvalidParameters.new(service_name, __method__,
params.keys, #{function_name}_params)
end
WebServices::ServiceRequest.perform(self.domain, #{uri}, #{method}, params)
end
def #{function_name}_params
#{function_name}_required_params + #{function_name}_optional_params
end
def #{function_name}_required_params
#{parameters}.select { |param,req| req }.keys
end
def #{function_name}_optional_params
#{parameters}.select { |param,req| !req }.keys
end
RUBY
end
Before I can even run the code, just requiring the gem I'm building into IRB spits out this error:
1.9.2p320 :001 > require 'web-services'
SyntaxError: (eval):7: unknown regexp options - rt
The offending line is:
WebServices::ServiceRequest.perform(self.domain, #{uri}, #{method}, params)
Removing the "#{uri}" argument fixes it, even leaving in the "#{method}" argument. Does anyone out there have a clue as to why this might be? I'm about at my wit's end.
You have a url that looks something like /something/rt and that will look like a regex literal in here:
WebServices::ServiceRequest.perform(self.domain, #{uri}, #{method}, params)
You need to escape and quote #{uri} so that it looks like a string inside the heredoc, that way class_eval will see perform(..., '/something/rt', ...) and be happy. You might have similar issues with #{method}.

Resources