module LazyResource module UrlGeneration extend ActiveSupport::Concern def element_path(options = nil) self.class.element_path(self.instance_variable_get("@#{self.class.primary_key_name}"), options) end def element_url(options = nil) url = self.class.site.to_s.gsub(/\/$/, '') url << self.element_path(options) end def new_element_path self.class.new_element_path end def collection_path(options = nil) self.class.collection_path(options) end def collection_url(options = nil) url = self.class.site.to_s.gsub(/\/$/, '') url << self.collection_path(options) end def split_options(options = {}) self.class.split_options(options) end module ClassMethods # Gets the \prefix for a resource's nested URL (e.g., prefix/collectionname/1) def prefix(options={}) path = '/' options = options.to_a.uniq path = options.inject(path) do |uri, option| key, value = option[0].to_s, option[1] uri << ActiveSupport::Inflector.pluralize(key.gsub("_id", '')) uri << "/#{value}/" end end # Gets the element path for the given ID in +id+. If the +query_options+ parameter is omitted, Rails # will split from the \prefix options. # # ==== Options # +prefix_options+ - A \hash to add a \prefix to the request for nested URLs (e.g., :account_id => 19 # would yield a URL like /accounts/19/purchases.json). # # +query_options+ - A \hash to add items to the query string for the request. def element_path(id, prefix_options = {}, query_options = nil, from = nil) prefix_options, query_options = split_options(prefix_options) if query_options.nil? from = self.from if from.nil? && respond_to?(:from) "#{prefix(prefix_options)}#{from || collection_name}/#{URI.escape id.to_s}#{query_string(query_options)}" end # Gets the new element path for REST resources. # # ==== Options # * +prefix_options+ - A hash to add a prefix to the request for nested URLs (e.g., :account_id => 19 # would yield a URL like /accounts/19/purchases/new.json). def new_element_path(prefix_options = {}, from = nil) from = self.from if from.nil? && respond_to?(:from) "#{prefix(prefix_options)}#{from || collection_name}/new" end # Gets the collection path for the REST resources. If the +query_options+ parameter is omitted, Rails # will split from the +prefix_options+. # # ==== Options # * +prefix_options+ - A hash to add a prefix to the request for nested URLs (e.g., :account_id => 19 # would yield a URL like /accounts/19/purchases.json). # * +query_options+ - A hash to add items to the query string for the request. def collection_path(prefix_options = {}, query_options = nil, from = nil, include_query = true) prefix_options, query_options = split_options(prefix_options) if query_options.nil? from = self.from if from.nil? && respond_to?(:from) path = "#{prefix(prefix_options)}#{from || collection_name}" path += "#{query_string(query_options)}" if include_query path end # Builds the query string for the request. def query_string(options) "?#{options.to_query}" unless options.nil? || options.empty? end # split an option hash into two hashes, one containing the prefix options, # and the other containing the leftovers. def split_options(options = {}) prefix_options, query_options = {}, {} (options || {}).each do |key, value| next if key.blank? (key =~ /\w*_id$/ ? prefix_options : query_options)[key.to_sym] = value end [prefix_options, query_options] end end end end