Class: Sinclair

Inherits:
Object
  • Object
show all
Includes:
OptionsParser
Defined in:
lib/sinclair.rb,
lib/sinclair/config.rb,
lib/sinclair/options.rb,
lib/sinclair/version.rb,
lib/sinclair/matchers.rb,
lib/sinclair/exception.rb,
lib/sinclair/input_hash.rb,
lib/sinclair/config_class.rb,
lib/sinclair/configurable.rb,
lib/sinclair/env_settable.rb,
lib/sinclair/config_builder.rb,
lib/sinclair/config_factory.rb,
lib/sinclair/method_builder.rb,
lib/sinclair/options_parser.rb,
lib/sinclair/options/builder.rb,
lib/sinclair/method_definition.rb,
lib/sinclair/method_definitions.rb,
lib/sinclair/matchers/add_method.rb,
lib/sinclair/method_builder/base.rb,
lib/sinclair/env_settable/builder.rb,
lib/sinclair/config/methods_builder.rb,
lib/sinclair/matchers/add_method_to.rb,
lib/sinclair/matchers/add_class_method.rb,
lib/sinclair/matchers/add_class_method_to.rb,
lib/sinclair/matchers/add_instance_method.rb,
lib/sinclair/method_definition/block_helper.rb,
lib/sinclair/matchers/add_instance_method_to.rb,
lib/sinclair/method_definition/block_definition.rb,
lib/sinclair/method_builder/block_method_builder.rb,
lib/sinclair/method_definition/string_definition.rb,
lib/sinclair/method_builder/string_method_builder.rb

Overview

Builder that add instance methods to a class

Examples:

Stand alone usage

class MyModel
end

buider = Sinclair.new(MyModel)

value = 10
builder.add_method(:default_value) { value }
builder.add_method(:value, '@value || default_value')
builder.add_method(:value=) { |val| @value = val }
builder.build

instance = MyModel.new
instance.value # returns 10
instance.value = 20
instance.value # returns 20

Using cache

module DefaultValueable
  def default_reader(*methods, value:, accept_nil: false)
    DefaultValueBuilder.new(
      self, value: value, accept_nil: accept_nil
    ).add_default_values(*methods)
  end
end

class DefaultValueBuilder < Sinclair
  def add_default_values(*methods)
    default_value = value

    methods.each do |method|
      add_method(method, cached: cache_type) { default_value }
    end

    build
  end

  private

  delegate :accept_nil, :value, to: :options_object

  def cache_type
    accept_nil ? :full : :simple
  end
end

class Server
  extend DefaultValueable

  attr_writer :host, :port

  default_reader :host, value: 'server.com', accept_nil: false
  default_reader :port, value: 80,           accept_nil: true

  def url
    return "http://#{host}" unless port

    "http://#{host}:#{port}"
  end
end
server = Server.new

server.url # returns 'http://server.com:80'

server.host = 'interstella.com'
server.port = 5555
server.url # returns 'http://interstella.com:5555'

server.host = nil
server.port = nil
server.url # return 'http://server.com'

Author:

  • darthjee

Defined Under Namespace

Modules: ConfigClass, Configurable, EnvSettable, Matchers, OptionsParser Classes: Config, ConfigBuilder, ConfigFactory, Exception, InputHash, MethodBuilder, MethodDefinition, MethodDefinitions, Options

Constant Summary collapse

VERSION =
'1.6.4'

Instance Attribute Summary

Attributes included from OptionsParser

#options

Instance Method Summary collapse

Methods included from OptionsParser

#options_object

Constructor Details

#initialize(klass, options = {}) ⇒ Sinclair

Returns a new instance of Sinclair

Examples:

Preparing builder


class Purchase
  def initialize(value, quantity)
    @value = value
    @quantity = quantity
  end
end

builder = Sinclair.new(Purchase)

Passing building options (Used on subclasses)


class MyBuilder < Sinclair
  def add_methods
    if options_object.rescue_error
      add_safe_method
    else
      add_method(:symbolize) { @variable.to_sym }
    end
  end

  def add_safe_method
    add_method(:symbolize) do
      begin
        @variable.to_sym
      rescue StandardError
        :default
      end
    end
  end
end

class MyModel
end

builder = MyBuilder.new(MyModel, rescue_error: true)

builder.add_method
builder.build

instance = MyModel.new

instance.symbolize # returns :default

Parameters:

  • klass (Class)

    Class that will receive the methods

  • options (Hash) (defaults to: {})

    open hash options to be used by builders inheriting from Sinclair through the Sinclair::OptionsParser concern



151
152
153
154
# File 'lib/sinclair.rb', line 151

def initialize(klass, options = {})
  @klass = klass
  @options = options
end

Instance Method Details

#add_class_method(name, code, **options) ⇒ Array<MethodDefinition> #add_class_method(name, **options, &block) ⇒ Array<MethodDefinition>

Add a method to the method list to be created on klass

Examples:

class EnvFetcher
end

builder = Sinclair.new(EnvFetcher)

