fast_attributes 0.7.0 → 0.8.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: 714fe623705696e372c8b188c47dd28e59a79462
4
- data.tar.gz: 36390f23832e5c3c2253a0f2f54628254fb9faa6
3
+ metadata.gz: 9c90efa52db1c0c48916b37d6229a101e99e32fb
4
+ data.tar.gz: dfd651948c3f0700ccfb4d421fb1ad47009da8df
5
5
  SHA512:
6
- metadata.gz: 758076d95b01e4b721ccfe1674708514584024ce84f94e37fcaf9eb09019c4851ee5b2ba3ea8dbe3dca8ea4119e9a31806252e2cef6f1e6db011d7d4fd91f797
7
- data.tar.gz: c433c6a45235e96011f55b6314abc087038d1872d8a6f08ac1159d1282f651d53139b351c6622115f0f346adf8183b61e3c66301bce1878cb91be49744aaaa79
6
+ metadata.gz: b2eec805647af281fa932263b04cbbdcb3aff1f6d7e564e9a48ec5480f064e59258e493d4be24685e3f104ffa1e8ac19dc6bf972386c838b7b86bbad4105cdb8
7
+ data.tar.gz: 60c51d7ccba9ca05ca50852bc3943d90b0081131a7756446d91de9b454bfa7f0c1bf438cef4c7a0eac1b49cb11eddb53c0995e5dff4c4091578fcdcee56f9e74
data/.travis.yml CHANGED
@@ -1,6 +1,6 @@
1
1
  language: ruby
2
2
  script: bundle exec rspec spec
3
3
  rvm:
4
- - 1.9.3
5
4
  - 2.0.0
6
5
  - 2.1.1
