Class: Sinclair

Inherits:
Object show all
Extended by:
ClassMethods
Includes:
OptionsParser
Defined in:
lib/sinclair.rb,
lib/sinclair/model.rb,
lib/sinclair/caster.rb,
lib/sinclair/config.rb,
lib/sinclair/options.rb,
lib/sinclair/version.rb,
lib/sinclair/matchers.rb,
lib/sinclair/settable.rb,
lib/sinclair/exception.rb,
lib/sinclair/comparable.rb,
lib/sinclair/input_hash.rb,
lib/sinclair/config_class.rb,
lib/sinclair/configurable.rb,
lib/sinclair/env_settable.rb,
lib/sinclair/class_methods.rb,
lib/sinclair/matchers/base.rb,
lib/sinclair/model/builder.rb,
lib/sinclair/chain_settable.rb,
lib/sinclair/config_builder.rb,
lib/sinclair/config_factory.rb,
lib/sinclair/equals_checker.rb,
lib/sinclair/method_builder.rb,
lib/sinclair/options_parser.rb,
lib/sinclair/options/builder.rb,
lib/sinclair/settable/caster.rb,
lib/sinclair/settable/builder.rb,
lib/sinclair/method_definition.rb,
lib/sinclair/matchers/method_to.rb,
lib/sinclair/method_definitions.rb,
lib/sinclair/matchers/add_method.rb,
lib/sinclair/method_builder/base.rb,
lib/sinclair/caster/class_methods.rb,
lib/sinclair/equals_checker/reader.rb,
lib/sinclair/model/builder_options.rb,
lib/sinclair/options/class_methods.rb,
lib/sinclair/config/methods_builder.rb,
lib/sinclair/matchers/add_method_to.rb,
lib/sinclair/settable/class_methods.rb,
lib/sinclair/comparable/class_methods.rb,
lib/sinclair/matchers/add_class_method.rb,
lib/sinclair/matchers/change_method_on.rb,
lib/sinclair/matchers/add_class_method_to.rb,
lib/sinclair/matchers/add_instance_method.rb,
lib/sinclair/matchers/change_class_method.rb,
lib/sinclair/method_definition/stringifier.rb,
lib/sinclair/method_definition/block_helper.rb,
lib/sinclair/matchers/add_instance_method_to.rb,
lib/sinclair/matchers/change_class_method_on.rb,
lib/sinclair/matchers/change_instance_method.rb,
lib/sinclair/method_definition/call_definition.rb,
lib/sinclair/matchers/change_instance_method_on.rb,
lib/sinclair/method_builder/call_method_builder.rb,
lib/sinclair/method_definition/block_definition.rb,
lib/sinclair/method_definition/parameter_helper.rb,
lib/sinclair/method_builder/block_method_builder.rb,
lib/sinclair/method_definition/parameter_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

value = 10

Sinclair.build(MyModel) do
  add_method(:default_value) { value }
  add_method(:value, '@value || default_value')
  add_method(:value=) { |val| @value = val }
end

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: ChainSettable, ClassMethods, Comparable, ConfigClass, Configurable, EnvSettable, Matchers, OptionsParser, Settable Classes: Caster, Config, ConfigBuilder, ConfigFactory, EqualsChecker, Exception, InputHash, MethodBuilder, MethodDefinition, MethodDefinitions, Model, Options

Constant Summary collapse

VERSION =
'2.1.1'

Instance Attribute Summary collapse

Attributes included from OptionsParser

#options

Class Method Summary collapse

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

MyBuilder.build(MyModel, rescue_error: true) do
  add_method
end

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



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

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

Instance Attribute Details

#klassClass (readonly)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Class that will receive the methods

Returns:

  • (Class)


469
470
471
# File 'lib/sinclair.rb', line 469

def klass
  @klass
end

Class Method Details

.build(klass, options = {}, &block) { ... } ⇒ Array<MethodDefinition>

Runs build using a block for adding the methods

The block is executed adding the methods and after the builder runs build building all the methods

Examples:

Simple usage

class MyPerson
end

Sinclair.build(model_class) do
  add_method(:random_name, cached: true) do
    "John #{Random.rand(1000)} Doe"
  end
end

model = MyPerson.new

model.random_name # returns 'John 803 Doe'

Parameters:

  • block (Proc)

    block to be executed by the builder in order to add the methods before running build

  • 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

Yields:

Returns:

See Also:



# File 'lib/sinclair.rb', line 109

Instance Method Details

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

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