builder.add_class_method(:hostname, 'ENV["HOSTNAME"]')
builder.build

ENV['HOSTNAME'] = 'myhost'

env_fetcher.hostname # returns 'myhost'
class EnvFetcher
end

builder = Sinclair.new(EnvFetcher)

builder.add_class_method(:timeout) { ENV['TIMEOUT'] }
builder.build

ENV['TIMEOUT'] = '300'

env_fetcher.timeout # returns '300'

Overloads:

  • #add_class_method(name, code, **options) ⇒ Array<MethodDefinition>

    Parameters:

    • code (String)

      code to be evaluated when the method is ran

  • #add_class_method(name, **options, &block) ⇒ Array<MethodDefinition>

    Parameters:

    • block (Proc)

      block to be ran as method

Parameters:

  • name (String, Symbol)

    name of the method to be added

  • options (Hash)

    Options of construction

Options Hash (**options):

  • cached (Boolean)

    Flag telling to create a method with cache

Returns:



271
272
273
274
275
# File 'lib/sinclair.rb', line 271

def add_class_method(name, code = nil, **options, &block)
  class_definitions.add(
    name, code, **options, &block
  )
end

#add_method(name, code, **options) ⇒ Array<MethodDefinition> #add_method(name, **options, &block) ⇒ Array<MethodDefinition>

Add a method to the method list to be created on klass instances

Examples:

Using string code

class Person
  attr_reader :first_name, :last_name

  def initialize(first_name, last_name)
    @first_name = first_name
    @last_name = last_name
  end
end

builder = Sinclair.new(Person)
builder.add_method(:full_name, '[first_name, last_name].join(" ")')
builder.build

Person.new('john', 'wick').full_name # returns 'john wick'

Using block

class Person
  attr_reader :first_name, :last_name

  def initialize(first_name, last_name)
    @first_name = first_name
    @last_name = last_name
  end
end

builder = Sinclair.new(Person)
builder.add_method(:full_name, '[first_name, last_name].join(" ")')
builder.add_method(:bond_name) { "#{last_name}, #{full_name}" }
builder.build

Person.new('john', 'wick').bond_name # returns 'wick, john wick'

Overloads:

  • #add_method(name, code, **options) ⇒ Array<MethodDefinition>

    Parameters:

    • code (String)

      code to be evaluated when the method is ran

  • #add_method(name, **options, &block) ⇒ Array<MethodDefinition>

    Parameters:

    • block (Proc)

      block to be ran as method

Parameters:

  • name (String, Symbol)

    name of the method to be added

  • options (Hash)

    Options of construction

Options Hash (**options):

  • cached (Boolean)

    Flag telling to create a method with cache

Returns:



225
226
227
228
229
# File 'lib/sinclair.rb', line 225

def add_method(name, code = nil, **options, &block)
  definitions.add(
    name, code, **options, &block
  )
end

#buildArray<MethodDefinition>

builds all the methods added into the klass

Examples:

Adding a default value method


class MyModel
end

buider = Sinclair.new(MyModel)

builder.add_method(:default_value) { value }

MyModel.new.respond_to(:default_value) # returns false

builder.build

MyModel.new.respond_to(:default_value) # returns true

Returns:



174
175
176
177
# File 'lib/sinclair.rb', line 174

def build
  builder.build_methods(definitions, MethodBuilder::INSTANCE_METHOD)
  builder.build_methods(class_definitions, MethodBuilder::CLASS_METHOD)
end

#eval_and_add_method(name, &block) ⇒ Array<MethodDefinition>

Evaluetes a block which will result in a String, the method code

Examples:

Building a initial value class method


module InitialValuer
  extend ActiveSupport::Concern

  class_methods do
    def initial_value_for(attribute, value)
      builder = Sinclair.new(self, initial_value: value)
      builder.eval_and_add_method(attribute) do
        "@#{attribute} ||= #{options_object.initial_value}"
      end
      builder.build
    end
  end
end

class MyClass
  include InitialValuer
  attr_writer :age
  initial_value_for :age, 20
end

object = MyClass.new
object.age # 20
object.age = 30
object.age # 30

Adding option for rescue


class Purchase
  def initialize(value, quantity)
    @value = value
    @quantity = quantity
  end
end

builder = Sinclair.new(Purchase)

builder.eval_and_add_method(:total_price) do
  code = 'self.value * self.quantity'
  code.concat ' rescue 0' if options_object.rescue_error
  code
end

builder.build

Purchase.new(2.3, 5).total_price # raises error

Using option for rescue


builder = Sinclair.new(Purchase, rescue_error: true)

builder.eval_and_add_method(:total_price) do
  code = 'self.value * self.quantity'
  code.concat ' rescue 0' if options_object.rescue_error
  code
end

builder.build

Purchase.new(2.3, 5).total_price # returns 0

class Purchase
  attr_reader :value, :quantity
end

Purchase.new(2.3, 5).total_price # returns 11.5

Returns:



347
348
349
# File 'lib/sinclair.rb', line 347

def eval_and_add_method(name, &block)
  add_method(name, instance_eval(&block))
end