fast_attributes 0.0.1 → 0.1.0
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.
- checksums.yaml +4 -4
- data/.coveralls.yml +1 -0
- data/.rspec +2 -0
- data/.travis.yml +2 -0
- data/CHANGELOG.md +3 -0
- data/README.md +59 -1
- data/benchmarks/Gemfile +8 -0
- data/benchmarks/comparison.rb +58 -0
- data/fast_attributes.gemspec +3 -1
- data/lib/fast_attributes/version.rb +1 -1
- data/lib/fast_attributes.rb +8 -10
- data/spec/fast_attributes_spec.rb +198 -0
- data/spec/fixtures/book.rb +10 -0
- data/spec/spec_helper.rb +8 -0
- metadata +50 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 77f2e59818faf79d91ebf8f90f76cebc2bab978b
|
4
|
+
data.tar.gz: bb9905bc7899f5c2d4d4e69c8f9c42760e28be3e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0c6a59bfb0c1a73be212f8c2f9485186aaf3282d90d09633aac841fffd083645d4c12c9afc144781c38f850aa30362661710d1833886a834b544a9d568ae7410
|
7
|
+
data.tar.gz: 009c11fbd431c352d1c8fe72502851a14a1eaeb55c73184c3b2585ccf2db1b6dbdebff910bc27a05cc5e78e503f82398a95d4a719f44ea28600b191aad7bf848
|
data/.coveralls.yml
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
service_name: travis-ci
|
data/.rspec
ADDED
data/.travis.yml
ADDED
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -1,6 +1,64 @@
|
|
1
1
|
# FastAttributes
|
2
|
+
[](http://rubygems.org/gems/fast_attributes)
|
3
|
+
[](https://travis-ci.org/applift/fast_attributes)
|
4
|
+
[](https://coveralls.io/r/applift/fast_attributes?branch=master)
|
2
5
|
|
3
|
-
|
6
|
+
## Motivation
|
7
|
+
There are already a lot of good and flexible gems which solve the similar problem, allow to define attributes with their types, for example: [virtus](https://github.com/solnic/virtus) or [attrio](https://github.com/jetrockets/attrio). But the disadvantage of existing gems is performance. So, the goal of `fast_attributes` is to make a simple solution which is fast, understandable and easy extendable.
|
8
|
+
|
9
|
+
This is [performance benchmark](https://github.com/applift/fast_attributes/blob/master/benchmarks/comparison.rb) of `fast_attributes` and other popular gems.
|
10
|
+
|
11
|
+
```
|
12
|
+
Calculating -------------------------------------
|
13
|
+
FastAttributes: without values
|
14
|
+
71131 i/100ms
|
15
|
+
FastAttributes: integer values for integer attributes
|
16
|
+
8410 i/100ms
|
17
|
+
FastAttributes: string values for integer attributes
|
18
|
+
6869 i/100ms
|
19
|
+
Attrio: without values
|
20
|
+
700 i/100ms
|
21
|
+
Attrio: integer values for integer attributes
|
22
|
+
1165 i/100ms
|
23
|
+
Attrio: string values for integer attributes
|
24
|
+
1073 i/100ms
|
25
|
+
Virtus: without values
|
26
|
+
898 i/100ms
|
27
|
+
Virtus: integer values for integer attributes
|
28
|
+
2123 i/100ms
|
29
|
+
Virtus: string values for integer attributes
|
30
|
+
306 i/100ms
|
31
|
+
-------------------------------------------------
|
32
|
+
FastAttributes: without values
|
33
|
+
1528209.4 (±16.2%) i/s - 1564882 in 1.045527s
|
34
|
+
FastAttributes: integer values for integer attributes
|
35
|
+
88794.2 (±16.0%) i/s - 92510 in 1.078912s
|
36
|
+
FastAttributes: string values for integer attributes
|
37
|
+
77673.3 (±4.7%) i/s - 82428 in 1.063921s
|
38
|
+
Attrio: without values
|
39
|
+
7164.3 (±2.6%) i/s - 7700 in 1.075560s
|
40
|
+
Attrio: integer values for integer attributes
|
41
|
+
11932.2 (±2.1%) i/s - 12815 in 1.074474s
|
42
|
+
Attrio: string values for integer attributes
|
43
|
+
11007.2 (±0.9%) i/s - 11803 in 1.072382s
|
44
|
+
Virtus: without values
|
45
|
+
10151.0 (±5.5%) i/s - 10776 in 1.065475s
|
46
|
+
Virtus: integer values for integer attributes
|
47
|
+
21104.7 (±10.4%) i/s - 21230 in 1.019115s
|
48
|
+
Virtus: string values for integer attributes
|
49
|
+
3195.6 (±1.7%) i/s - 3366 in 1.053637s
|
50
|
+
|
51
|
+
Comparison:
|
52
|
+
FastAttributes: without values : 1528209.4 i/s
|
53
|
+
FastAttributes: integer values for integer attributes: 88794.2 i/s - 17.21x slower
|
54
|
+
FastAttributes: string values for integer attributes : 77673.3 i/s - 19.67x slower
|
55
|
+
Virtus: integer values for integer attributes : 21104.7 i/s - 72.41x slower
|
56
|
+
Attrio: integer values for integer attributes : 11932.2 i/s - 128.07x slower
|
57
|
+
Attrio: string values for integer attributes : 11007.2 i/s - 138.84x slower
|
58
|
+
Virtus: without values : 10151.0 i/s - 150.55x slower
|
59
|
+
Attrio: without values : 7164.3 i/s - 213.31x slower
|
60
|
+
Virtus: string values for integer attributes : 3195.6 i/s - 478.22x slower
|
61
|
+
```
|
4
62
|
|
5
63
|
## Installation
|
6
64
|
|
data/benchmarks/Gemfile
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'benchmark/ips'
|
2
|
+
require 'fast_attributes'
|
3
|
+
require 'virtus'
|
4
|
+
require 'attrio'
|
5
|
+
|
6
|
+
ATTR_NAMES = [:attr0, :attr1, :attr2, :attr3, :attr4, :attr5, :attr6, :attr7, :attr8, :attr9]
|
7
|
+
|
8
|
+
module Initializer
|
9
|
+
def initialize(attributes = {})
|
10
|
+
attributes.each do |attribute, value|
|
11
|
+
public_send("#{attribute}=", value)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class FastIntegers
|
17
|
+
extend FastAttributes
|
18
|
+
include Initializer
|
19
|
+
attribute *ATTR_NAMES, Integer
|
20
|
+
end
|
21
|
+
|
22
|
+
class AttrioIntegers
|
23
|
+
include Attrio
|
24
|
+
include Initializer
|
25
|
+
define_attributes do
|
26
|
+
ATTR_NAMES.each do |name|
|
27
|
+
attr name, Integer
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
class VirtusIntegers
|
33
|
+
include Virtus.model
|
34
|
+
ATTR_NAMES.each do |name|
|
35
|
+
attribute name, Integer
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
Benchmark.ips do |x|
|
40
|
+
x.config(time: 1, warmup: 1)
|
41
|
+
|
42
|
+
integers = {attr0: 0, attr1: 1, attr2: 2, attr3: 3, attr4: 4, attr5: 5, attr6: 6, attr7: 7, attr8: 8, attr9: 9}
|
43
|
+
strings = {attr0: '0', attr1: '1', attr2: '2', attr3: '3', attr4: '4', attr5: '5', attr6: '6', attr7: '7', attr8: '8', attr9: '9'}
|
44
|
+
|
45
|
+
x.report('FastAttributes: without values ') { FastIntegers.new }
|
46
|
+
x.report('FastAttributes: integer values for integer attributes') { FastIntegers.new(integers) }
|
47
|
+
x.report('FastAttributes: string values for integer attributes ') { FastIntegers.new(strings) }
|
48
|
+
|
49
|
+
x.report('Attrio: without values ') { AttrioIntegers.new }
|
50
|
+
x.report('Attrio: integer values for integer attributes ') { AttrioIntegers.new(integers) }
|
51
|
+
x.report('Attrio: string values for integer attributes ') { AttrioIntegers.new(strings) }
|
52
|
+
|
53
|
+
x.report('Virtus: without values ') { VirtusIntegers.new }
|
54
|
+
x.report('Virtus: integer values for integer attributes ') { VirtusIntegers.new(integers) }
|
55
|
+
x.report('Virtus: string values for integer attributes ') { VirtusIntegers.new(strings) }
|
56
|
+
|
57
|
+
x.compare!
|
58
|
+
end
|
data/fast_attributes.gemspec
CHANGED
@@ -18,6 +18,8 @@ Gem::Specification.new do |spec|
|
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
|
-
spec.add_development_dependency 'bundler',
|
21
|
+
spec.add_development_dependency 'bundler', '~> 1.5'
|
22
22
|
spec.add_development_dependency 'rake'
|
23
|
+
spec.add_development_dependency 'rspec', '~> 3.0.0'
|
24
|
+
spec.add_development_dependency 'coveralls', '~> 0.7.0'
|
23
25
|
end
|
data/lib/fast_attributes.rb
CHANGED
@@ -6,21 +6,15 @@ module FastAttributes
|
|
6
6
|
@type_casting ||= {
|
7
7
|
'String' => 'String(%s)',
|
8
8
|
'Integer' => 'Integer(%s)',
|
9
|
+
'Array' => 'Array(%s)',
|
9
10
|
'Date' => 'Date.parse(%s)',
|
10
11
|
'Time' => 'Time.parse(%s)',
|
11
|
-
'DateTime' => 'DateTime.parse(%s)'
|
12
|
-
'Array' => 'Array(%s)'
|
12
|
+
'DateTime' => 'DateTime.parse(%s)'
|
13
13
|
}
|
14
14
|
end
|
15
15
|
|
16
|
-
def default_type_casting
|
17
|
-
'%s'
|
18
|
-
end
|
19
|
-
|
20
16
|
def get_type_casting(klass)
|
21
|
-
@type_casting
|
22
|
-
default_type_casting
|
23
|
-
end
|
17
|
+
@type_casting[type_from_class(klass)]
|
24
18
|
end
|
25
19
|
|
26
20
|
def add_type_casting(klass, casting)
|
@@ -41,11 +35,15 @@ module FastAttributes
|
|
41
35
|
end
|
42
36
|
|
43
37
|
def attribute(*attributes, klass)
|
38
|
+
unless FastAttributes.type_exists?(klass)
|
39
|
+
raise %(Unsupported attribute type "#{FastAttributes.type_from_class(klass)}")
|
40
|
+
end
|
41
|
+
|
44
42
|
@fast_attributes ||= []
|
45
43
|
attributes.each do |attribute|
|
46
44
|
@fast_attributes << attribute
|
47
45
|
|
48
|
-
type_matching =
|
46
|
+
type_matching = "when #{FastAttributes.type_from_class(klass)} then value"
|
49
47
|
type_casting = FastAttributes.get_type_casting(klass) % 'value'
|
50
48
|
all_attributes = @fast_attributes.map do |attr|
|
51
49
|
"'#{attr}'=>@#{attr}"
|
@@ -0,0 +1,198 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe FastAttributes do
|
4
|
+
describe '.type_casting' do
|
5
|
+
it 'returns predefined type casting rules' do
|
6
|
+
expect(FastAttributes.type_casting).to eq({
|
7
|
+
'String' => 'String(%s)',
|
8
|
+
'Integer' => 'Integer(%s)',
|
9
|
+
'Array' => 'Array(%s)',
|
10
|
+
'Date' => 'Date.parse(%s)',
|
11
|
+
'Time' => 'Time.parse(%s)',
|
12
|
+
'DateTime' => 'DateTime.parse(%s)'
|
13
|
+
})
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe '.get_type_casting' do
|
18
|
+
it 'returns type casting function' do
|
19
|
+
expect(FastAttributes.get_type_casting(String)).to eq('String(%s)')
|
20
|
+
expect(FastAttributes.get_type_casting(Time)).to eq('Time.parse(%s)')
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe '.add_type_casting' do
|
25
|
+
after do
|
26
|
+
FastAttributes.remove_type_casting(OpenStruct)
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'adds type to supported type casting list' do
|
30
|
+
FastAttributes.add_type_casting(OpenStruct, 'OpenStruct.new(a: %s)')
|
31
|
+
expect(FastAttributes.get_type_casting(OpenStruct)).to eq('OpenStruct.new(a: %s)')
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe '.remove_type_casting' do
|
36
|
+
before do
|
37
|
+
FastAttributes.add_type_casting(OpenStruct, 'OpenStruct.new(a: %s)')
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'removes type casting function from supported list' do
|
41
|
+
FastAttributes.remove_type_casting(OpenStruct)
|
42
|
+
expect(FastAttributes.get_type_casting(OpenStruct)).to be(nil)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe '.type_exists?' do
|
47
|
+
it 'checks if type is registered' do
|
48
|
+
expect(FastAttributes.type_exists?(DateTime)).to be(true)
|
49
|
+
expect(FastAttributes.type_exists?(OpenStruct)).to be(false)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
describe '.type_from_class' do
|
54
|
+
it 'converts class into type name' do
|
55
|
+
expect(FastAttributes.type_from_class(DateTime)).to eq('DateTime')
|
56
|
+
expect(FastAttributes.type_from_class(OpenStruct)).to eq('OpenStruct')
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
describe '#attribute' do
|
61
|
+
it 'generates getter methods' do
|
62
|
+
book = Book.new
|
63
|
+
expect(book.respond_to?(:title)).to be(true)
|
64
|
+
expect(book.respond_to?(:name)).to be(true)
|
65
|
+
expect(book.respond_to?(:pages)).to be(true)
|
66
|
+
expect(book.respond_to?(:authors)).to be(true)
|
67
|
+
expect(book.respond_to?(:published)).to be(true)
|
68
|
+
expect(book.respond_to?(:sold)).to be(true)
|
69
|
+
expect(book.respond_to?(:finished)).to be(true)
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'generates setter methods' do
|
73
|
+
book = Book.new
|
74
|
+
expect(book.respond_to?(:title=)).to be(true)
|
75
|
+
expect(book.respond_to?(:name=)).to be(true)
|
76
|
+
expect(book.respond_to?(:pages=)).to be(true)
|
77
|
+
expect(book.respond_to?(:authors=)).to be(true)
|
78
|
+
expect(book.respond_to?(:published=)).to be(true)
|
79
|
+
expect(book.respond_to?(:sold=)).to be(true)
|
80
|
+
expect(book.respond_to?(:finished=)).to be(true)
|
81
|
+
end
|
82
|
+
|
83
|
+
it 'generates attributes method' do
|
84
|
+
book = Book.new
|
85
|
+
expect(book.respond_to?(:attributes)).to be(true)
|
86
|
+
end
|
87
|
+
|
88
|
+
it 'setter methods convert values to correct datatype' do
|
89
|
+
book = Book.new
|
90
|
+
book.title = 123
|
91
|
+
book.name = 456
|
92
|
+
book.pages = '250'
|
93
|
+
book.authors = 'Jobs'
|
94
|
+
book.published = '2014-06-21'
|
95
|
+
book.sold = '2014-06-21 20:45:15'
|
96
|
+
book.finished = '2014-05-20 21:35:20'
|
97
|
+
|
98
|
+
expect(book.title).to eq('123')
|
99
|
+
expect(book.name).to eq('456')
|
100
|
+
expect(book.pages).to be(250)
|
101
|
+
expect(book.authors).to eq(%w[Jobs])
|
102
|
+
expect(book.published).to eq(Date.new(2014, 6, 21))
|
103
|
+
expect(book.sold).to eq(Time.new(2014, 6, 21, 20, 45, 15))
|
104
|
+
expect(book.finished).to eq(DateTime.new(2014, 5, 20, 21, 35, 20))
|
105
|
+
end
|
106
|
+
|
107
|
+
it 'setter methods accept values which are already in a proper type' do
|
108
|
+
book = Book.new
|
109
|
+
book.title = title = 'One'
|
110
|
+
book.name = name = 'Two'
|
111
|
+
book.pages = pages = 250
|
112
|
+
book.authors = authors = %w[Jobs]
|
113
|
+
book.published = published = Date.new(2014, 06, 21)
|
114
|
+
book.sold = sold = Time.new(2014, 6, 21, 20, 45, 15)
|
115
|
+
book.finished = finished = DateTime.new(2014, 05, 20, 21, 35, 20)
|
116
|
+
|
117
|
+
expect(book.title).to be(title)
|
118
|
+
expect(book.name).to be(name)
|
119
|
+
expect(book.pages).to be(pages)
|
120
|
+
expect(book.authors).to be(authors)
|
121
|
+
expect(book.published).to be(published)
|
122
|
+
expect(book.sold).to be(sold)
|
123
|
+
expect(book.finished).to be(finished)
|
124
|
+
end
|
125
|
+
|
126
|
+
it 'setter methods accept nil values' do
|
127
|
+
book = Book.new
|
128
|
+
book.title = 'One'
|
129
|
+
book.name = 'Two'
|
130
|
+
book.pages = 250
|
131
|
+
book.authors = %w[Jobs]
|
132
|
+
book.published = Date.new(2014, 06, 21)
|
133
|
+
book.sold = Time.new(2014, 6, 21, 20, 45, 15)
|
134
|
+
book.finished = DateTime.new(2014, 05, 20, 21, 35, 20)
|
135
|
+
|
136
|
+
book.title = nil
|
137
|
+
book.name = nil
|
138
|
+
book.pages = nil
|
139
|
+
book.authors = nil
|
140
|
+
book.published = nil
|
141
|
+
book.sold = nil
|
142
|
+
book.finished = nil
|
143
|
+
|
144
|
+
expect(book.title).to be(nil)
|
145
|
+
expect(book.name).to be(nil)
|
146
|
+
expect(book.pages).to be(nil)
|
147
|
+
expect(book.authors).to be(nil)
|
148
|
+
expect(book.published).to be(nil)
|
149
|
+
expect(book.sold).to be(nil)
|
150
|
+
expect(book.finished).to be(nil)
|
151
|
+
end
|
152
|
+
|
153
|
+
it 'setter methods raise an exception when cannot parse values' do
|
154
|
+
book = Book.new
|
155
|
+
|
156
|
+
expect{ book.title = BasicObject.new }.to raise_error(TypeError)
|
157
|
+
expect{ book.name = BasicObject.new }.to raise_error(TypeError)
|
158
|
+
expect{ book.pages = 'number' }.to raise_error(ArgumentError)
|
159
|
+
expect{ book.published = 'date' }.to raise_error(ArgumentError)
|
160
|
+
expect{ book.sold = 'time' }.to raise_error(ArgumentError)
|
161
|
+
expect{ book.finished = 'datetime' }.to raise_error(ArgumentError)
|
162
|
+
end
|
163
|
+
|
164
|
+
it 'attributes method return all attributes with nil values by default' do
|
165
|
+
book = Book.new
|
166
|
+
expect(book.attributes).to eq({
|
167
|
+
'title' => nil,
|
168
|
+
'name' => nil,
|
169
|
+
'pages' => nil,
|
170
|
+
'authors' => nil,
|
171
|
+
'published' => nil,
|
172
|
+
'sold' => nil,
|
173
|
+
'finished' => nil,
|
174
|
+
})
|
175
|
+
end
|
176
|
+
|
177
|
+
it 'attributes method return all attributes with their values' do
|
178
|
+
book = Book.new
|
179
|
+
book.title = 'One'
|
180
|
+
book.name = 'Two'
|
181
|
+
book.pages = 250
|
182
|
+
book.authors = %w[Jobs]
|
183
|
+
book.published = Date.new(2014, 06, 21)
|
184
|
+
book.sold = Time.new(2014, 6, 21, 20, 45, 15)
|
185
|
+
book.finished = DateTime.new(2014, 05, 20, 21, 35, 20)
|
186
|
+
|
187
|
+
expect(book.attributes).to eq({
|
188
|
+
'title' => 'One',
|
189
|
+
'name' => 'Two',
|
190
|
+
'pages' => 250,
|
191
|
+
'authors' => %w[Jobs],
|
192
|
+
'published' => Date.new(2014, 06, 21),
|
193
|
+
'sold' => Time.new(2014, 6, 21, 20, 45, 15),
|
194
|
+
'finished' => DateTime.new(2014, 05, 20, 21, 35, 20),
|
195
|
+
})
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
CHANGED
@@ -1,43 +1,71 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fast_attributes
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kostiantyn Stepaniuk
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-06-
|
11
|
+
date: 2014-06-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - ~>
|
17
|
+
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '1.5'
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - ~>
|
24
|
+
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '1.5'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rake
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- -
|
31
|
+
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '0'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- -
|
38
|
+
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
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: 3.0.0
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 3.0.0
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: coveralls
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 0.7.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.7.0
|
41
69
|
description: Fast attributes with data types
|
42
70
|
email:
|
43
71
|
- ks@applift.com
|
@@ -45,15 +73,23 @@ executables: []
|
|
45
73
|
extensions: []
|
46
74
|
extra_rdoc_files: []
|
47
75
|
files:
|
48
|
-
- .
|
76
|
+
- ".coveralls.yml"
|
77
|
+
- ".gitignore"
|
78
|
+
- ".rspec"
|
79
|
+
- ".travis.yml"
|
49
80
|
- CHANGELOG.md
|
50
81
|
- Gemfile
|
51
82
|
- LICENSE.txt
|
52
83
|
- README.md
|
53
84
|
- Rakefile
|
85
|
+
- benchmarks/Gemfile
|
86
|
+
- benchmarks/comparison.rb
|
54
87
|
- fast_attributes.gemspec
|
55
88
|
- lib/fast_attributes.rb
|
56
89
|
- lib/fast_attributes/version.rb
|
90
|
+
- spec/fast_attributes_spec.rb
|
91
|
+
- spec/fixtures/book.rb
|
92
|
+
- spec/spec_helper.rb
|
57
93
|
homepage: https://github.com/applift/fast_attributes
|
58
94
|
licenses:
|
59
95
|
- MIT
|
@@ -64,18 +100,21 @@ require_paths:
|
|
64
100
|
- lib
|
65
101
|
required_ruby_version: !ruby/object:Gem::Requirement
|
66
102
|
requirements:
|
67
|
-
- -
|
103
|
+
- - ">="
|
68
104
|
- !ruby/object:Gem::Version
|
69
105
|
version: '0'
|
70
106
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
71
107
|
requirements:
|
72
|
-
- -
|
108
|
+
- - ">="
|
73
109
|
- !ruby/object:Gem::Version
|
74
110
|
version: '0'
|
75
111
|
requirements: []
|
76
112
|
rubyforge_project:
|
77
|
-
rubygems_version: 2.
|
113
|
+
rubygems_version: 2.2.2
|
78
114
|
signing_key:
|
79
115
|
specification_version: 4
|
80
116
|
summary: Fast attributes with data types
|
81
|
-
test_files:
|
117
|
+
test_files:
|
118
|
+
- spec/fast_attributes_spec.rb
|
119
|
+
- spec/fixtures/book.rb
|
120
|
+
- spec/spec_helper.rb
|