Overloads:

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

    Examples:

    Adding a method by String

    class EnvFetcher
    end
    
    builder = Sinclair.new(EnvFetcher)
    
    builder.add_class_method(:hostname, 'ENV["HOSTNAME"]')
    builder.build
    
    ENV['HOSTNAME'] = 'myhost'
    
    EnvFetcher.hostname # returns 'myhost'

    Parameters:

    • name (String, Symbol)

      name of the method to be added

    • code (String)

      code to be evaluated when the method is ran

    • options (Hash)

      Options of construction

    Options Hash (**options):

    • cached (Boolean)

      Flag telling to create a method with cache

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

    Examples:

    Adding a method by Block

    class EnvFetcher
    end
    
    builder = Sinclair.new(EnvFetcher)
    
    builder.add_class_method(:timeout) { ENV['TIMEOUT'] }
    builder.build
    
    ENV['TIMEOUT'] = '300'
    
    EnvFetcher.timeout # returns '300'

    Parameters:

    • name (String, Symbol)

      name of the method to be added

    • block (Proc)

      block to be ran as method

    • options (Hash)

      Options of construction

    Options Hash (**options):

    • cached (Boolean)

      Flag telling to create a method with cache

  • #add_class_method(*args, type: **options, &block) ⇒ Array<MethodDefinition>

    Examples:

    Passing type block

    class EnvFetcher
    end
    
    builder = Sinclair.new(EnvFetcher)
    
    builder.add_class_method(:timeout, type: :block) { ENV['TIMEOUT'] }
    builder.build
    
    ENV['TIMEOUT'] = '300'
    
    EnvFetcher.timeout # returns '300'

    Passing type call

    class EnvFetcher
    end
    
    builder = Sinclair.new(EnvFetcher)
    
    builder.add_class_method(:attr_accessor, :timeout, type: :call)
    builder.build
    
    EnvFetcher.timeout = 10
    
    env_fetcher.timeout # returns '10'

    Parameters:

    • args (Array<Object>)

      arguments to be passed to the definition

    • type (Symbol) (defaults to: **options)

      type of method definition

    • block (Proc)

      block to be ran as method when type is block

    • options (Hash)

      Options of construction

    See Also:

Returns:

See Also:



382
383
384
# File 'lib/sinclair.rb', line 382

def add_class_method(*args, type: nil, **options, &block)
  class_definitions.add(*args, type: type, **options, &block)
end

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

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

Overloads:

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

    Examples:

    Using string code to add a string defined method

    class Person
      attr_accessor :first_name, :last_name
    
      def initialize(first_name, last_name)
        @first_name = first_name
        @last_name = last_name
      end
    end
    
    Sinclair.build(Person) do
      add_method(:full_name, '[first_name, last_name].join(" ")')
    end
    
    Person.new('john', 'wick').full_name # returns 'john wick'

    Parameters:

    • name (String, Symbol)

      name of the method to be added

    • code (String)

      code to be evaluated when the method is ran

    • options (Hash)

      Options of construction

    Options Hash (**options):

    • cached (Boolean)

      Flag telling to create a method with cache

    See Also:

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

    Examples:

    Using block to add a block method

    class Person
      attr_accessor :first_name, :last_name
    
      def initialize(first_name, last_name)
        @first_name = first_name
        @last_name = last_name
      end
    end
    
    Sinclair.build(Person) do
      add_method(:bond_name) { "#{last_name}, #{first_name} #{last_name}" }
    end
    
    Person.new('john', 'wick').bond_name # returns 'wick, john wick'

    Parameters:

    • name (String, Symbol)

      name of the method to be added

    • block (Proc)

      block to be ran as method

    • options (Hash)

      Options of construction

    Options Hash (**options):

    • cached (Boolean)

      Flag telling to create a method with cache

    See Also:

  • #add_method(*args, type: , **options, &block) ⇒ Array<MethodDefinition>

    Examples:

    Passing type block

    class Person
      attr_accessor :first_name, :last_name
    
      def initialize(first_name, last_name)
        @first_name = first_name
        @last_name = last_name
      end
    end
    
    Sinclair.build(Person) do
      add_method(:bond_name, type: :block, cached: true) do
        "{last_name}, #{first_name} #{last_name}"
      end
    end
    
    person.Person.new('john', 'wick')
    
    person.bond_name # returns 'wick, john wick'
    person.first_name = 'Johny'
    person.bond_name # returns 'wick, john wick'

    Passing type call

    class Person
    end
    
    builder = Sinclair.new(Person)
    builder.add_method(:attr_accessor, :bond_name, type: :call)
    builder.build
    
    person.bond_name = 'Bond, James Bond'
    person.bond_name # returns 'Bond, James Bond'

    Parameters:

    • args (Array<Object>)

      arguments to be passed to the definition

    • type (Symbol) (defaults to: )

      type of method definition

    • block (Proc)

      block to be ran as method when type is block

    • options (Hash)

      Options of construction

    Options Hash (**options):

    • cached (Boolean)

      Flag telling to create a method with cache

    See Also:

Returns:

  • (Array<MethodDefinition>)

    the list of all currently defined instance methods

See Also:



297
298
299
# File 'lib/sinclair.rb', line 297

def add_method(*args, type: nil, **options, &block)
  definitions.add(*args, type: type, **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:



196
197
198
199
# File 'lib/sinclair.rb', line 196

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:

  • (Array<MethodDefinition>)

    the list of all currently defined instance methods



456
457
458
# File 'lib/sinclair.rb', line 456

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