4 ms·
A good way to explore is getting an interactive session with something like pry and exploring what methods and attributes are available that way. It sounds clun
by ajmurmann 3y ago
A good way to explore is getting an interactive session with something like pry and exploring what methods and attributes are available that way. It sounds clunky, but it's quite effective as you frequently get to play through the entire implementation once and it pairs extremely well with TDD.
- cortesoft 3y agoI love ruby, and find it great to use pry and irb to explore and figure stuff out. However, many times ruby libraries will use dynamic programming and method_missing to define methods on the fly… this makes it really hard to figure out what methods are actually available. For that reason, I try to never use method missing to define core functionality in ruby, and hate when other gems do it.
- jaggederest 3y agoThe responsible thing when you use `method_missing` is to define `respond_to` to indicate whether an object responds to a particular method. This alleviates the "is a method available" issue because you can just ask the object "Do you respond to :method_I_want_to_call?", and it will correctly inform you it does or does not. This kind of discoverability is one of the things I miss when I'm working in Javascript/TS as I have been recently - sure you can check the .method_name property to see if it's a function and then execute it but it doesn't feel as nice. E.g. def method_missing(name, \*args) if name =~ /^has_/ has(name, *args) end super end def respond_to(name) if name =~ /^has_/ return true end super end
- cortesoft 3y agoSure, but my favorite thing to do in irb is <object I want to inspect>.methods.sort - Object.methods This won’t work even with respond_to being defined
- danielheath 3y agoI also love this technique . I prefer to subtract {}.methods though - shorter to type and removes more cruft.
- ajmurmann 3y agoHah, I am even twice as lazy as you and do '- 1.methods'. Works for 99.9% of cases.
- drusepth 3y agoPry is amazing for understanding code. IMO the most useful method is absolutely `some_object.methods`, but you can also improve the output a ton by always doing: some_object.methods - {}.methods # or some other "parent" class/object This does set subtraction to remove all the "core" object methods from your some_object methods, so you can see just what's unique about that object. For example, comparing one of my services with a parent Service class it inherits from: irb(main):017:0> PaypalService.methods - Service.methods => [:capture_invoice_funds, :months_price, :client, :create_prepay_invoice, :order_info] instead of listing out the 187 methods that PaypalService has that it inherits from Service and every other parent object up the line, which is usually a surprisingly long ancestor list in any Ruby on Rails class (even POROs!). There are a TON of useful methods like this that I'd recommend getting familiar with, which makes exploration and discovery of code incredibly fast and efficient. You can find them all with the same trick: by using `methods` on any method. :) irb(main):043:0> PaypalService.method(:months_price).methods - {}.methods => [:<<, :>>, :arity, :curry, :source_location, :call, :parameters, :original_name, :owner, :receiver, :super_method, :name, :unbind, :comment, :source] Some of the more relevant ones: irb(main):037:0> PaypalService.method(:months_price).arity => 1 irb(main):038:0> puts PaypalService.method(:months_price).parameters req n_months irb(main):039:0> puts PaypalService.method(:months_price).source def self.months_price(n_months) case n_months when 1 9.00 when 3 24.00 when 6 48.00 when 12 84.00 else raise "Invalid month prepay: #{n_months}" end end
- subarctic 3y agoI second this, when I was in Ruby land I used to regularly drop a binding.pry (later binding.irb) in the middle of some code i wanted to understand, and call things like `method` to see where an unrecognized method came from.