6
+ - 2.2.5
data/CHANGELOG.md CHANGED
@@ -1,3 +1,16 @@
1
+ **0.8.0 (September 15, 2016)**
2
+ * Support of default values [Phil Schalm](https://github.com/pnomolos)
3
+ ```ruby
4
+ class Product
5
+ extend FastAttributes
6
+
7
+ define_attributes initialize: true, attributes: true do
8
+ attribute :title, String, default: "Book"
9
+ attribute :price, Float, default: 10
10
+ end
11
+ end
12
+ ```
13
+
1
14
  **0.7.0 (August 31, 2014)**
2
15
  * Support `boolean` data type as a lenient type.
3
16
  ```ruby
data/README.md CHANGED
@@ -107,6 +107,25 @@ book.attributes
107
107
  "finished"=>
108
108
  #<DateTime: 1937-08-20T12:35:00+00:00 ((2428766j,45300s,0n),+0s,2299161j)>}
109
109
  ```
110
+
111
+ ## Default values
112
+
113
+ Requires `define_attributes` to be used with `initialize: true` (this is where the default values are set):
114
+
115
+ ```ruby
116
+ class Book
117
+ extend FastAttributes
118
+
119
+ define_attributes initialize: true do
120
+ attribute :author, String, default: "Some String"
121
+ end
122
+ end
123
+
124
+ book = Book.new
125
+ book.attributes
126
+ {"author" => "Some String"}
127
+ ```
128
+
110
129
  ## Custom Type
111
130
  It's easy to add a custom attribute type.
112
131
  ```ruby
@@ -123,7 +142,7 @@ book.author
123
142
  # => #<OpenStruct name="Rowling">
124
143
  ```
125
144
 
126
- Notice, that second parameter is a string. It's necessary because this code is compiled into a ruby method in runtime. The placeholder `%s` represents a value which this method accepts.
145
+ Notice, that second parameter is a string. It's necessary because this code is compiled into a ruby method in runtime. The placeholder `%s` represents a value which this method accepts.
127
146
 
128
147
  It's possible to refer to a placeholder several times.
129
148
  ```ruby
@@ -183,7 +202,7 @@ FastAttributes.type_cast String do # begin
183
202
  # case String
184
203
  from 'nil', to: 'nil' # when nil then nil
185
204
  from 'String', to: '%s' # when String then %s
186
- otherwise 'String(%s)' # else String(%s)
205
+ otherwise 'String(%s)' # else String(%s)
187
206
  # end
188
207
  on_error 'TypeError', act: 'nil' # rescue TypeError => e
189
208
  # nil
@@ -210,7 +229,7 @@ end
210
229
  order = Order.new
211
230
  order.terms_of_service = 'yes'
212
231
  order.terms_of_service
213
- # => true
232
+ # => true
214
233
  order.terms_of_service = 'no'
215
234
  order.terms_of_service
216
235
  # => false
@@ -4,6 +4,7 @@ require 'time'
4
4
  require 'fast_attributes/version'
5
5
  require 'fast_attributes/builder'
6
6
  require 'fast_attributes/type_cast'
7
+ require 'fast_attributes/default_attributes'
7
8
 
8
9
  module FastAttributes
9
10
  TRUE_VALUES = {true => nil, 1 => nil, '1' => nil, 't' => nil, 'T' => nil, 'true' => nil, 'TRUE' => nil, 'on' => nil, 'ON' => nil}
@@ -10,17 +10,24 @@ module FastAttributes
10
10
  @methods = Module.new
11
11
  end
12
12
 
13
- def attribute(*attributes, type)
13
+ def attribute(*attributes, type, options)
14
+ unless options.is_a?(Hash)
15
+ (attributes ||= []) << type
16
+ type = options
17
+ options = {}
18
+ end
19
+
14
20
  unless FastAttributes.type_exists?(type)
15
21
  raise UnsupportedTypeError, %(Unsupported attribute type "#{type.inspect}")
16
22
  end
17
23
 
18
- @attributes << [attributes, type]
24
+ @attributes << [attributes, type, options || {}]
19
25
  end
20
26
 
21
27
  def compile!
22
28
  compile_getter
23
29
  compile_setter
30
+ set_defaults
24
31
 
25
32
  if @options[:initialize]
26
33
  compile_initialize
@@ -36,17 +43,17 @@ module FastAttributes
36
43
  private
37
44
 
38
45
  def compile_getter
39
- each_attribute do |attribute, _|
46
+ each_attribute do |attribute, *|
40
47
  @methods.module_eval <<-EOS, __FILE__, __LINE__ + 1
41
- def #{attribute} # def name
42
- @#{attribute} # @name
43
- end # end
48
+ def #{attribute} # def name
49
+ @#{attribute} # @name
50
+ end # end
44
51
  EOS
45
52
  end
46
53
  end
47
54
 
48
55
  def compile_setter
49
- each_attribute do |attribute, type|
56
+ each_attribute do |attribute, type, *|
50
57
  type_cast = FastAttributes.get_type_casting(type)
51
58
  method_body = type_cast.compile_method_body(attribute, 'value')
52
59
 
@@ -59,9 +66,15 @@ module FastAttributes
59
66
  end
60
67
 
61
68
  def compile_initialize
69
+ attribute_string = if FastAttributes.default_attributes(@klass).empty?
70
+ "attributes"
71
+ else
72
+ "FastAttributes.default_attributes(self.class).merge(attributes)"
73
+ end
74
+
62
75
  @methods.module_eval <<-EOS, __FILE__, __LINE__ + 1
63
76
  def initialize(attributes = {})
64
- attributes.each do |name, value|
77
+ #{attribute_string}.each do |name, value|
65
78
  public_send("\#{name}=", value)
66
79
  end
67
80
  end
@@ -90,10 +103,16 @@ module FastAttributes
90
103
  @klass.send(:include, @methods)
91
104
  end
92
105
 
106
+ def set_defaults
107
+ each_attribute do |attribute, type, options|
108
+ FastAttributes.add_default_attribute(@klass, attribute, options[:default]) if options[:default]
109
+ end
110
+ end
111
+
93
112
  def each_attribute
94
- @attributes.each do |attributes, type|
113
+ @attributes.each do |attributes, type, options = {}|
95
114
  attributes.each do |attribute|
96
- yield attribute, type
115
+ yield attribute, type, options
97
116
  end
98
117
  end
99
118
  end
@@ -0,0 +1,33 @@
1
+ module FastAttributes
2
+ class << self
3
+ SINGLETON_CLASSES = [::NilClass, ::TrueClass, ::FalseClass, ::Numeric, ::Symbol].freeze
4
+
5
+ def default_attributes(klass)
6
+ return {} unless (@default_attributes || {})[klass]
7
+ @default_attributes[klass].each_with_object({}) do |(attribute, value), memo|
8
+ memo[attribute] = if value.respond_to?(:call)
9
+ value.call
10
+ elsif cloneable?(value)
11
+ value.clone
12
+ else
13
+ value
14
+ end
15
+ end
16
+ end
17
+
18
+ def add_default_attribute(klass, attribute, value)
19
+ @default_attributes ||= {}
20
+ @default_attributes[klass] ||= {}
21
+ @default_attributes[klass][attribute] = value
22
+ end
23
+
24
+ def cloneable?(value)
25
+ case value
26
+ when *SINGLETON_CLASSES
27
+ false
28
+ else
29
+ true
30
+ end
31
+ end
32
+ end
33
+ end
@@ -1,3 +1,3 @@
1
1
  module FastAttributes
2
- VERSION = '0.7.0'
2
+ VERSION = '0.8.0'
3
3
  end
@@ -364,4 +364,37 @@ describe FastAttributes do
364
364
  end
365
365
  end
366
366
  end
367
+
368
+ describe "default attributes" do
369
+ it "sets the default values" do
370
+ class_with_defaults = ClassWithDefaults.new
371
+
372
+ expect(class_with_defaults.title).to eq('a title')
373
+ expect(class_with_defaults.pages).to be(10)
374
+ expect(class_with_defaults.authors).to eq([1, 2, 4])
375
+ end
376
+
377
+ it "allows you to override default values" do
378
+ class_with_defaults = ClassWithDefaults.new(title: 'Something', authors: [1, 5, 7])
379
+
380
+ expect(class_with_defaults.title).to eq('Something')
381
+ expect(class_with_defaults.pages).to be(10)
382
+ expect(class_with_defaults.authors).to eq([1, 5, 7])
383
+ end
384
+
385
+ it "allows callable default values" do
386
+ class_with_defaults = ClassWithDefaults.new
387
+
388
+ expect(class_with_defaults.callable).to eq("callable value")
389
+ end
390
+
391
+ it "doesn't use the same instance between multiple instances" do
392
+ class_with_defaults = ClassWithDefaults.new
393
+ class_with_defaults.authors << 2
394
+
395
+ class_with_defaults2 = ClassWithDefaults.new
396
+
397
+ expect(class_with_defaults2.authors).to eq([1, 2, 4])
398
+ end
399
+ end
367
400
  end
@@ -113,3 +113,14 @@ class DefaultLenientAttributes
113
113
  attribute :rate, :float
114
114
  attribute :active, :boolean
115
115
  end
116
+
117
+ class ClassWithDefaults
118
+ extend FastAttributes
119
+
120
+ define_attributes initialize: true, attributes: true do
121
+ attribute :title, String, default: "a title"
122
+ attribute :pages, Integer, default: 10
123
+ attribute :authors, Array, default: [1, 2, 4]
124
+ attribute :callable, String, default: lambda { "callable value" }
125
+ end
126
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fast_attributes
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0
4
+ version: 0.8.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-08-31 00:00:00.000000000 Z
11
+ date: 2016-09-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -101,6 +101,7 @@ files:
101
101
  - fast_attributes.gemspec
102
102
  - lib/fast_attributes.rb
103
103
  - lib/fast_attributes/builder.rb
104
+ - lib/fast_attributes/default_attributes.rb
104
105
  - lib/fast_attributes/type_cast.rb
105
106
  - lib/fast_attributes/version.rb
106
107
  - spec/fast_attributes/type_cast_spec.rb