How to access attribute which are stored as variables - ruby

model Sample has attributes car,bike
x ="bike"
y = Sample.new
How can I do?
y.x ??
It gives me an error
Is there any way I can do it, I know that x is an attribute but I dont know which one.
So how can I get y.x?

You can use send to invoke a method on an object when the method is stored as a string:
x = "bike"
y = Sample.new
y.send(x) # Equivalent to y.bike
The following are equivalent, except that you may send protected methods:
object.method_name
object.send("method_name")
object.send(:method_name)

You have to use dynamic message passing. Try this:
y.send :bike
Or, in your case
y.send x

Related

Accessing specific attribute of an object

Hello I have the following object
object = [#<ShopifyAPI::DiscountCode:0x000000000e1c78a8 #attributes={"code"=>"Disc2", "amount"=>"1.00", "type"=>"percentage"}, #prefix_options={}, #persisted=true>]
How can I properly access the "code" name of that object?
I have tried object[:code] and object.code but it appears I am overlooking something.
object is an array of ShopifyAPI::DiscountCode.
The best way to access it is
object[0].attributes['code']
If u want code of all the objects available in the array, you could get the array of values by
object.map { |obj| obj.attributes['code'] }
Given that this is an Array of ShopifyAPI::DiscountCodes (which inherit from ActiveResource::Base)
You can call the code method on them. eg:
object[0].code
#=> "Disc2"
object.map(&:code)
#=> ["Disc2"]
First, object is array:
obj0 = object[0]
Second, this is instance variable:
attributes = obj0.instance_variable_get(:#attributes)
Last, gets values by keys:
attributes['code']

How to use polymorphism to remove a switch statement which compares strings?

I am new to Ruby, so let me describe the context of my problem first:
I have a json as input which has the following key / value pair:
{
"service": "update"
}
The value has many different values for example: insert,delete etc.
Next there is a method x which handles the different requests:
def x(input)
case input[:service]
services = GenericService.new
when "update"
result = services.service(UpdateService.new,input)
when "insert"
result = services.service(InsertService.new,input)
when "delete"
result = services.service(DeleteService.new,input)
....
....
else
raise "Unknown service"
end
puts JSON.pretty_generate(result)
end
What is bothering me is that I still need to use a switch statement to check the String values (reminds me of 'instance of' ugh..). Is there a cleaner way (not need to use a switch)?
Finally I tried to search for an answer to my question and did not succeed, if however I missed it feel free to comment the related question.
Update: I was thinking to maybe cast the string to the related class name as follows: How do I create a class instance from a string name in ruby? and then call result = services.services(x.constantize.new,input) , then the class names ofcourse needs to match the input of the json.
You can try something like:
def x(input)
service_class_name = "#{input[:service].capitalize}Service"
service_class = Kernel.const_get(service_class_name)
service_class.new(input).process
end
In addition you might want to check if this is a valid Service class name at all.
I don't understand why you want to pass the service to GenericService this seems strange. let the service do it's job.
If you're trying to instatiate a class by it's name you're actually speaking about Reflection rather than Polymorphism.
In Ruby you can achieve this in this way:
byName = Object.const_get('YourClassName')
or if you are in a Rails app
byName= 'YourClassName'.constantize
Hope this helps
Just first thoughts, but you can do:
eval(services.service("#{input[:service].capitalize}Service.new, #{input})") if valid_service? input[:service]
def valid_service?
w%(delete update insert).include? input[:service]
end
As folks will no doubt shout, eval needs to be used with alot of care

want a calculation result instead of <bound method ...Python 2.8

I have tried finding this in the docs but don't quite get it. I am starting to work with Classes, When I try to get the result, I get instead of the actual 'width' I maybe I need to get but not sure.. It sounds too complicated just to get a result. Can someone advise?
I have:
class Rectangle(object):
def __init__(self, pt_ll, pt_ur):
self.ll = pt_ll
self.lr = Point(pt_ur.x, pt_ll.y)
self.ur = pt_ur
self.ul = Point(pt_ll.x, pt_ur.y)
def width(self):
"""Returns the width-float of the Rectangle."""
w = self.ur.x - self.ll.x
return w
Then I call it:
r = Rectangle(Point(0,0), Point(10,10))
print r.ur.x
print r.ll.x
print r.width
and get this output:
10.0
0.0
<bound method Rectangle.width of <__main__.Rectangle object at 0x000000000B5CBC50>>
print r.width
This returns the width method itself, this is what you see in the output.
You want to call that method so you need to instead do this:
print r.width()
This hints at an interesting thing about python, you can pass around functions just like you can with other variables.

Ruby send(attribute.to_sym) for Rails Method

I'm using Ruby 1.9.2 and need to go through all of the values for a table to make sure everything is in UTF-8 encoding. There are a lot of columns so I was hoping to be able to use the column_names method to loop through them all and encode the values to UTF-8. I thought this might work:
def self.make_utf
for listing in Listing.all
for column in Listing.column_names
column_value_utf = listing.send(column.to_sym).encode('UTF-8')
listing.send(column.to_sym) = column_value_utf
end
listing.save
end
return "Updated columns to UTF-8"
end
But it returns an error:
syntax error, unexpected '=', expecting keyword_end
listing.send(column.to_sym) = column_value_utf
I can't figure out how to make this work correctly.
You're using send wrong and you're sending the wrong symbol for what you want to do:
listing.send(column + '=', column_value_utf)
You're trying to call the x= method (for some x) with column_value_utf as an argument, that's what o.x = column_value_utf would normally do. So you need to build the right method name (just a string will do) and then send the arguments for that method in as arguments to send.

how to use object attribute value for method name ruby

I have a two mailers
welcome_manger(user) welcome_participant(user)
Both send different information and have different layouts.
when I call the deliver method I would like to use something like the following
UserMailer.welcome_self.role(self.user)
This does not work. How can I accomplish this?
Something like this perhaps:
m = 'welcome_' + self.role
UserMailer.send(m.to_sym, [self.user])
Assuming that self.role returns a String.
The send method invokes a method by name:
obj.send(symbol [, args...]) → obj
Invokes the method identified by symbol, passing it any arguments specified.
So you just need to build the appropriate method name as a string and then convert it a symbol with to_sym.

Resources