Ruby - dry-rb - how to update an existing object's attributes? - ruby

Using dry-rb structs and types, I'm trying amend an object that has already been created, but can't seem to figure it out.
[3] pry(main)> class User < Dry::Struct
attribute :name, Types::String.optional
attribute :age, Types::Coercible::Integer
end
=> User
[4] pry(main)> user = User.new(name: nil, age: '21')
=> #<User name=nil age=21>
[5] pry(main)> user.name = "ted"
NoMethodError: undefined method `name=' for #<User name=nil age=21>
Did you mean? name
from (pry):10:in `__pry__'
[6] pry(main)> user(name: "Ted")
NoMethodError: undefined method `user' for main:Object
Did you mean? super
from (pry):11:in `__pry__'
[7] pry(main)> user[:name => "Ted"]
Dry::Struct::MissingAttributeError: Missing attribute: {:name=>"Ted"}
from /Users/me/.rvm/gems/ruby-2.6.5/gems/dry-struct-1.3.0/lib/dry/struct.rb:137:in `block in []'
[8] pry(main)> user('name' => 'Ted')
NoMethodError: undefined method `user' for main:Object
Did you mean? super
from (pry):13:in `__pry__'
Is this just not possible, or am I missing something super obvious? Any help is much appreciated

Related

Accessing httparty API results in ruby

I'm trying to access the API results from HTTParty, but can't figure out how...I've stored the results in a variable called zillow that looks like the following:
=> {"searchresults"=>
{"request"=>{"address"=>"49 Alpine Way", "citystatezip"=>"28805"},
"message"=>{"text"=>"Request successfully processed", "code"=>"0"},
"response"=>
{"results"=>
{"result"=>
{"zpid"=>"5628657",
"links"=>
{"homedetails"=>"http://www.zillow.com/homedetails/49-Alpine-Way-Asheville-NC-28805/5628657_zpid/",
"graphsanddata"=>"http://www.zillow.com/homedetails/49-Alpine-Way-Asheville-NC-28805/5628657_zpid/#charts-and-data",
"mapthishome"=>"http://www.zillow.com/homes/5628657_zpid/",
"comparables"=>"http://www.zillow.com/homes/comps/5628657_zpid/"},
"address"=>
{"street"=>"49 Alpine Way",
"zipcode"=>"28805",
"city"=>"Asheville",
I'm trying to access "zpid" but keep getting nil as a response. I've tried the following:
[107] pry(main)> zillow["searchresults"]["zpid"]
=> nil
[108] pry(main)> zillow["zpid"]
=> nil
[109] pry(main)> zillow["searchresults"]["results"]["zpid"]
NoMethodError: undefined method `[]' for nil:NilClass
from (pry):100:in `<main>'
[110] pry(main)> zillow.find["zpid"]
NoMethodError: undefined method `[]' for #<Enumerator:0x0000000323b3f8>
from (pry):101:in `<main>'
[111] pry(main)> zillow.get["zpid"]
NoMethodError: undefined method `get' for #<HTTParty::Response:0x00000003adb0f8>
from /home/pjw/.rvm/gems/ruby-2.3.0/gems/httparty-0.14.0/lib/httparty/response.rb:85:in `method_missing'
[112] pry(main)> zillow["searchresults"]
=> {"request"=>{"address"=>"49 Alpine Way", "citystatezip"=>"28805"},
"message"=>{"text"=>"Request successfully processed", "code"=>"0"},
What am I missing?
You missed a chain of keys to get zpid
zillow["searchresults"]["response"]["results"]["result"]["zpid"]
If you on ruby 2.3.0 then you can use Hash#dig method

Simple ruby code demonstrating default arguments is throwing name/method error

Seems pretty straightforward. Trying to write a simple code that has a default argument. This throws an error with a name error and method error. Code should be able to take any argument and print the arg and if not arg given print "meat".
Any help why its throwing errors?
def meal_choice( meal = "meat")
puts "#{meal}"
end
Failures:
1) #meal_choice should default to meat
Failure/Error: expect(meal_choice).to eq("meat")
NameError:
undefined local variable or method `meal_choice' for #<RSpec::ExampleGroups::MealChoice:0x007fb4ec159188>
# ./spec/meal_choice_spec.rb:3:in `block (2 levels) in <top (required)>'
2) #meal_choice should allow you to set a meal
Failure/Error: expect(meal_choice("vegan")).to eq("vegan")
NoMethodError:
undefined method `meal_choice' for #<RSpec::ExampleGroups::MealChoice:0x007fb4ec14b0d8>
# ./spec/meal_choice_spec.rb:7:in `block (2 levels) in <top (required)>'
Finished in 0.00125 seconds (files took 0.12294 seconds to load)
2 examples, 2 failures
Failed examples:
rspec ./spec/meal_choice_spec.rb:2 # #meal_choice should default to meat
rspec ./spec/meal_choice_spec.rb:6 # #meal_choice should allow you to set a meal
It is a working code:
[1] pry(main)> def meal_choice( meal = "meat")
[1] pry(main)* puts "#{meal}"
[1] pry(main)* end
#=> :meal_choice
[2] pry(main)> meal_choice
#=> meat
#=> nil
[3] pry(main)> meal_choice(:sdgsdg)
#=> sdgsdg
#=> nil
You must be having a typo in the method call or wrongly calling a method.
You need to make the method do the work without puts:
def meal_choice (meal = "meat")
meal
end

