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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4c7f1055c9b3373f670d0a951802c291da7e64d3
4
- data.tar.gz: c07c8f114c8dedaa380ff9a17901fa1f6b928f87
3
+ metadata.gz: 77f2e59818faf79d91ebf8f90f76cebc2bab978b
4
+ data.tar.gz: bb9905bc7899f5c2d4d4e69c8f9c42760e28be3e
5
5
  SHA512:
6
- metadata.gz: 1490d8927c991b691150524b0febe8abb69f554bc113d4b19c17318b180a37c724b07ab98be843c0aee452462449b69cfac4852b76eb4353c881b354f4beb2c5
7
- data.tar.gz: 6d27f9bce17691ecd4bfe988598876a27632abe9b24f52b52d2f5d585195e515a1fc572c3dcde75390379cd0a0fb5ea75194f5559977c07f0a56b649a0166491
6
+ metadata.gz: 0c6a59bfb0c1a73be212f8c2f9485186aaf3282d90d09633aac841fffd083645d4c12c9afc144781c38f850aa30362661710d1833886a834b544a9d568ae7410
7
+ data.tar.gz: 009c11fbd431c352d1c8fe72502851a14a1eaeb55c73184c3b2585ccf2db1b6dbdebff910bc27a05cc5e78e503f82398a95d4a719f44ea28600b191aad7bf848
data/.coveralls.yml ADDED
@@ -0,0 +1 @@
1
+ service_name: travis-ci
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format d
data/.travis.yml ADDED
@@ -0,0 +1,2 @@
1
+ language: ruby
2
+ script: bundle exec rspec spec
data/CHANGELOG.md CHANGED
@@ -1,2 +1,5 @@
1
+ **0.1.0 (June 26, 2014)**
2
+ * Support `Integer`, `String`, `Array`, `Date`, `Time` and `DateTime` attribute types
3
+
1
4
  **0.0.1 (June 20, 2014)**
2
5
  * Initial commit
data/README.md CHANGED
@@ -1,6 +1,64 @@
1
1
  # FastAttributes
2
+ [![Gem Version](http://img.shields.io/gem/v/fast_attributes.svg)](http://rubygems.org/gems/fast_attributes)
3
+ [![Build Status](http://img.shields.io/travis/applift/fast_attributes.svg)](https://travis-ci.org/applift/fast_attributes)
4
+ [![Coverage Status](http://img.shields.io/coveralls/applift/fast_attributes.svg)](https://coveralls.io/r/applift/fast_attributes?branch=master)
2
5
 
3
- TODO: Write a gem description
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
 
@@ -0,0 +1,8 @@
1
+ source 'https://rubygems.org'
2
+
3
+ ruby '2.1.2'
4
+
5
+ gem 'fast_attributes', '0.0.1'
6
+ gem 'virtus', '1.0.2'
7
+ gem 'attrio', '0.7.3'
8
+ gem 'benchmark-ips', '2.0.0'
@@ -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
@@ -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', '~> 1.5'
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
@@ -1,3 +1,3 @@
1
1
  module FastAttributes
2
- VERSION = '0.0.1'
2
+ VERSION = '0.1.0'
3
3
  end
@@ -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.fetch(type_from_class(klass)) do
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 = FastAttributes.type_exists?(klass) ? "when #{FastAttributes.type_from_class(klass)} then value" : nil
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
@@ -0,0 +1,10 @@
1
+ class Book
2
+ extend FastAttributes
3
+
4
+ attribute :title, :name, String
5
+ attribute :pages, Integer
6
+ attribute :authors, Array
7
+ attribute :published, Date
8
+ attribute :sold, Time
9
+ attribute :finished, DateTime
10
+ end
@@ -0,0 +1,8 @@
1
+ require 'coveralls'
2
+ Coveralls.wear!
3
+
4
+ require 'fast_attributes'
5
+ require 'ostruct'
6
+ require 'date'
7
+ require 'time'
8
+ require 'fixtures/book'
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.1
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-20 00:00:00.000000000 Z
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
- - .gitignore
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.0.3
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