lib/acfs/model/locatable.rb in acfs-0.30.0.1.b260 vs lib/acfs/model/locatable.rb in acfs-0.30.0.1.b261

- old
+ new

@@ -12,23 +12,88 @@ module Locatable extend ActiveSupport::Concern module ClassMethods - # Return URL for this class of resource. Given suffix will be appended. + # @overload url(suffix) + # @deprecated + # Return URL for this class of resource. Given suffix will be appended. # + # @example + # User.url # => "http://users.srv.org/users" + # User.url(5) # => "http://users.srv.org/users/5" + # + # @param [ String ] suffix Suffix to append to URL. + # @return [ String ] Generated URL. + # + # @overload url(opts = {}) + # Return URL for this class of resources. Given options will be used to replace + # URL path arguments and to determine the operation action. + # + # @example + # User.url(id: 5, action: :read) # => "http://users.srv.org/users/5" + # User.url(action: :list) # => "http://users.srv.org/users" + # + # @param opts [Hash] Options. + # @option opts [Symbol] :action Operation action, usually `:list`, `:create`, `:read`, + # `:update` or`:delete`. + # @return [ String ] Generated URL. + # + def url(suffix = nil, opts = {}) + if Hash === suffix + opts, suffix = suffix, nil + end + + opts[:action] = :list if suffix + + url = location(opts).build(opts).str + url += "/#{suffix}" if suffix.to_s.present? + url + end + + # Return a location object able to build the URL for this resource and + # given action. + # # @example - # User.url # => "http://users.srv.org/users" - # User.url(5) # => "http://users.srv.org/users/5" + # class Identity < ::Acfs::Resource + # service MyService, path: 'users/:user_id/identities' + # end # - # @param [ String ] suffix Suffix to append to URL. - # @return [ String ] Generated URL. - # @see Acfs::Service#url_for Delegates to Service#url_for with `suffix` option. + # location = Identity.location(action: :read) + # location.arguments + # => [:user_id, :id] # - def url(suffix = nil) - service.url_for(self, suffix: suffix) + # location.raw_url + # => 'http://service/users/:user_id/identities/:id' + # + # location = Identity.location(action: :list) + # location.arguments + # => [:user_id] + # + # location.build(user_id: 42) + # => 'http://service/users/42/identities' + # + # @param opts [Hash] Options. + # @option opts [Symbol] :action Operation action, usually `:list`, `:create`, `:read`, + # `:update` or`:delete`. + # + # @return [Location] Location object. + # + def location(opts = {}) + service.location(self, opts) end + + # @api private + def path_defaults + { + list: '/:path', + create: '/:path', + read: '/:path/:id', + update: '/:path/:id', + delete: '/:path/:id' + } + end end # Return URL for this resource. Resource if will be appended # as suffix if present. # @@ -40,11 +105,24 @@ # user.url # => "http://users.srv.org/users/5" # # @return [ String ] Generated URL. # @see ClassMethods#url # - def url - return nil if id.nil? - self.class.service.url_for self, suffix: read_attribute(:id) + def url(opts = {}) + return nil if need_primary_key? && !has_primary_key? + + self.class.service.location(self.class, opts.reverse_merge(action: :read)).build(attributes).str + end + + # @api private + # Return true if resource needs a primary key (id) for singular actions. + def need_primary_key? + true + end + + # @api private + # Return true if resource has a primary key (id) set. + def has_primary_key? + respond_to?(:id) && !id.nil? end end end