u-attributes 0.9.0 → 0.10.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
  SHA256:
3
- metadata.gz: 63911d6718fe30f139ee9acfb5b4a4577a71c3e01222087a17a4d0f349b31935
4
- data.tar.gz: 8a3a4266c67d1e8eade0d742cf2d057c0bafb2f2e25c26c768f73cea4d40aa97
3
+ metadata.gz: e37bcd7fa7880973930c3a455850708bf22962266c5d2b09f69885dc0c7b9a8d
4
+ data.tar.gz: ed08290e3bca0a590a88a7720deb3c6e94eae93d64a12884eb108806ce2a13ce
5
5
  SHA512:
6
- metadata.gz: 927eb73d0b9cfce21e9d8abe11ab899296a6f45721d7821ea175e0bc58d144015ba22e488f1bdb6be563821a8b4e25a1082eba4c103ceedbed556ded654ab721
7
- data.tar.gz: 85bf3683290458bfb863b215fe5eca4e57e041bb2dd167e1908a629c9081d9c8417584b847b9a775d46658f8069c5d960484a9c7a2be7ffb462eac1104f4b4ca
6
+ metadata.gz: 031f5deb4ece3c5be0004290675a4bbd72e90a8b1436068054dc1acf8d949e7b4957e6b20d4f53112136cd35d15ede29d648576e7b3fe52fe0216e73012afad7
7
+ data.tar.gz: 6191e30d97bdf5cdeb06a5ece5db65877ca14304af432dc8f69077cb691fc0458a4adb1124ebf1acdbdeae4eae2682944770cb1268708680ebafd0062165a38c
@@ -3,5 +3,13 @@ sudo: false
3
3
  language: ruby
4
4
  cache: bundler
5
5
  rvm:
6
- - 2.6.3
7
- before_install: gem install bundler -v 2.0.1
6
+ - 2.2.0
7
+ - 2.3.0
8
+ - 2.4.0
9
+ - 2.5.0
10
+ - 2.6.0
11
+ before_install:
12
+ - gem uninstall -v '>= 2' -i $(rvm gemdir)@global -ax bundler || true
13
+ - gem install bundler -v '< 2'
14
+ env:
15
+ - DISABLE_SIMPLECOV=true
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- u-attributes (0.9.0)
4
+ u-attributes (0.10.0)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # μ-attributes (Micro::Attributes)
1
+ # μ-attributes (Micro::Attributes) [![Build Status](https://travis-ci.com/serradura/u-attributes.svg?branch=master)](https://travis-ci.com/serradura/u-attributes)
2
2
 
3
3
  This gem allows defining read-only attributes, that is, your objects will have only getters to access their attributes data.
4
4
 
@@ -98,9 +98,9 @@ person.attribute(:name) { |value| puts value } # John Doe
98
98
  person.attribute('age') { |value| puts value } # 20
99
99
  person.attribute('foo') { |value| puts value } # !! Nothing happened, because of the attribute not exists.
100
100
 
101
- #--------------#
102
- # #attribute() #
103
- #--------------#
101
+ #---------------#
102
+ # #attribute!() #
103
+ #---------------#
104
104
  #
105
105
  # Works like the #attribute() method, but will raise an exception when the attribute not exist.
106
106
 
@@ -264,6 +264,99 @@ p person.attributes # {"age"=>20, "name"=>"John Doe"}
264
264
  p Person.new(name: 'John').attributes # {"age"=>nil, "name"=>"John"}
