setsumei 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,5 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
5
+ .rvmrc
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --colour
2
+ --format documentation
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in setsumei.gemspec
4
+ gemspec
@@ -0,0 +1,4 @@
1
+ Setsumei
2
+ --------
3
+
4
+ Api description tool to build ruby DSL's from JSON data.
@@ -0,0 +1,2 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
@@ -0,0 +1,2 @@
1
+ require 'setsumei/describable'
2
+ require 'setsumei/build'
@@ -0,0 +1,21 @@
1
+ require 'setsumei/build/key'
2
+
3
+ module Setsumei
4
+ module Build
5
+ def Build.a(klass,options = {})
6
+ inform_developer "#{klass} should be able to list its attributes" unless klass.respond_to? :defined_attributes
7
+ inform_developer "wrong number of arguments, options must include from: data }" unless options.keys.include? :from
8
+
9
+ klass.new.tap do |object|
10
+ klass.defined_attributes.each do |_,attribute|
11
+ attribute.set_value_on object, from_value_in: options[:from]
12
+ end
13
+ end
14
+ end
15
+
16
+ private
17
+ def self.inform_developer(message)
18
+ raise ArgumentError.new message
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,28 @@
1
+ module Setsumei
2
+ module Build
3
+ class Key
4
+ def Key.for(name,options = { given: [name] } )
5
+ possible_keys = options[:given]
6
+ lower_camel_case(name,possible_keys) || at_symbol_case(name,possible_keys) || upper_camel_case(name,possible_keys)
7
+ end
8
+ def Key.lower_camel_case name, keys = nil
9
+ lower_camel_case = name.to_s.gsub(/_[a-zA-Z]/) { |a| a[1].upcase }
10
+ return_if lower_camel_case, in: keys
11
+ end
12
+ def Key.at_symbol_case name, keys = nil
13
+ at_symbol_case = "@" + lower_camel_case(name)
14
+ return_if at_symbol_case, in: keys
15
+ end
16
+ def Key.upper_camel_case name, keys = nil
17
+ lower_camel_case = self.lower_camel_case(name)
18
+ upper_camel_case = lower_camel_case[0].upcase + lower_camel_case[1..-1]
19
+ return_if upper_camel_case, in: keys
20
+ end
21
+
22
+ private
23
+ def self.return_if value, options = { in: [] }
24
+ (options[:in] || [value]).select { |possible| possible == value }.first
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,80 @@
1
+ require 'setsumei/describable/boolean_attribute'
2
+ require 'setsumei/describable/string_attribute'
3
+ require 'setsumei/describable/float_attribute'
4
+ require 'setsumei/describable/int_attribute'
5
+ require 'setsumei/describable/object_attribute'
6
+ require 'setsumei/describable/collection'
7
+
8
+ module Setsumei
9
+ module Describable
10
+
11
+ def Describable.included(other)
12
+ other.extend DescriptionMethods
13
+ end
14
+
15
+ module DescriptionMethods
16
+
17
+ def defined_attributes
18
+ _defined_attributes.dup
19
+ end
20
+
21
+ def define field_name, options = {}
22
+ _defined_attributes[field_name] = attribute_type(options[:as_a]).named field_name, options
23
+ attr_accessor field_name
24
+ end
25
+
26
+ def collection_of klass, options = {}
27
+ self.class_eval do
28
+ include Enumerable
29
+ include Comparable
30
+
31
+ def each(*args,&block)
32
+ _internal_collection.each(*args,&block)
33
+ end
34
+
35
+ def include? value
36
+ _internal_collection.include? value
37
+ end
38
+
39
+ def <<(value)
40
+ _internal_collection << value
41
+ end
42
+
43
+ def [](value)
44
+ _internal_collection[value]
45
+ end
46
+
47
+ def []=(index,value)
48
+ _internal_collection[index] = value
49
+ end
50
+
51
+ def <=>(other)
52
+ _internal_collection <=> other || super
53
+ end
54
+
55
+ private
56
+ def _internal_collection
57
+ @_internal_collection ||= []
58
+ end
59
+ end
60
+ _defined_attributes[:_self] = Collection.of klass,options
61
+ end
62
+
63
+ private
64
+ def _defined_attributes
65
+ (@_defined_attributes ||= {})
66
+ end
67
+ def attribute_type(type)
68
+ case type
69
+ when :boolean then BooleanAttribute
70
+ when :string then StringAttribute
71
+ when nil then StringAttribute
72
+ when :float then FloatAttribute
73
+ when :int then IntAttribute
74
+ else
75
+ ObjectAttribute if type.is_a?(Class)
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,34 @@
1
+ module Setsumei
2
+ module Describable
3
+ class BooleanAttribute
4
+
5
+ def BooleanAttribute.named(name, options = {})
6
+ new.tap do |attribute|
7
+ attribute.name = name
8
+ end
9
+ end
10
+
11
+ attr_accessor :name
12
+
13
+ def is_an_attribute_of_type?(type)
14
+ type == :boolean || type == self.class
15
+ end
16
+
17
+ def value_for(pre_type_cast_value)
18
+ pre_type_cast_value.to_s.downcase == "true" || pre_type_cast_value.to_s == "1"
19
+ end
20
+
21
+ def set_value_on(object, options)
22
+ object.send accessor, value_from_hash(options[:from_value_in])
23
+ end
24
+
25
+ private
26
+ def accessor
27
+ :"#{name}="
28
+ end
29
+ def value_from_hash(hash)
30
+ value_for hash[ Build::Key.for name, given: hash.keys ]
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,20 @@
1
+ module Setsumei
2
+ module Describable
3
+ class Collection
4
+ def Collection.of(klass,options = {})
5
+ new.tap do |collection|
6
+ collection.klass = klass
7
+ collection.options = options
8
+ end
9
+ end
10
+
11
+ attr_accessor :klass, :options
12
+
13
+ def set_value_on(object, options = {})
14
+ [options[:from_value_in][Build::Key.for((self.options[:within] || klass), given: options[:from_value_in].keys)]].flatten(1).each do |data|
15
+ object << Build.a(klass, from: data)
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,34 @@
1
+ module Setsumei
2
+ module Describable
3
+ class FloatAttribute
4
+
5
+ def FloatAttribute.named(name, options = {})
6
+ new.tap do |attribute|
7
+ attribute.name = name
8
+ end
9
+ end
10
+
11
+ attr_accessor :name
12
+
13
+ def is_an_attribute_of_type?(type)
14
+ type == :float || type == self.class
15
+ end
16
+
17
+ def value_for(pre_type_cast_value)
18
+ pre_type_cast_value.to_f
19
+ end
20
+
21
+ def set_value_on(object, options)
22
+ object.send accessor, value_from_hash(options[:from_value_in])
23
+ end
24
+
25
+ private
26
+ def accessor
27
+ :"#{name}="
28
+ end
29
+ def value_from_hash(hash)
30
+ value_for hash[ Build::Key.for name, given: hash.keys ]
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,33 @@
1
+ module Setsumei
2
+ module Describable
3
+ class IntAttribute
4
+ def IntAttribute.named(name, options = {})
5
+ new.tap do |attribute|
6
+ attribute.name = name
7
+ end
8
+ end
9
+
10
+ attr_accessor :name
11
+
12
+ def is_an_attribute_of_type?(type)
13
+ type == :int || type == self.class
14
+ end
15
+
16
+ def value_for(pre_type_cast_value)
17
+ pre_type_cast_value.to_f.round
18
+ end
19
+
20
+ def set_value_on(object, options)
21
+ object.send accessor, value_from_hash(options[:from_value_in])
22
+ end
23
+
24
+ private
25
+ def accessor
26
+ :"#{name}="
27
+ end
28
+ def value_from_hash(hash)
29
+ value_for hash[ Build::Key.for name, given: hash.keys ]
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,41 @@
1
+ module Setsumei
2
+ module Describable
3
+ class ObjectAttribute
4
+
5
+ def ObjectAttribute.named(name,options = {})
6
+ raise ArgumentError.new("you must specify what the object is") unless options.has_key? :as_a
7
+ new.tap do |attribute|
8
+ attribute.name = name
9
+ attribute.klass = options[:as_a]
10
+ end
11
+ end
12
+
13
+ attr_accessor :name, :klass
14
+
15
+ def initialize
16
+ self.klass = Object
17
+ end
18
+
19
+ def value_for(data)
20
+ return nil if data.nil? || data.empty?
21
+ Build.a self.klass, from: data
22
+ end
23
+
24
+ def is_an_attribute_of_type?(type)
25
+ type == :object || type == self.class || type == self.klass
26
+ end
27
+
28
+ def set_value_on(object, options)
29
+ object.send accessor, value_from_hash(options[:from_value_in])
30
+ end
31
+
32
+ private
33
+ def accessor
34
+ :"#{name}="
35
+ end
36
+ def value_from_hash(hash)
37
+ value_for hash[ Build::Key.for name, given: hash.keys ]
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,33 @@
1
+ module Setsumei
2
+ module Describable
3
+ class StringAttribute
4
+ def StringAttribute.named(name,options = {})
5
+ new.tap do |attribute|
6
+ attribute.name = name
7
+ end
8
+ end
9
+
10
+ attr_accessor :name
11
+
12
+ def is_an_attribute_of_type?(type)
13
+ type == :string || type == self.class
14
+ end
15
+
16
+ def value_for(pre_type_cast_value)
17
+ pre_type_cast_value.to_s
18
+ end
19
+
20
+ def set_value_on(object, options)
21
+ object.send accessor, value_from_hash(options[:from_value_in])
22
+ end
23
+
24
+ private
25
+ def accessor
26
+ :"#{name}="
27
+ end
28
+ def value_from_hash(hash)
29
+ value_for hash[ Build::Key.for name, given: hash.keys ]
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,3 @@
1
+ module Setsumei
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,24 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "setsumei/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "setsumei"
7
+ s.version = Setsumei::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Jon Rowe"]
10
+ s.email = ["hello@jonrowe.co.uk"]
11
+ s.homepage = "https://github.com/JonRowe/setsumei"
12
+ s.summary = %q{A tool for describing API's as ruby objects}
13
+ s.description = %q{A tool for describing API's as ruby objects. Currently supports building these objects from JSON}
14
+
15
+ s.files = `git ls-files`.split("\n")
16
+ s.test_files = `git ls-files -- {spec,features}/*`.split("\n")
17
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
18
+ s.require_paths = ["lib"]
19
+
20
+ s.add_runtime_dependency 'json'
21
+ s.add_development_dependency 'rspec'
22
+ s.add_development_dependency 'autotest-standalone'
23
+ s.add_development_dependency 'ruby-debug19'
24
+ end
@@ -0,0 +1,88 @@
1
+ require 'spec_helper'
2
+
3
+ module Setsumei
4
+ module Build
5
+ describe Key do
6
+ describe ".for name, given: hash_keys" do
7
+ let(:hash_keys) { ["otherAttribute","@anotherAttribute","Array","Object"] }
8
+
9
+ subject { Key.for :attribute_name, given: hash_keys }
10
+
11
+ specify do
12
+ hash_keys.concat ["AttributeName", "attributeName", "@attributeName"]
13
+ subject.should == "attributeName"
14
+ end
15
+
16
+ specify do
17
+ hash_keys.concat ["AttributeName", "@attributeName"]
18
+ subject.should == "@attributeName"
19
+ end
20
+
21
+ specify do
22
+ hash_keys.concat ["AttributeName"]
23
+ subject.should == "AttributeName"
24
+ end
25
+ end
26
+
27
+ describe "lower_camel_case(name,keys)" do
28
+ let(:keys) { [] }
29
+
30
+ subject { Key.lower_camel_case :attribute_name, keys }
31
+
32
+ it "should return lower camelcase named when keys contain name" do
33
+ keys << "attributeName"
34
+ subject.should == "attributeName"
35
+ end
36
+ it "should return nil when keys do not contain name" do
37
+ subject.should be_nil
38
+ end
39
+
40
+ context "keys are ommited" do
41
+ it "should return lower camelcase name" do
42
+ Key.lower_camel_case(:attribute_name).should == "attributeName"
43
+ end
44
+ end
45
+ end
46
+
47
+ describe "upper_camel_case(name,keys)" do
48
+ let(:keys) { [] }
49
+
50
+ subject { Key.upper_camel_case :attribute_name, keys }
51
+
52
+ it "should return upper camelcase named when keys contain name" do
53
+ keys << "AttributeName"
54
+ subject.should == "AttributeName"
55
+ end
56
+ it "should return nil when keys do not contain name" do
57
+ subject.should be_nil
58
+ end
59
+
60
+ context "keys are ommited" do
61
+ it "should return upper camelcase name" do
62
+ Key.upper_camel_case(:attribute_name).should == "AttributeName"
63
+ end
64
+ end
65
+ end
66
+
67
+ describe "at_symbol_case(name,keys)" do
68
+ let(:keys) { [] }
69
+
70
+ subject { Key.at_symbol_case :attribute_name, keys }
71
+
72
+ it "should return symbol case named when keys contain name" do
73
+ keys << "@attributeName"
74
+ subject.should == "@attributeName"
75
+ end
76
+ it "should return nil when keys do not contain name" do
77
+ subject.should be_nil
78
+ end
79
+
80
+ context "keys are ommited" do
81
+ it "should return at symbol case" do
82
+ Key.at_symbol_case(:attribute_name).should == "@attributeName"
83
+ end
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end