Why Gemfury? Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Debian packages RPM packages NuGet packages

Repository URL to install this package:

Details    
getfitter / lib / get_fitter / base.rb
Size: Mime:
require 'roar/json'
require 'roar/client'
require 'roar/coercion'
require 'get_fitter/overrides/ostruct'
require 'get_fitter/error'

module GetFitter
  #
  # Base Class for fetching all the data from the remote api.
  # All Classes should inherit from this class.
  #
  # Abstract base class for the different resources.
  # Provides some helper methods for the resources.
  #
  # @abstract
  class Base < OpenStruct
    include Roar::JSON
    include Roar::Hypermedia
    include Roar::Client
    include Roar::Coercion

    #
    # Class level methods for resources to fetch data from api
    # @abstract
    class << self
      # Fetch an object by id or URL
      # @param [String] id String the resource id
      # @return [Booking, Event, Organisation, User, Venue]
      # @example Fetch event by id
      #   GetFitter::Event.fetch(1)
      #
      # @example Fetch event by url
      #   GetFitter::Event.fetch('http://api.vagrant.dev:3000/events/1')
      # @api public
      def fetch(id)
        object = new(url: link(id))
        GetFitter::Request.new(object.request_attributes).fetch
      end

      #
      # Fetch all resource data page by page
      # @return [Bookings, Events, Organisations, Users, Venues]
      # @example Fetch Events page by page
      #   GetFitter::Event.fetch_all.each do |page|
      #     puts page.items.size
      #   end
      # @api public
      def fetch_all
        klass_name =
          GetFitter.const_get(name.split('::').last).const_get('RESOURCE_NAME')
        object =
          GetFitter.const_get("#{klass_name.capitalize}").new(
            url: "#{GetFitter::API.configuration.url[0]}/#{klass_name}")
        GetFitter::Request.new(
          resource: object, uri: object.url, params: {}).fetch
      end

      #
      # Fetch all objects matching the query parameters
      # @param [Hash] params Query parameters
      # @return [Request]
      # @api public
      def where(params)
        klass_name =
          GetFitter.const_get(name.split('::').last).const_get('RESOURCE_NAME')
        object =
          GetFitter.const_get("#{klass_name.capitalize}").new(
            url: "#{GetFitter::API.configuration.url[0]}/#{klass_name}")
        GetFitter::Request.new(
          resource: object, uri: object.url, params: params)
      end

      def save_existing(id, params)
        object = new(params)
        object.id = id
        object.save
      end

      protected

      #
      # Generate a resource link based on the passed params
      # @param [String] id the resource id
      # @return [String] resource link
      # @api private
      def link(id)
        "#{GetFitter::API.configuration.url[0]}/"\
          "#{const_get('RESOURCE_NAME')}/#{id}/"
      end
    end

    # The hypermedia URL of this resource
    # @return [String]
    # @example
    #   event.url #=>
    #     'http://example.com/events/3af9912d-1584-4e5d-bbed-dd1697acd298/'
    # @api public
    property :url

    #
    # Fetch a resource if the ID is set
    # @return [Booking, Event, Organisation, User, Venue]
    # @example Fetch event by id
    #   GetFitter::Event.new(id: '3af9912d-1584-4e5d-bbed-dd1697acd298').fetch
    # @api public
    def fetch
      GetFitter::Request.new(request_attributes).fetch
    end

    def save
      id ? update : create
    end


    #
    # Generate the Request initialize params
    # @param [Hash] opts the options to create a Request with.
    # @options opts [Booking, Event, Organisation, User, Venue] :resource
    # @option opts [String] :uri resource uri
    # @option opts [Hash] :params other params
    # @return [Hash]
    # @api private
    def request_attributes(opts = {})
      { resource: self, uri: link, params: { token: auth_token } }.merge(opts)
    end

    protected

    def create
      klass_name = GetFitter.const_get(self.class.name.split('::').last)
                   .const_get('RESOURCE_NAME')
      post(uri: "#{GetFitter::API.configuration.url[0]}/#{klass_name}",
           as: 'application/json') do |req|
        req.add_field('Authorization', 'Bearer ' + auth_token)
      end
    end

    def update
      klass_name = GetFitter.const_get(self.class.name.split('::').last)
                   .const_get('RESOURCE_NAME')

      put(uri: "#{GetFitter::API.configuration.url[0]}/#{klass_name}/#{id}",
          as: 'application/json') do |req|
        req.add_field('Authorization', 'Bearer ' + auth_token)
      end
    end

    #
    # Generate a resource link from the id
    # @return [String] resource link
    # @raise [GetFitter::Error:: ArgumentError] if no id
    # @api private
    def link
      if url
        url
      elsif id
        "#{GetFitter::API.configuration.url[0]}/"\
          "#{self.class::RESOURCE_NAME}/#{id}/"
      else
        fail(GetFitter::Error::ArgumentError.new('Please use id to fetch'\
          ' resource', nil))
      end
    end

    def auth_token
      GetFitter::API.configuration.token
    end
  end
end