lib/sfkb/rest.rb in sfkb-0.1.2 vs lib/sfkb/rest.rb in sfkb-0.1.3

- old
+ new

@@ -1,11 +1,14 @@ module SFKB # Some REST helpers module REST # Used to interpolate variables into REST endpoint URIs - @@placeholder = /[<{](.+?)[>}]/ + @@placeholder = /[<{](.+?)[>}]/.freeze + # Used to identify URLs; %s should be the api_version + @@url_pattern = '/services/data/v%s'.freeze + # { a: :b }.inject({}, &@@stringify) #=> { 'a' => :b } @@stringify = lambda do |collector, kv| collector.tap { |h| h[kv[0].to_s] = kv[1] } end @@ -25,27 +28,47 @@ path = path.gsub(@@placeholder) { params.delete($1, &@@required) } params = params.inject('', &@@parameterize) [path, params].reject(&:nil?).reject(&:empty?).join('?') end + # The starting URL + def services_url + @@url_pattern % options[:api_version] + end + # The REST API starts here def index - endpoint("/services/data/v#{options[:api_version]}") do |k, v| - endpoint(v) { |k, v| endpoint(v) } - end + endpoint(get(services_url).body) end - - # Fetches the object at url, and extends it with methods - def endpoint(url) - get(url).body.tap do |o| - o.each do |k, v| - o.define_singleton_method(k) do - ivar = :"@#{k}" - return instance_variable_get(ivar) if instance_variable_defined?(ivar) - instance_variable_set(ivar, block_given? ? yield(k, v) : v) - end - end - end + + # endpoint takes a map, and for eack key/value pair, adds a singleton + # method to the map which will fetch that resource (if it looks like a + # URL). + def endpoint(map) + map.each { |k, v| apply_endpoint(map, k, v) } + map + end + + # applies an endpoint to obj, named k, which fetches v and makes it an + # endpoint if it looks like a URL + def apply_endpoint(obj, k, v) + α = -> { endpoint(get(v).body) } + β = -> { v } + λ = url?(v) ? -> { α.call } : -> { β.call } + obj.define_singleton_method(k, &λ) if url?(v) + obj + end + + # Identifies a valid URL for this REST instance + def url?(string) + return false unless string.to_s =~ url_pattern + return false if string.to_s =~ @@placeholder + true + end + + # Identifies a valid URL for this REST instance + def url_pattern + %r{#{services_url}} end extend self end end