eapi 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.coveralls.yml +1 -0
- data/.gitignore +57 -0
- data/.rspec +2 -0
- data/.travis.yml +15 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +32 -0
- data/Rakefile +11 -0
- data/eapi.gemspec +34 -0
- data/lib/eapi.rb +16 -0
- data/lib/eapi/common.rb +48 -0
- data/lib/eapi/errors.rb +6 -0
- data/lib/eapi/methods.rb +9 -0
- data/lib/eapi/methods/accessor.rb +55 -0
- data/lib/eapi/methods/names.rb +34 -0
- data/lib/eapi/methods/properties.rb +157 -0
- data/lib/eapi/methods/types.rb +35 -0
- data/lib/eapi/multiple.rb +13 -0
- data/lib/eapi/version.rb +3 -0
- data/spec/eapi_basic_spec.rb +39 -0
- data/spec/eapi_list_spec.rb +92 -0
- data/spec/eapi_to_h_spec.rb +42 -0
- data/spec/eapi_validations_spec.rb +80 -0
- data/spec/spec_helper.rb +12 -0
- metadata +243 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: b1e95dc0187bc0b633dd39f04862c3f57f1c412f
|
4
|
+
data.tar.gz: 35a9ef27b0186c91592e4a7d1bee6d43a717e13e
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: e68a34cf0a19910cda0eebdd3e855bcf3fe70fa4ab34de5c3e6f0c6bc7b67b25493f8d0a8acdf77a54fb25bffe06c841d889331abefaee245614668560d38508
|
7
|
+
data.tar.gz: 3f0961bb4964307784f5e251640b39c52ee6e488592462712b41c3b0996e75f327b9726454ec1d340dc3ce27b24a8089475201fa39946b108a7869260988a53c
|
data/.coveralls.yml
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
service_name: travis-ci
|
data/.gitignore
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
.idea
|
2
|
+
|
3
|
+
*.gem
|
4
|
+
*.rbc
|
5
|
+
/.config
|
6
|
+
/coverage/
|
7
|
+
/InstalledFiles
|
8
|
+
/pkg/
|
9
|
+
/spec/reports/
|
10
|
+
/test/tmp/
|
11
|
+
/test/version_tmp/
|
12
|
+
/tmp/
|
13
|
+
.bundle
|
14
|
+
.config
|
15
|
+
.yardoc
|
16
|
+
Gemfile.lock
|
17
|
+
InstalledFiles
|
18
|
+
_yardoc
|
19
|
+
coverage
|
20
|
+
doc/
|
21
|
+
lib/bundler/man
|
22
|
+
pkg
|
23
|
+
rdoc
|
24
|
+
spec/reports
|
25
|
+
test/tmp
|
26
|
+
test/version_tmp
|
27
|
+
tmp
|
28
|
+
*.bundle
|
29
|
+
*.so
|
30
|
+
*.o
|
31
|
+
*.a
|
32
|
+
mkmf.log
|
33
|
+
|
34
|
+
|
35
|
+
## Specific to RubyMotion:
|
36
|
+
.dat*
|
37
|
+
.repl_history
|
38
|
+
build/
|
39
|
+
|
40
|
+
## Documentation cache and generated files:
|
41
|
+
/.yardoc/
|
42
|
+
/_yardoc/
|
43
|
+
/doc/
|
44
|
+
/rdoc/
|
45
|
+
|
46
|
+
## Environment normalisation:
|
47
|
+
/.bundle/
|
48
|
+
/lib/bundler/man/
|
49
|
+
|
50
|
+
# for a library or gem, you might want to ignore these files since the code is
|
51
|
+
# intended to run in multiple environments; otherwise, check them in:
|
52
|
+
# Gemfile.lock
|
53
|
+
# .ruby-version
|
54
|
+
# .ruby-gemset
|
55
|
+
|
56
|
+
# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
|
57
|
+
.rvmrc
|
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Eduardo Turiño
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# Eapi (Elastic API)
|
2
|
+
|
3
|
+
ruby gem for building complex structures that will end up in hashes (initially devised for ElasticSearch search requests)
|
4
|
+
|
5
|
+
[![Coverage Status](https://coveralls.io/repos/eturino/eapi/badge.png)](https://coveralls.io/r/eturino/eapi)
|
6
|
+
[![Build Status](https://travis-ci.org/eturino/eapi.svg?branch=master)](https://travis-ci.org/eturino/eapi)
|
7
|
+
|
8
|
+
## Installation
|
9
|
+
|
10
|
+
Add this line to your application's Gemfile:
|
11
|
+
|
12
|
+
gem 'eapi'
|
13
|
+
|
14
|
+
And then execute:
|
15
|
+
|
16
|
+
$ bundle
|
17
|
+
|
18
|
+
Or install it yourself as:
|
19
|
+
|
20
|
+
$ gem install eapi
|
21
|
+
|
22
|
+
## Usage
|
23
|
+
|
24
|
+
TODO: Write usage instructions here
|
25
|
+
|
26
|
+
## Contributing
|
27
|
+
|
28
|
+
1. Fork it ( https://github.com/eturino/eapi/fork )
|
29
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
30
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
31
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
32
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
data/eapi.gemspec
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'eapi/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "eapi"
|
8
|
+
spec.version = Eapi::VERSION
|
9
|
+
spec.authors = ["Eduardo Turiño"]
|
10
|
+
spec.email = ["eturino@eturino.com"]
|
11
|
+
spec.summary = %q{ruby gem for building complex structures that will end up in hashes (initially devised for ElasticSearch search requests)}
|
12
|
+
#spec.description = %q{TODO: Write a longer description. Optional.}
|
13
|
+
spec.homepage = ""
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.6"
|
22
|
+
spec.add_development_dependency "rake"
|
23
|
+
spec.add_development_dependency "rspec"
|
24
|
+
spec.add_development_dependency "rspec-nc"
|
25
|
+
spec.add_development_dependency "pry"
|
26
|
+
spec.add_development_dependency "pry-nav"
|
27
|
+
spec.add_development_dependency "pry-rescue"
|
28
|
+
spec.add_development_dependency "pry-stack_explorer"
|
29
|
+
spec.add_development_dependency "pry-doc"
|
30
|
+
spec.add_development_dependency "coveralls"
|
31
|
+
|
32
|
+
spec.add_dependency 'activesupport', '~> 4'
|
33
|
+
spec.add_dependency 'activemodel', '~> 4'
|
34
|
+
end
|
data/lib/eapi.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'active_support/all'
|
2
|
+
require 'active_model'
|
3
|
+
|
4
|
+
require 'eapi/version'
|
5
|
+
require 'eapi/errors'
|
6
|
+
require 'eapi/multiple'
|
7
|
+
require 'eapi/methods'
|
8
|
+
require 'eapi/common'
|
9
|
+
|
10
|
+
|
11
|
+
module Eapi
|
12
|
+
def self.method_missing(method, *args, &block)
|
13
|
+
klass = const_get("Eapi::#{method}")
|
14
|
+
klass.new *args, &block
|
15
|
+
end
|
16
|
+
end
|
data/lib/eapi/common.rb
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
module Eapi
|
2
|
+
module Common
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
included do
|
5
|
+
include ActiveModel::Validations
|
6
|
+
include Eapi::Methods::Properties::InstanceMethods
|
7
|
+
end
|
8
|
+
|
9
|
+
def initialize(** properties)
|
10
|
+
properties.each do |k, v|
|
11
|
+
normal_setter = "#{k}="
|
12
|
+
#TODO: what to do with unrecognised properties
|
13
|
+
send normal_setter, v if respond_to? normal_setter
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def method_missing(method, *args)
|
18
|
+
catch(:response) do
|
19
|
+
Eapi::Methods::Types.check_asking_type method, self
|
20
|
+
|
21
|
+
# if nothing catch -> continue super
|
22
|
+
super
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def to_h
|
27
|
+
raise Eapi::Errors::InvalidElementError, "errors: #{errors.full_messages}, self: #{self.inspect}" unless valid?
|
28
|
+
|
29
|
+
create_hash
|
30
|
+
end
|
31
|
+
|
32
|
+
def create_hash
|
33
|
+
{}.tap do |hash|
|
34
|
+
self.class.properties.each do |prop|
|
35
|
+
stored = get(prop)
|
36
|
+
val = (stored.present? && stored.respond_to?(:to_h)) ? stored.to_h : stored
|
37
|
+
hash[prop] = val unless val.nil?
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
module ClassMethods
|
43
|
+
include Eapi::Methods::Accessor
|
44
|
+
include Eapi::Methods::Types::ClassMethods
|
45
|
+
include Eapi::Methods::Properties::ClassMethods
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
data/lib/eapi/errors.rb
ADDED
data/lib/eapi/methods.rb
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
module Eapi
|
2
|
+
module Methods
|
3
|
+
|
4
|
+
module Accessor
|
5
|
+
def define_multiple_accessor(field)
|
6
|
+
init = Eapi::Methods::Names.init field
|
7
|
+
fluent_adder = Eapi::Methods::Names.add field
|
8
|
+
fluent_setter = Eapi::Methods::Names.fluent_setter field
|
9
|
+
getter = Eapi::Methods::Names.getter field
|
10
|
+
|
11
|
+
define_method fluent_adder do |value|
|
12
|
+
current = send(getter) || send(init)
|
13
|
+
current << value
|
14
|
+
send(fluent_setter, current)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def define_init(field, type_class)
|
19
|
+
init = Eapi::Methods::Names.init field
|
20
|
+
instance_var = Eapi::Methods::Names.instance_var field
|
21
|
+
|
22
|
+
define_method init do
|
23
|
+
value = type_class.new
|
24
|
+
instance_variable_set instance_var, value
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def define_accessors(field)
|
29
|
+
normal_setter = Eapi::Methods::Names.setter field
|
30
|
+
fluent_setter = Eapi::Methods::Names.fluent_setter field
|
31
|
+
getter = Eapi::Methods::Names.getter field
|
32
|
+
instance_var = Eapi::Methods::Names.instance_var field
|
33
|
+
|
34
|
+
define_method normal_setter do |value|
|
35
|
+
instance_variable_set instance_var, value
|
36
|
+
end
|
37
|
+
|
38
|
+
# fluent setter that calls the normal setter and returns self
|
39
|
+
define_method fluent_setter do |value|
|
40
|
+
send normal_setter, value
|
41
|
+
self
|
42
|
+
end
|
43
|
+
|
44
|
+
# special getter => if no arguments it is a getter, if arguments it calls the fluent setter
|
45
|
+
define_method getter do |*args|
|
46
|
+
if args.empty?
|
47
|
+
instance_variable_get instance_var
|
48
|
+
else
|
49
|
+
send fluent_setter, *args
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Eapi
|
2
|
+
module Methods
|
3
|
+
|
4
|
+
module Names
|
5
|
+
def self.init(field)
|
6
|
+
"init_#{field}"
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.clear(field)
|
10
|
+
"clear_#{field}"
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.add(field)
|
14
|
+
"add_#{field}"
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.getter(field)
|
18
|
+
"#{field}"
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.setter(field)
|
22
|
+
"#{field}="
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.fluent_setter(field)
|
26
|
+
"set_#{field}"
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.instance_var(field)
|
30
|
+
"@#{field}"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,157 @@
|
|
1
|
+
module Eapi
|
2
|
+
module Methods
|
3
|
+
|
4
|
+
module Properties
|
5
|
+
module InstanceMethods
|
6
|
+
def get(field)
|
7
|
+
getter = Eapi::Methods::Names.getter field
|
8
|
+
send(getter)
|
9
|
+
end
|
10
|
+
|
11
|
+
def set(field, value)
|
12
|
+
setter = Eapi::Methods::Names.fluent_setter field
|
13
|
+
send(setter, value)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
module ClassMethods
|
18
|
+
def property(field, definition = {})
|
19
|
+
fs = field.to_sym
|
20
|
+
define_accessors fs
|
21
|
+
run_definition fs, definition
|
22
|
+
store_definition fs, definition
|
23
|
+
end
|
24
|
+
|
25
|
+
def properties
|
26
|
+
@_definitions.keys
|
27
|
+
end
|
28
|
+
|
29
|
+
def definition_for(field)
|
30
|
+
@_definitions ||= {}
|
31
|
+
@_definitions.fetch(field.to_sym, {}).dup
|
32
|
+
end
|
33
|
+
|
34
|
+
def store_definition(field, definition)
|
35
|
+
@_definitions ||= {}
|
36
|
+
@_definitions[field] = definition
|
37
|
+
end
|
38
|
+
|
39
|
+
def run_definition(field, definition)
|
40
|
+
DefinitionRunner.new(self, field, definition).run
|
41
|
+
end
|
42
|
+
|
43
|
+
private :run_definition
|
44
|
+
private :store_definition
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
class DefinitionRunner < Struct.new(:klass, :field, :definition)
|
49
|
+
def run
|
50
|
+
run_multiple_accessor
|
51
|
+
run_init
|
52
|
+
run_validations
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
def run_validations
|
57
|
+
run_required
|
58
|
+
run_validate_type
|
59
|
+
run_validate_with
|
60
|
+
run_validate_type_element
|
61
|
+
run_validate_element_with
|
62
|
+
end
|
63
|
+
|
64
|
+
def run_validate_type
|
65
|
+
if type
|
66
|
+
klass.send :validates_each, field do |record, attr, value|
|
67
|
+
return if value.nil? && !required
|
68
|
+
|
69
|
+
record.errors.add(attr, "must be a #{type}") unless value.kind_of?(type)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def run_validate_element_with
|
75
|
+
if multiple && validate_element_with
|
76
|
+
validates_each field do |record, attr, value|
|
77
|
+
if value.respond_to?(:each)
|
78
|
+
value.each do |v|
|
79
|
+
validate_element_with.call(record, attr, v)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def run_validate_type_element
|
87
|
+
if multiple && type_element
|
88
|
+
validates_each field do |record, attr, value|
|
89
|
+
if value.respond_to?(:each)
|
90
|
+
value.each do |v|
|
91
|
+
record.errors.add(attr, "element must be a #{type}") unless v.kind_of?(type)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def run_validate_with
|
99
|
+
if validate_with
|
100
|
+
klass.send :validates_each, field do |record, attr, value|
|
101
|
+
validate_with.call(record, attr, value)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def run_required
|
107
|
+
if required
|
108
|
+
klass.send :validates_presence_of, field
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def run_init
|
113
|
+
if type || multiple
|
114
|
+
klass.send :define_init, field, type || Array
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def run_multiple_accessor
|
119
|
+
if multiple
|
120
|
+
klass.send :define_multiple_accessor, field
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
def type_multiple?(type)
|
125
|
+
return false if type.nil?
|
126
|
+
return true if type == Array || type == Set
|
127
|
+
|
128
|
+
type.respond_to?(:is_multiple?) && type.is_multiple?
|
129
|
+
end
|
130
|
+
|
131
|
+
def validate_element_with
|
132
|
+
definition.fetch(:validate_element_with, nil)
|
133
|
+
end
|
134
|
+
|
135
|
+
def multiple
|
136
|
+
definition.fetch(:multiple, false) || type_multiple?(type)
|
137
|
+
end
|
138
|
+
|
139
|
+
def required
|
140
|
+
definition.fetch(:required, false)
|
141
|
+
end
|
142
|
+
|
143
|
+
def validate_with
|
144
|
+
definition.fetch(:validate_with, nil)
|
145
|
+
end
|
146
|
+
|
147
|
+
def type_element
|
148
|
+
definition.fetch(:type_element, nil)
|
149
|
+
end
|
150
|
+
|
151
|
+
def type
|
152
|
+
definition.fetch(:type, nil)
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
end
|
157
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Eapi
|
2
|
+
module Methods
|
3
|
+
|
4
|
+
module Types
|
5
|
+
def self.type_question_method(method)
|
6
|
+
ms = method.to_s
|
7
|
+
if ms.start_with?('is_a_') && ms.end_with?('?')
|
8
|
+
ms.sub('is_a_', '').sub('?', '')
|
9
|
+
else
|
10
|
+
nil
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.check_asking_type(method, obj)
|
15
|
+
type = Types.type_question_method method
|
16
|
+
if type
|
17
|
+
throw :response, obj.class.is?(type)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
module ClassMethods
|
23
|
+
def is?(type)
|
24
|
+
@i_am_a && @i_am_a.include?(type.to_sym)
|
25
|
+
end
|
26
|
+
|
27
|
+
def is(*types)
|
28
|
+
@i_am_a ||= []
|
29
|
+
@i_am_a.concat(types.map(&:to_sym))
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
data/lib/eapi/version.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe Eapi do
|
4
|
+
|
5
|
+
context 'basic behaviour' do
|
6
|
+
class Eapi::MyTestKlass
|
7
|
+
include Eapi::Common
|
8
|
+
|
9
|
+
property :something
|
10
|
+
end
|
11
|
+
|
12
|
+
describe '#something (fluent setter/getter)' do
|
13
|
+
describe '#something as getter' do
|
14
|
+
it 'return the value' do
|
15
|
+
eapi = Eapi::MyTestKlass.new something: :hey
|
16
|
+
expect(eapi.something).to eq :hey
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe '#something("val")' do
|
21
|
+
it 'set the value and return self' do
|
22
|
+
eapi = Eapi::MyTestKlass.new something: :hey
|
23
|
+
res = eapi.something :other
|
24
|
+
expect(eapi).to be res
|
25
|
+
expect(eapi.something).to eq :other
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe 'Eapi.MyTestKlass(...)' do
|
31
|
+
it 'calls EapiTestClass.new' do
|
32
|
+
eapi = Eapi.MyTestKlass(something: :hey)
|
33
|
+
expect(eapi).to be_a Eapi::MyTestKlass
|
34
|
+
expect(eapi.something).to eq :hey
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe Eapi do
|
4
|
+
|
5
|
+
context 'list' do
|
6
|
+
class Eapi::MyTestClassValMult
|
7
|
+
include Eapi::Common
|
8
|
+
|
9
|
+
property :something, multiple: true
|
10
|
+
end
|
11
|
+
|
12
|
+
it '#add_something' do
|
13
|
+
eapi = Eapi::MyTestClassValMult.new something: [1, 2]
|
14
|
+
res = eapi.add_something 3
|
15
|
+
expect(res).to be eapi
|
16
|
+
expect(eapi.something).to eq [1, 2, 3]
|
17
|
+
end
|
18
|
+
|
19
|
+
it '#init_something called on first add if element is nil' do
|
20
|
+
eapi = Eapi::MyTestClassValMult.new
|
21
|
+
res = eapi.add_something :a
|
22
|
+
expect(res).to be eapi
|
23
|
+
expect(eapi.something.to_a).to eq [:a]
|
24
|
+
end
|
25
|
+
|
26
|
+
class Eapi::MyTestClassValMultImpl
|
27
|
+
include Eapi::Common
|
28
|
+
|
29
|
+
property :something, type: Set
|
30
|
+
end
|
31
|
+
|
32
|
+
class MyMultiple
|
33
|
+
def self.is_multiple?
|
34
|
+
true
|
35
|
+
end
|
36
|
+
|
37
|
+
def <<(x)
|
38
|
+
@elements ||= []
|
39
|
+
@elements << x
|
40
|
+
end
|
41
|
+
|
42
|
+
def to_a
|
43
|
+
@elements.to_a
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
class Eapi::MyTestClassValMultImpl2
|
48
|
+
include Eapi::Common
|
49
|
+
|
50
|
+
property :something, type: MyMultiple
|
51
|
+
end
|
52
|
+
|
53
|
+
class MyMultipleEapi
|
54
|
+
include Eapi::Multiple
|
55
|
+
|
56
|
+
def <<(x)
|
57
|
+
@elements ||= []
|
58
|
+
@elements << x
|
59
|
+
end
|
60
|
+
|
61
|
+
def to_a
|
62
|
+
@elements.to_a
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
class Eapi::MyTestClassValMultImpl3
|
67
|
+
include Eapi::Common
|
68
|
+
|
69
|
+
property :something, type: MyMultipleEapi
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'if type is Array or Set, or responds true to is_multiple?, it is multiple implicitly + uses that class to initialize the property when adding' do
|
73
|
+
[
|
74
|
+
[Eapi::MyTestClassValMult, Array],
|
75
|
+
[Eapi::MyTestClassValMultImpl, Set],
|
76
|
+
[Eapi::MyTestClassValMultImpl2, MyMultiple],
|
77
|
+
[Eapi::MyTestClassValMultImpl3, MyMultipleEapi],
|
78
|
+
].each do |(eapi_class, type_class)|
|
79
|
+
eapi = eapi_class.new
|
80
|
+
res = eapi.add_something :a
|
81
|
+
expect(res).to be eapi
|
82
|
+
expect(eapi.something.to_a).to eq [:a]
|
83
|
+
expect(eapi.something).to be_a_kind_of type_class
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
it 'validate elements' do
|
88
|
+
skip 'test TBD'
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe Eapi do
|
4
|
+
|
5
|
+
context '#to_h' do
|
6
|
+
class Eapi::MyTestClassToH
|
7
|
+
include Eapi::Common
|
8
|
+
|
9
|
+
property :something, required: true
|
10
|
+
property :other
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'raise error if invalid' do
|
14
|
+
eapi = Eapi::MyTestClassToH.new
|
15
|
+
expect { eapi.to_h }.to raise_error do |error|
|
16
|
+
expect(error).to be_a_kind_of Eapi::Errors::InvalidElementError
|
17
|
+
expect(error.message).to be_start_with "errors: [\"Something can't be blank\"], self: #<Eapi::MyTestClassToH"
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'create a hash with elements (calling to_h to each element), avoiding nils' do
|
23
|
+
eapi = Eapi::MyTestClassToH.new
|
24
|
+
eapi.something 'hi'
|
25
|
+
expected = {something: 'hi'}
|
26
|
+
expect(eapi.to_h).to eq expected
|
27
|
+
|
28
|
+
class MyTestObject
|
29
|
+
def to_h
|
30
|
+
'hello'
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
element = MyTestObject.new
|
35
|
+
eapi = Eapi::MyTestClassToH.new
|
36
|
+
eapi.something(element).other(true)
|
37
|
+
expected = {something: 'hello', other: true}
|
38
|
+
|
39
|
+
expect(eapi.to_h).to eq expected
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe Eapi do
|
4
|
+
|
5
|
+
context 'validations' do
|
6
|
+
describe '#valid?' do
|
7
|
+
it 'true if no validations' do
|
8
|
+
class Eapi::MyTestClassVal
|
9
|
+
include Eapi::Common
|
10
|
+
|
11
|
+
property :something
|
12
|
+
end
|
13
|
+
|
14
|
+
eapi = Eapi::MyTestClassVal.new something: :hey
|
15
|
+
expect(eapi).to be_valid
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'false if validations not met' do
|
19
|
+
class Eapi::MyTestClassVal2
|
20
|
+
include Eapi::Common
|
21
|
+
|
22
|
+
property :something
|
23
|
+
|
24
|
+
validates_presence_of :something
|
25
|
+
end
|
26
|
+
|
27
|
+
eapi = Eapi::MyTestClassVal2.new
|
28
|
+
expect(eapi).not_to be_valid
|
29
|
+
expect(eapi.errors.full_messages).to eq ["Something can't be blank"]
|
30
|
+
expect(eapi.errors.messages).to eq({something: ["can't be blank"]})
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'if required, same as validate presence' do
|
35
|
+
class Eapi::MyTestClassVal3
|
36
|
+
include Eapi::Common
|
37
|
+
|
38
|
+
property :something, required: true
|
39
|
+
end
|
40
|
+
|
41
|
+
eapi = Eapi::MyTestClassVal3.new
|
42
|
+
expect(eapi).not_to be_valid
|
43
|
+
expect(eapi.errors.full_messages).to eq ["Something can't be blank"]
|
44
|
+
expect(eapi.errors.messages).to eq({something: ["can't be blank"]})
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'if type specified with a class, validates it' do
|
48
|
+
class Eapi::MyTestClassVal3
|
49
|
+
include Eapi::Common
|
50
|
+
|
51
|
+
property :something, type: Hash
|
52
|
+
end
|
53
|
+
|
54
|
+
eapi = Eapi::MyTestClassVal3.new something: 1
|
55
|
+
expect(eapi).not_to be_valid
|
56
|
+
expect(eapi.errors.full_messages).to eq ["Something must be a Hash"]
|
57
|
+
expect(eapi.errors.messages).to eq({something: ["must be a Hash"]})
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'if validate_with: specified with a class, uses it to validate the property' do
|
61
|
+
class Eapi::MyTestClassVal4
|
62
|
+
include Eapi::Common
|
63
|
+
|
64
|
+
property :something, validate_with: ->(record, attr, value) do
|
65
|
+
record.errors.add(attr, "must pass my custom validation") unless value == :valid_val
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
eapi = Eapi::MyTestClassVal4.new something: 1
|
70
|
+
|
71
|
+
expect(eapi).not_to be_valid
|
72
|
+
expect(eapi.errors.full_messages).to eq ["Something must pass my custom validation"]
|
73
|
+
expect(eapi.errors.messages).to eq({something: ["must pass my custom validation"]})
|
74
|
+
|
75
|
+
eapi.something :valid_val
|
76
|
+
expect(eapi).to be_valid
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,243 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: eapi
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Eduardo Turiño
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-06-28 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.6'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.6'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec-nc
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: pry
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: pry-nav
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: pry-rescue
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: pry-stack_explorer
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: pry-doc
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: coveralls
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - ">="
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0'
|
146
|
+
type: :development
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - ">="
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '0'
|
153
|
+
- !ruby/object:Gem::Dependency
|
154
|
+
name: activesupport
|
155
|
+
requirement: !ruby/object:Gem::Requirement
|
156
|
+
requirements:
|
157
|
+
- - "~>"
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: '4'
|
160
|
+
type: :runtime
|
161
|
+
prerelease: false
|
162
|
+
version_requirements: !ruby/object:Gem::Requirement
|
163
|
+
requirements:
|
164
|
+
- - "~>"
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: '4'
|
167
|
+
- !ruby/object:Gem::Dependency
|
168
|
+
name: activemodel
|
169
|
+
requirement: !ruby/object:Gem::Requirement
|
170
|
+
requirements:
|
171
|
+
- - "~>"
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: '4'
|
174
|
+
type: :runtime
|
175
|
+
prerelease: false
|
176
|
+
version_requirements: !ruby/object:Gem::Requirement
|
177
|
+
requirements:
|
178
|
+
- - "~>"
|
179
|
+
- !ruby/object:Gem::Version
|
180
|
+
version: '4'
|
181
|
+
description:
|
182
|
+
email:
|
183
|
+
- eturino@eturino.com
|
184
|
+
executables: []
|
185
|
+
extensions: []
|
186
|
+
extra_rdoc_files: []
|
187
|
+
files:
|
188
|
+
- ".coveralls.yml"
|
189
|
+
- ".gitignore"
|
190
|
+
- ".rspec"
|
191
|
+
- ".travis.yml"
|
192
|
+
- Gemfile
|
193
|
+
- LICENSE.txt
|
194
|
+
- README.md
|
195
|
+
- Rakefile
|
196
|
+
- eapi.gemspec
|
197
|
+
- lib/eapi.rb
|
198
|
+
- lib/eapi/common.rb
|
199
|
+
- lib/eapi/errors.rb
|
200
|
+
- lib/eapi/methods.rb
|
201
|
+
- lib/eapi/methods/accessor.rb
|
202
|
+
- lib/eapi/methods/names.rb
|
203
|
+
- lib/eapi/methods/properties.rb
|
204
|
+
- lib/eapi/methods/types.rb
|
205
|
+
- lib/eapi/multiple.rb
|
206
|
+
- lib/eapi/version.rb
|
207
|
+
- spec/eapi_basic_spec.rb
|
208
|
+
- spec/eapi_list_spec.rb
|
209
|
+
- spec/eapi_to_h_spec.rb
|
210
|
+
- spec/eapi_validations_spec.rb
|
211
|
+
- spec/spec_helper.rb
|
212
|
+
homepage: ''
|
213
|
+
licenses:
|
214
|
+
- MIT
|
215
|
+
metadata: {}
|
216
|
+
post_install_message:
|
217
|
+
rdoc_options: []
|
218
|
+
require_paths:
|
219
|
+
- lib
|
220
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
221
|
+
requirements:
|
222
|
+
- - ">="
|
223
|
+
- !ruby/object:Gem::Version
|
224
|
+
version: '0'
|
225
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
226
|
+
requirements:
|
227
|
+
- - ">="
|
228
|
+
- !ruby/object:Gem::Version
|
229
|
+
version: '0'
|
230
|
+
requirements: []
|
231
|
+
rubyforge_project:
|
232
|
+
rubygems_version: 2.2.2
|
233
|
+
signing_key:
|
234
|
+
specification_version: 4
|
235
|
+
summary: ruby gem for building complex structures that will end up in hashes (initially
|
236
|
+
devised for ElasticSearch search requests)
|
237
|
+
test_files:
|
238
|
+
- spec/eapi_basic_spec.rb
|
239
|
+
- spec/eapi_list_spec.rb
|
240
|
+
- spec/eapi_to_h_spec.rb
|
241
|
+
- spec/eapi_validations_spec.rb
|
242
|
+
- spec/spec_helper.rb
|
243
|
+
has_rdoc:
|