nickcharlton/atlas-ruby

View on GitHub
lib/atlas/box.rb

Summary

Maintainability
A
0 mins
Test Coverage
module Atlas
  # Representation and handling of Box objects.
  #
  # @attr_accessor [String] name The name of the box
  # @attr_accessor [String] username The owner of the box
  # @attr_accessor [String] short_description A short version of the
  #   description.
  # @attr_accessor [String] description Markdown text used to describe it.
  # @attr_accessor [Boolean] is_private A boolean if the box is private.
  # @attr_accessor [Version] current_version the current version of this box.
  # @attr_accessor [Array] versions versions associated with this box.
  class Box < Resource
    attr_accessor :name, :username, :short_description, :description,
                  :private, :current_version, :versions
    date_accessor :created_at, :updated_at

    requires :username, :name, :short_description, :description

    # Find a box by it's tag.
    #
    # @param [String] tag the tag of the box.
    #
    # @return [Box] a representation of the box.
    def self.find(tag)
      url_builder = UrlBuilder.new tag
      response = Atlas.client.get(url_builder.box_url)

      new(tag, response)
    end

    # Create a new Box.
    #
    # @param [Hash] attr attributes to create the box with
    # @param attr [String] :name The name of the box, used to identify it.
    # @option attr [String] :username The username to assign the box to.
    # @option attr [String] :short_description The short description is used on
    #   small box previews.
    # @option attr [String] :description Markdown text used as a full-length and
    #   in-depth description of the box.
    # @option attr [Boolean] :is_private A boolean if the box should be private
    #   or not.
    #
    # @return [Box] a newly created box.
    def self.create(attr = {})
      tag = "#{attr.fetch(:username, '')}/#{attr[:name]}"
      box = new(tag, attr)
      box.save
      box
    end

    # Initialize a box from a tag and object hash.
    #
    # @param [String] tag the tag which represents the origin of the box.
    # @param [Hash] hash the attributes for the box
    # @param hash [String] :name The name of the box, used to identify it.
    # @option hash [String] :username The username to assign the box to.
    # @option hash [String] :short_description The short description is used on
    #   small box previews.
    # @option hash [String] :description Markdown text used as a full-length and
    #   in-depth description of the box.
    # @option hash [Boolean] :is_private A boolean if the box should be private
    #   or not.
    #
    # @return [Box] a new box object.
    def initialize(tag, hash = {})
      hash.replace_key!("private", "is_private")
      hash.replace_key!("description_markdown", "description")

      super(tag, hash)
    end

    # Assign the current version.
    #
    # @note This is intended to be used to assign the response object, not
    #   calling directly. Calling `release` will set the `current_version`.
    #
    # @param [Hash] attr a response hash of a `BoxVersion`.
    def current_version=(attr)
      if attr.is_a? Hash
        @current_version = BoxVersion.new("#{tag}/#{attr['version']}", attr)
      else
        @current_version = attr
      end
    end

    # Assign the versions of this box.
    #
    # @note This is intended to be used to assign the response object, not
    #   calling directly. You could do something unexpected by replacing this.
    #
    # @param [Array] attr an array of responses hashes.
    def versions=(attr)
      @versions = attr.collect do |v|
        BoxVersion.new("#{tag}/#{v['version']}", v)
      end
    end

    # Create a version for this box.
    #
    # @param [Hash] attr attributes to set on the version.
    #
    # @return [BoxVersion] a BoxVersion representing the new version.
    def create_version(attr)
      BoxVersion.create(tag, attr)
    end

    # Save the box.
    #
    # @return [Hash] Atlas response object.
    def save
      validate!

      body = { box: to_hash }

      # versions are saved seperately
      body[:box].delete(:versions)

      # update or create the box
      begin
        response = Atlas.client.put(url_builder.box_url, body: body)
      rescue Atlas::Errors::NotFoundError
        body[:box].replace_key!(:private, :is_private)

        response = Atlas.client.post("/boxes", body: body)
      end

      # trigger the same on versions
      versions.each(&:save) if versions

      update_with_response(response, [:versions])
    end

    # Delete the box.
    #
    # @return [Hash] response body from Atlas.
    def delete
      Atlas.client.delete(url_builder.box_url)
    end
  end
end