README.md in sinclair-1.3.0 vs README.md in sinclair-1.3.1

- old
+ new

@@ -6,25 +6,27 @@ [![Gem Version](https://badge.fury.io/rb/sinclair.svg)](https://badge.fury.io/rb/sinclair) ![sinclair](https://raw.githubusercontent.com/darthjee/sinclair/master/sinclair.jpg) -This gem helps the creation of complex concern with class methods +This gem helps the creation of complex gems/concerns +that enables creation of methods on the fly through class +methods Yard Documentation ------------------- -https://www.rubydoc.info/gems/sinclair/1.3.0 +https://www.rubydoc.info/gems/sinclair/1.3.1 Installation --------------- - Install it ```ruby gem install sinclair ``` - - Or add Sinclairn to your `Gemfile` and `bundle install`: + - Or add Sinclair to your `Gemfile` and `bundle install`: ```ruby gem 'sinclair' ``` @@ -32,14 +34,16 @@ bundle install sinclair ``` Usage --------------- -The concern builder can actully be used in two ways, as an stand alone object capable of -adding methods to your class or by extending it for more complex logics +# Sinclair +Sinclair can actully be used in several ways, as an stand alone object capable of +adding methods to your class on the fly, as a builder inside a class method +or by extending it for more complex logics - - Stand Alone usage: +## Stand Alone usage creating methods on the fly: ```ruby class Clazz end @@ -54,22 +58,82 @@ puts "Twenty => #{instance.twenty}" # Twenty => 20 puts "Eighty => #{instance.eighty}" # Eighty => 80 ``` - - Extending the builder +## Builder in class method: ```ruby + class HttpJsonModel + attr_reader :json - class ValidationBuilder < Sinclair - delegate :expected, to: :options_object + class << self + def parse(attribute, path: []) + builder = Sinclair.new(self) - def initialize(klass, options={}) - super + keys = (path + [attribute]).map(&:to_s) + + builder.add_method(attribute) do + keys.inject(hash) { |h, key| h[key] } + end + + builder.build + end end - def add_validation(field) + def initialize(json) + @json = json + end + + def hash + @hash ||= JSON.parse(json) + end + end + + class HttpPerson < HttpJsonModel + parse :uid + parse :name, path: [:personal_information] + parse :age, path: [:personal_information] + parse :username, path: [:digital_information] + parse :email, path: [:digital_information] + end + + json = <<-JSON + { + "uid": "12sof511", + "personal_information":{ + "name":"Bob", + "age": 21 + }, + "digital_information":{ + "username":"lordbob", + "email":"lord@bob.com" + } + } + JSON + + person = HttpPerson.new(json) + + person.uid # returns '12sof511' + person.name # returns 'Bob' + person.age # returns 21 + person.username # returns 'lordbob' + person.email # returns 'lord@bob.com' +``` + +## Extending the builder + +```ruby + + class ValidationBuilder < Sinclair + delegate :expected, to: :options_object + + def initialize(klass, options={}) + super + end + + def add_validation(field) add_method("#{field}_valid?", "#{field}.is_a?#{expected}") end def add_accessors(fields) klass.send(:attr_accessor, *fields) @@ -147,14 +211,17 @@ legs: 2 ) invalid_object.valid? # returns false ``` - - Caching the result - If wanted, the result of the method can be stored in an - instance variable with the same name +## Caching the result +If wanted, the result of the method can be stored in an +instance variable with the same name. +When caching, you can cache with type `:full` so that even `nil` +values are cached + ```ruby class MyModel attr_accessor :base, :expoent end @@ -174,9 +241,95 @@ model.expoent = 2 model.cached_power # returns 9 model.expoent = 3 model.cached_power # returns 9 (from cache) +``` + +```ruby + 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' +``` + +# Sinclair::Configurable + +Configurable is a module that, when used, can add configurations +to your classes/modules. + +Configurations are read-only objects that can only be set using +the `configurable#configure` method + +```ruby + class MyConfigurable + extend Sinclair::Configurable + + configurable_with :host, :port + end + + MyConfigurable.configure do |config| + config.host 'interstella.art' + config.port 5555 + end + + MyConfigurable.config.host # returns 'interstella.art' + MyConfigurable.config.port # returns 5555 + + MyConfigurable.reset_config + + MyConfigurable.config.host # returns nil + MyConfigurable.config.port # returns nil ``` RSspec matcher ---------------