class Lokalise::Resources::Base

Attributes

branch[R]
client[R]
path[R]
project_id[R]
raw_data[R]
team_id[R]
user_id[R]

Public Class Methods

create(client, path, params) click to toggle source

Creates one or multiple records

# File lib/ruby-lokalise-api/resources/base.rb, line 71
def create(client, path, params)
  response = post path, client, prepare_params(params)
  object_from response, params
end
destroy(client, path, params = {}) click to toggle source

Destroys records by given ids

# File lib/ruby-lokalise-api/resources/base.rb, line 83
def destroy(client, path, params = {})
  delete(path, client, prepare_params(params))['content']
end
find(client, path, params = {}) click to toggle source

Fetches a single record

# File lib/ruby-lokalise-api/resources/base.rb, line 66
def find(client, path, params = {})
  new get(path, client, prepare_params(params))
end
inherited(subclass) click to toggle source

Dynamically adds attribute readers for each inherited class. Attributes are defined in the `data/attributes.json` file. Also sets the `ATTRIBUTES` constant to assign values to each attribute later when the response arrives from the API

Calls superclass method
# File lib/ruby-lokalise-api/resources/base.rb, line 33
def inherited(subclass)
  klass_attributes = attributes_for subclass
  subclass.class_exec do
    const_set :ATTRIBUTES, klass_attributes
    attr_reader(*klass_attributes)
  end
  super
end
new(response, endpoint_generator = nil) click to toggle source

Initializes a new resource based on the response. `endpoint_generator` is used in cases when a new instance is generated from a different resource. For example, restoring from a snapshot creates a totally different project which should have a new path.

@param response [Hash] @param endpoint_generator [Proc] Generate proper paths for certain resources @return [Lokalise::Resources::Base]

# File lib/ruby-lokalise-api/resources/base.rb, line 21
def initialize(response, endpoint_generator = nil)
  populate_attributes_for response['content']
  extract_common_attributes_for response['content']
  @client = response['client']
  @path = infer_path_from response, endpoint_generator
end
supports(*methods) click to toggle source

Defines CRUD instance methods. In the simplest case it delegates work to the class method. In more complex case it is possible to specify sub-path and the class method name to call. Usage: `supports :update, :destroy, [:complex_method, '/sub/path', :update]`

# File lib/ruby-lokalise-api/resources/base.rb, line 46
def supports(*methods)
  methods.each do |m_data|
    # `method_name` - the method that the resource should support
    # `sub_path` - a string that has to be appended to a base path
    # `c_method` - method name to delegate the work to
    method_name, sub_path, c_method =
      m_data.is_a?(Array) ? m_data : [m_data, '', m_data]

    define_method method_name do |params = {}|
      path = instance_variable_get(:@path)
      # If there's a sub_path which is a string,
      # preserve the initial path to allow further chaining
      params = params.merge(_initial_path: path) if sub_path
      self.class.send c_method, instance_variable_get(:@client),
                      path + sub_path, params
    end
  end
end
update(client, path, params) click to toggle source

Updates one or multiple records

# File lib/ruby-lokalise-api/resources/base.rb, line 77
def update(client, path, params)
  response = put path, client, prepare_params(params)
  object_from response, params
end

Private Class Methods

object_from(response, params) click to toggle source

Instantiates a new resource or collection based on the given response

# File lib/ruby-lokalise-api/resources/base.rb, line 96
def object_from(response, params)
  model_class = name.base_class_name
  data_key_plural = data_key_for model_class: model_class, plural: true
  # Preserve the initial path to allow chaining
  response['path'] = params.delete(:_initial_path) if params.key?(:_initial_path)

  if response['content'].key?(data_key_plural)
    produce_collection model_class, response, params
  else
    produce_resource model_class, response
  end
end
prepare_params(params) click to toggle source

Filters out internal attributes that should not be sent to Lokalise

# File lib/ruby-lokalise-api/resources/base.rb, line 90
def prepare_params(params)
  filter_attrs = %i[_initial_path]
  params.reject { |key, _v| filter_attrs.include?(key) }
end
produce_collection(model_class, response, params) click to toggle source
# File lib/ruby-lokalise-api/resources/base.rb, line 119
def produce_collection(model_class, response, params)
  Module.const_get("Lokalise::Collections::#{model_class}").new(response, params)
end
produce_resource(model_class, response) click to toggle source
# File lib/ruby-lokalise-api/resources/base.rb, line 109
def produce_resource(model_class, response)
  data_key_singular = data_key_for model_class: model_class
  if response['content'].key? data_key_singular
    data = response['content'].delete data_key_singular
    response['content'].merge! data
  end

  new response
end

Public Instance Methods

extract_common_attributes_for(content) click to toggle source

Extracts all common attributes that resources have. Some of them may be absent in certain cases. rubocop:disable Naming/MemoizedInstanceVariableName

# File lib/ruby-lokalise-api/resources/base.rb, line 183
def extract_common_attributes_for(content)
  @raw_data = content
  @project_id ||= content['project_id']
  @user_id ||= content['user_id']
  @team_id ||= content['team_id']
  @branch ||= content['branch']
end
id_from(response, id_key, data_key) click to toggle source
# File lib/ruby-lokalise-api/resources/base.rb, line 154
def id_from(response, id_key, data_key)
  # Content may be `{"project_id": '123', ...}` or {"snapshot": {"snapshot_id": '123', ...}}
  # Sometimes there is an `id_key` but it has a value of `null`
  # (for example when we do not place the actual order but only check its price).
  # Therefore we must explicitly check if the key is present
  return response['content'][id_key] if response['content'].key?(id_key)

  response['content'][data_key][id_key]
end
infer_path_from(response, endpoint_generator = nil) click to toggle source

Generates path for the individual resource based on the path for the collection

# File lib/ruby-lokalise-api/resources/base.rb, line 125
def infer_path_from(response, endpoint_generator = nil)
  id_key = id_key_for self.class.name.base_class_name
  data_key = data_key_for model_class: self.class.name.base_class_name

  path_with_id response, id_key, data_key, endpoint_generator
end
path_with_id(response, id_key, data_key, endpoint_generator = nil) click to toggle source
# File lib/ruby-lokalise-api/resources/base.rb, line 132
def path_with_id(response, id_key, data_key, endpoint_generator = nil)
  # Some resources do not have ids at all
  return nil unless response['content'].key?(id_key) || response['content'].key?(data_key)

  # ID of the resource
  id = id_from response, id_key, data_key

  # If `endpoint_generator` is present, generate a new path
  # based on the fetched id
  if endpoint_generator
    path = endpoint_generator.call project_id, id
    return path.remove_trailing_slash
  end

  path = response['path'] || response['base_path']
  # If path already has id - just return it
  return path if path.match?(/#{id}\z/)

  # Otherwise this looks like a collection path, so append the resource id to it
  path.remove_trailing_slash + "/#{id}"
end
populate_attributes_for(content) click to toggle source

Store all resources attributes under the corresponding instance variables. `ATTRIBUTES` is defined inside resource-specific classes

# File lib/ruby-lokalise-api/resources/base.rb, line 166
def populate_attributes_for(content)
  data_key = data_key_for model_class: self.class.name.base_class_name

  self.class.const_get(:ATTRIBUTES).each do |attr|
    value = if content.key?(data_key) && content[data_key].is_a?(Hash)
              content[data_key][attr]
            else
              content[attr]
            end

    instance_variable_set "@#{attr}", value
  end
end