fast_attributes 0.7.0 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
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