265
265
  ```
266
266
 
267
+ ## Built-in extensions
268
+
269
+ You can use the method `Micro::Attributes.features()` to combine and require only the features that better fit your needs.
270
+
271
+ Note: The method `Micro::Attributes.with()` is an alias for `Micro::Attributes.features()`.
272
+
273
+ ### Diff extension
274
+
275
+ Provides a way to track changes in your object attributes.
276
+
277
+ #### How to enable?
278
+
279
+ ```ruby
280
+ #----------------------------------#
281
+ # Via Micro::Attributes.features() #
282
+ #----------------------------------#
283
+ class Job
284
+ include Micro::Attributes.features(:diff)
285
+
286
+ attributes :id, state: 'sleeping'
287
+
288
+ def initialize(options)
289
+ self.options = options
290
+ end
291
+ end
292
+
293
+ # --------------------------------------------------------------------#
294
+ # Using the .with() method alias and adding the initialize extension. #
295
+ # --------------------------------------------------------------------#
296
+
297
+ class Job
298
+ include Micro::Attributes.with(:initialize, :diff)
299
+
300
+ attributes :id, state: 'sleeping'
301
+ end
302
+
303
+ #---------------------------------------#
304
+ # Via Micro::Attributes.to_initialize() #
305
+ #---------------------------------------#
306
+ class Job
307
+ include Micro::Attributes.to_initialize(diff: true)
308
+
309
+ attribute :id
310
+ attribute :state, 'sleeping'
311
+ end
312
+ ```
313
+
314
+ #### Usage
315
+
316
+ ```ruby
317
+ require 'securerandom'
318
+
319
+ class Job
320
+ include Micro::Attributes.features(:initialize, :diff)
321
+
322
+ attributes :id, state: 'sleeping'
323
+ end
324
+
325
+ job = Job.new(id: SecureRandom.uuid())
326
+
327
+ p job.id # A random UUID generated from SecureRandom.uuid(). e.g: "e68bcc74-b91c-45c2-a904-12f1298cc60e"
328
+ p job.state # "sleeping"
329
+
330
+ job_running = job.with_attribute(:state, 'running')
331
+
332
+ p job_running.state # "running"
333
+
334
+ job_changes = job.diff_attributes(job_running)
335
+
336
+ #-----------------------------#
337
+ # #present?, #blank?, #empty? #
338
+ #-----------------------------#
339
+
340
+ p job_changes.present? # true
341
+ p job_changes.blank? # false
342
+ p job_changes.empty? # false
343
+
344
+ #-----------#
345
+ # #changed? #
346
+ #-----------#
347
+ p job_changes.changed? # true
348
+
349
+ p job_changes.changed?(:id) # false
350
+
351
+ p job_changes.changed?(:state) # true
352
+ p job_changes.changed?(:state, from: 'sleeping', to: 'running') # true
353
+
354
+ #----------------#
355
+ # #differences() #
356
+ #----------------#
357
+ p job_changes.differences # {"state"=>"running"}
358
+ ```
359
+
267
360
  ## Development
268
361
 
269
362
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
@@ -3,7 +3,7 @@
3
3
  require "micro/attributes/version"
4
4
  require "micro/attributes/attributes_utils"
5
5
  require "micro/attributes/macros"
6
- require "micro/attributes/to_initialize"
6
+ require "micro/attributes/features"
7
7
 
8
8
  module Micro
9
9
  module Attributes
@@ -22,23 +22,32 @@ module Micro
22
22
  end
23
23
  end
24
24
 
25
- def self.to_initialize
26
- @to_initialize ||= ::Micro::Attributes.const_get(:ToInitialize)
25
+ def self.to_initialize(diff: false)
26
+ options = [:initialize]
27
+ options << :diff if diff
28
+ features(*options)
27
29
  end
28
30
 
31
+ def self.features(*names)
32
+ Features.fetch(names)
33
+ end
34
+ singleton_class.send(:alias_method, :with, :features)
35
+
29
36
  def attributes=(arg)
30
37
  self.class.attributes_data(AttributesUtils.hash_argument!(arg)).each do |name, value|
31
- instance_variable_set("@#{name}", value) if attribute?(name)
38
+ __attributes[name] = instance_variable_set("@#{name}", value) if attribute?(name)
32
39
  end
40
+ __attributes.freeze
33
41
  end
34
42
  protected :attributes=
35
43
 
36
- def attributes
37
- state = self.class.attributes.each_with_object({}) do |name, memo|
38
- memo[name] = public_send(name) if respond_to?(name)
39
- end
44
+ def __attributes
45
+ @__attributes ||= {}
46
+ end
47
+ private :__attributes
40
48
 
41
- self.class.attributes_data(state)
49
+ def attributes
50
+ __attributes
42
51
  end
43
52
 
44
53
  def attribute?(name)
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "micro/attributes/features/diff"
4
+ require "micro/attributes/features/initialize"
5
+
6
+ module Micro
7
+ module Attributes
8
+ module Features
9
+ module InitializeAndDiff
10
+ def self.included(base)
11
+ base.send(:include, ::Micro::Attributes::Features::Initialize)
12
+ base.send(:include, ::Micro::Attributes::Features::Diff)
13
+ end
14
+ end
15
+
16
+ OPTIONS = {
17
+ 'diff' => Diff,
18
+ 'initialize' => Initialize,
19
+ 'diff:initialize' => InitializeAndDiff
20
+ }.freeze
21
+
22
+ private_constant :OPTIONS
23
+
24
+ def self.fetch(names)
25
+ option = OPTIONS[names.map { |name| name.to_s.downcase }.sort.join(':')]
26
+ return option if option
27
+ raise ArgumentError, 'Invalid feature name! Available options: diff, initialize'
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Micro::Attributes
4
+ module Features
5
+ module Diff
6
+ class Changes
7
+ attr_reader :from, :to, :differences
8
+
9
+ def initialize(from:, to:)
10
+ raise ArgumentError, "expected an instance of #{from.class}" unless to.is_a?(from.class)
11
+ @from, @to = from, to
12
+ @differences = diff(from.attributes, to.attributes).freeze
13
+ end
14
+
15
+ def empty?
16
+ @differences.empty?
17
+ end
18
+ alias_method :blank?, :empty?
19
+
20
+ def present?
21
+ !empty?
22
+ end
23
+
24
+ def changed?(name = nil, from: nil, to: nil)
25
+ if name.nil?
26
+ return present? if from.nil? && to.nil?
27
+ raise ArgumentError, 'pass the attribute name with the :from and :to values'
28
+ elsif from.nil? && to.nil?
29
+ differences.has_key?(name.to_s)
30
+ else
31
+ key = name.to_s
32
+ @from_attributes[key] == from && @to_attributes[key] == to
33
+ end
34
+ end
35
+
36
+ private
37
+
38
+ def diff(from_attributes, to_attributes)
39
+ @to_attributes = to_attributes
40
+ @from_attributes = from_attributes
41
+ @from_attributes.each_with_object({}) do |(from_key, from_val), acc|
42
+ to_value = @to_attributes[from_key]
43
+ acc[from_key] = to_value if from_val != to_value
44
+ end
45
+ end
46
+ end
47
+ private_constant :Changes
48
+
49
+ def diff_attributes(to)
50
+ return Changes.new(from: self, to: to) if to.is_a?(::Micro::Attributes)
51
+ raise ArgumentError, "#{to.inspect} must implement Micro::Attributes"
52
+ end
53
+ end
54
+ end
55
+ end
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Micro
4
- module Attributes
5
- module ToInitialize
3
+ module Micro::Attributes
4
+ module Features
5
+ module Initialize
6
6
  def self.included(base)
7
7
  base.send(:include, ::Micro::Attributes)
8
8
  end
@@ -19,7 +19,5 @@ module Micro
19
19
  self.class.new(attributes.merge(arg))
20
20
  end
21
21
  end
22
-
23
- private_constant :ToInitialize
24
22
  end
25
23
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Micro
4
4
  module Attributes
5
- VERSION = "0.9.0"
5
+ VERSION = "0.10.0"
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: u-attributes
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.0
4
+ version: 0.10.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rodrigo Serradura
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-07-08 00:00:00.000000000 Z
11
+ date: 2019-07-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -58,8 +58,10 @@ files:
58
58
  - bin/setup
59
59
  - lib/micro/attributes.rb
60
60
  - lib/micro/attributes/attributes_utils.rb
61
+ - lib/micro/attributes/features.rb
62
+ - lib/micro/attributes/features/diff.rb
63
+ - lib/micro/attributes/features/initialize.rb
61
64
  - lib/micro/attributes/macros.rb
62
- - lib/micro/attributes/to_initialize.rb
63
65
  - lib/micro/attributes/version.rb
64
66
  - lib/u-attributes.rb
65
67
  - u-attributes.gemspec