What object do I need to respond to .map(&:key)? (ruby) - ruby

I'm doing a code challenge, and know the message I need my code to respond to.
I also know I have the correct data in my object to pass the test, I just can't seem to get the format correct.
The test is
class.method.map(&:name)
Which should return an array of names that the method returns.
I have tried having my method return a hash with :name as a key and an array containing the hash but neither work, I'm getting this error
rb:82:in `each': undefined method `name' for [:name, "Name I want returned"]:Array
What do I need to do to respond to the map call correctly?

class.method.map(&:name) means
class.method.map do |instance|
instance.name
end
So basically your method needs to return a enumeration of objects, which has a method named name.

Related

How can I export existing AWS ELB policies? undefined method 'reduce'

We want to export our ELB configurations for re-use. I can get the ELB configs with:
all_elbs = Fog::AWS::ELB.load_balancers.all()
But this returns a failure:
all_policies = Fog::AWS::ELB.policies.all()
#=> /Library/Ruby/Gems/2.0.0/gems/fog-aws-0.0.6/lib/fog/aws/models/elb/policies.rb:20:
#=> in `munged_data': undefined method `reduce' for nil:NilClass (NoMethodError)
Ultimately, I want to be able to recreate a ELB based on an existing ELB.
That error message means that on line 20 of policies.rb there is code like foo.reduce and foo happens to be nil.
If we look at the source code of the gem, we see:
def munged_data
data.reduce([]){ |m,e| # line 20
So, the problem is that data is nil when the munged_data method is called. We see on line 8 of the same file that data is defined via a simple attr_accessor call. I cannot tell for sure where that should have been set. (There are 227 instances of #data = or data = in the gem.) This seems like a bug in the AWS gem, unless you were supposed to call some method before calling .all on policies.
Tracing further, we see that policies is defined in load_balancer.rb on line 154 as:
def policies
Fog::AWS::ELB::Policies.new({
:data => policy_descriptions,
:service => service,
:load_balancer => self
})
end
Assuming that the data passed to the method is used directly as the #data instance variable, then the problem is that policy_descriptions returned nil.
The implementation of policy_descriptions is:
def policy_descriptions
requires :id
#policy_descriptions ||= service.describe_load_balancer_policies(id).body["DescribeLoadBalancerPoliciesResult"]["PolicyDescriptions"]
end
If service.describe_load_balancer_policies(id).body["DescribeLoadBalancerPoliciesResult"] returned nil (or any object that did not have a [] method) this method would have thrown an error. So, my deduction is that this returned something like a hash, but that hash has no "PolicyDescriptions" key.
From there...I don't know.

Ruby : Converting String to a Method Call

I am new to Ruby. I'm trying to convert a string to a method call in
Ruby. I intend to store all my function calls in an Excel Worksheet and
use the extracted strings to make the actual method call. But I am not
able to convert the string obtained from the excel and use it as a
function call. I read somewhere that the Send() method helps convert
strings to method calls. But I am not able to use it correctly. For the
code mentioned below I obtain a "in <top (required)>': undefined method
Execute_Statement(5)' for main:Object (NoMethodError)"
begin
def Execute_Statement(var1)
puts("Hello",var1)
end
end
x='Execute_Statement(5)' #This would be fed from the Excel Worksheet
send(x)
What am I doing wrong ?
You can either adopt the bad practice, i.e. Just do eval(x). If don't want to adopt it, do some more work as below :
def Execute_Statement(var1)
puts("Hello",var1)
end
s = "Execute_Statement(5)" # I hope this is coming from your excel cell.
method_name,number = s[/.*(?=\()/],s[/\d+/]
send(method_name,number.to_i)
Remove the begin..end block, it is not needed for your case.
You should be passing your parameter as part of the send call. Also the method name needs to be a symbol. In other words define the function name as a symbol and define your parameter as a separate variable, then call send like so:
def Execute_Statement(var1)
puts("Hello",var1)
end
method_name = 'Execute_Statement'.to_sym
parameter = 5
send(method_name,parameter)
As commenter above says this does not seem like a great idea.

How to set a method dynamically as other class method

Im new to Ruby, and im creating a cli app with Thor and some additional gems. My problem is that i take user input (from the console) and pass the data as a variable to a existing method (This method is from a gem)
My method
def search(searchtype, searchterm)
search = OtherClass.new
result = search.search.searchtype keyword: "#{searchterm}"
puts result
# search.search.searchtype is not a method in the gem im using.
end
The OtherClass gem has these search methods: users, repos
The users method
def users(*args)
arguments(args, :required => [:keyword])
get_request("/legacy/user/search/#{escape_uri(keyword)}", arguments.params)
end
The repos method
def repos(*args)
arguments(args, :required => [:keyword])
get_request("/legacy/repos/search/#{escape_uri(keyword)}", arguments.params)
end
So how can i pass in the user data to the method from the OtherClass? Heres something like what i would want to do. The SEARCHTERM would be dynamically passed to the search.search object as a method parameter.
def search(SEARCHTYPE, searchterm)
search = OtherClass.new
result = search.search.SEARCHTYPE keyword: "#{searchterm}"
puts result
end
The "#{searchterm}" works as expected, but i also want to pass in the method to the search.search object dynamically, this could probably be done with if's but im sure theres a better way, maybe the Ruby way to solve this problem.
Finally i would want to be able to use this little program like this (the serch method)
./search.rb search opensource linux
(where opensource could be users, or another type of search, and linux could be the search keyword for the searchtype)
If this is possible i would apprechiate any help!
Thnx!
If you'd like to call a method dynamically, use Object#send.
http://ruby-doc.org/core-1.9.3/Object.html#method-i-send
I would caution against sending a method that was obtained by user input though, for security reasons.

How to return the receiver instance's self from should_receive block

I'd like to have instance methods of a class return self, and be init with another class instance self.
However I'm struggling to see how to spec this succintly:
::Api.should_receive(:new).once do |arg|
arg.should be_an_instance_of(::Cli)
end
When running this spec, this ensures that the next method is called on true instead of the Api instance, as expected, that is the return value of the block. Example:
class Cli
def eg
api = Api.new(self)
api.blowup # undefined method for true
end
end
I'd really like the block to return the Api instance self without invoking another call to Api.new(...) in the spec, the example below does this and to my mind a non-rspec reader would wonder why the spec passes when clearly Api.new(...) has been called more than once.
Can anyone suggest how best to do this?
Current solution:
This reads like ::Api.new(...) is called thrice: once to create api, once to create cli, once to create start. Yet the spec of one call passes. I understand why and that this is correct, so not a bug. However I'd like a spec that a reader not familiar with rspec could scan and not have the impression that Api.new has been called more than once. Also note that ...once.and_return(api){...} does not work, the block needs to return api in order to pass.
let(:cli){ ::Cli.start(['install']) }
let(:start){ ::Cli.start(['install']) }
it 'is the API' do
api = ::Api.new(cli)
::Api.should_receive(:new).once do |arg|
arg.should be_an_instance_of(::Cli)
api
end
start
end
You can save the original method (new) in a local variable and then use it to return the new api from within the block:
original_method = ::Api.method(:new)
::Api.should_receive(:new).once do |arg|
arg.should be_an_instance_of(::Cli)
original_method.call(arg)
end
This will run the expectation, checking that the argument is an instance of ::Cli, and then return the value from the original method (i.e. the api).

Adding object to array of arrays

I am trying to add an object to an array of arrays, but when i do, i am recieving an error in my array of array unit tests, stating :- "undefined method 'has_key' for nil:NilClass". However, if i try and add a string or number to the array of array, it works absolutely fine.
I set up my array of arrays like this
#array_of_array= Array.new(5) { Array.new(3) }
Now if I try to do this
#array_of_array[0][0] = MyObject.new
Then if I run my unit tests against #array_of_array, i get the error.
But if I try to do this
#array_of_array[0][0] = 'Test'
Theres no problem.
--Edited---
Heres failing test
it "should place object in correct starting position" do
array_of_array= Array.new(5) { Array.new(3) }
array_of_array[1][0] = MyObject.new
array_of_array.should eql('fail on purpose..want to see output')
end
Im new to ruby, so unsure of where im going wrong. Thanks
Like Claw said, the error probably means that your MyObject.new statement is returning a nil object for some reason. Then you're trying to call the function 'has_key' of that nil object.
Does your MyObject class throw an exception if you use .new! instead of .new ? If so, you could see why it's failing to return a proper MyObject object.
Edit
To catch an exception inside your 'new' method for the MyObject model, you could do something like:
def new
begin
#whatever is done in this method
rescue => exception
puts exception.message
end
end

Resources