why does Object.superclass.respond_to? :object_method ?

I am confused.
When I define a method in Object
I can call it in Objects superclass BasicObject!
Like so:
class Object
def object_method
"object_method called"
end
end
Object.superclass.respond_to? :object_method
# => true
Object.superclass.object_method
# => "object_method called"
I have expected that only derived classes inherit the new method!
P.S.: I come to this question from an exercise on rubymonk
.. implement a method superclasses inside Object ..
where the recursion stop criterion is "affected".
When you call Object.superclass, you get an object that describes BasicObject class.
This object is an instance of Class class that inherits from Object. Therefore, it has all the methods that Object has, including the one you added.
However, instances of the BasicObject class do not have this method:
irb(main):122:0> Object.object_method
=> "object_method called"
irb(main):123:0> Object.new.object_method
=> "object_method called"
irb(main):124:0> Object.superclass.object_method # Same as BasicObject.object_method
=> "object_method called"
irb(main):125:0> Object.superclass.new.object_method # Same as BasicObject.new.object_method
NoMethodError: undefined method `object_method' for #<BasicObject:0x441743be>
from (irb):125:in `evaluate'
from org/jruby/RubyKernel.java:1065:in `eval'
from org/jruby/RubyKernel.java:1390:in `loop'
from org/jruby/RubyKernel.java:1173:in `catch'
from org/jruby/RubyKernel.java:1173:in `catch'
from ~/.rvm/rubies/jruby-1.7.0/bin/irb:13:in `(root)'
Here is more stuff to meditate on:
irb(main):129:0> Object
=> Object
irb(main):130:0> Object.class
=> Class
irb(main):131:0> Object.new.class
=> Object
irb(main):132:0> Object.superclass
=> BasicObject
irb(main):133:0> Object.superclass.class
=> Class
irb(main):134:0> Object.superclass.new.class
NoMethodError: undefined method `class' for #<BasicObject:0x1c944d4a>
from (irb):134:in `evaluate'
from org/jruby/RubyKernel.java:1065:in `eval'
from org/jruby/RubyKernel.java:1390:in `loop'
from org/jruby/RubyKernel.java:1173:in `catch'
from org/jruby/RubyKernel.java:1173:in `catch'
from ~/.rvm/rubies/jruby-1.7.0/bin/irb:13:in `(root)'
Have fun!
As you can see, it is a derived class.
#ruby 1.8.7
Object.superclass
# => nil
nil.kind_of? Object
# => true
#ruby 2.0.0
Object.superclass
# => BasicObject
BasicObject.kind_of? Object
# => true

Method called on an object when displayed on the console in Ruby

I am willing to call a method when trying to display an object, but I don't find which method is used, for example:
[41] pry(main)> u
=> {"id"=>3}
[42] pry(main)> u.inspect
=> "#<User id=3>"
[43] pry(main)> u.to_s
=> "#<User id=3>"
[44] pry(main)> puts c
#<User id=3>
=> nil
I would like to know which method is called for the first case.
User is not an ActiveRecord class, it inherits from Hashie.
Thanks for your help!
It's probably the rails method attributes - though it is a feature of Pry, not of the standard rails console which would give you ruby-1.9.2-p290 :047 > u
=> #<u:0x8a2f6cc #id=3>

How do I use this mixin to alter the DateTime object?

I need to alter the DateTime object. The resource I've found states that this is what I need to do, but I'm not sure exactly what to do with this code. Where do I put it? Thanks for reading.
module DateTimePatch
def getlocal
"works!"
end
end
DateTime.send(:include, DateTimePatch)
EDIT:
So this is what I have
/lib/date_time.rb
class DateTime
def getlocal
"it works"
end
end
Console
ruby-1.9.2-p0 > Time.now.getlocal
=> 2010-11-09 23:40:36 +1000
ruby-1.9.2-p0 > DateTime.now
=> Tue, 09 Nov 2010 23:40:57 +1000
ruby-1.9.2-p0 > DateTime.now.getlocal
NoMethodError: undefined method `getlocal' for Tue, 09 Nov 2010 23:41:02 +1000:DateTime
EDIT2:
Ok so now I'm doing:
ruby-1.9.2-p0 > require './lib/date_time.rb'
=> true
ruby-1.9.2-p0 > DateTime.now.getlocal
NoMethodError: undefined method `now' for DateTime:Class
from (irb):2
from /Users/benhartney/.rvm/rubies/ruby-1.9.2-p0/bin/irb:17:in `<main>'
ruby-1.9.2-p0 > DateTime.now
NoMethodError: undefined method `now' for DateTime:Class
from (irb):3
from /Users/benhartney/.rvm/rubies/ruby-1.9.2-p0/bin/irb:17:in `<main>'
I tried adding a temporary now method to the mixin to see if the error still occurred and it did. DateTime.now worked fine before I loaded the mixin, not sure why this is happening?
So, you want to add a method to the DateTime class ? Try:
class DateTime
def get_local
"works!"
end
end
Probably you forgot to require your file.
irb(main):002:0> DateTime.now.getlocal
NoMethodError: undefined method `getlocal' for #
from (irb):2
from d:/Ruby/bin/irb.bat:20:in `'
irb(main):003:0> require './lib/date_time.rb'
=> true
irb(main):004:0> DateTime.now.getlocal
=> "it works"
UPD: and require 'date' in order to use ruby's DateTime class.

Resources