u-attributes 2.2.0 → 2.3.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
  SHA256:
3
- metadata.gz: 31b9f3d0195fc8b0f865279a79a54bd9beb8b0644d3f1b4371b6aa4163264024
4
- data.tar.gz: '048e8c549d655980eee398e8ae445a7eb6900143f98c8e04449d5e2c82f0c9e6'
3
+ metadata.gz: 2f90839cb67a0501e1ef44a5f06a324103063c87e929549377f885504bda5d8a
4
+ data.tar.gz: fd77058f7e514644a8363d460ad33ad76885648e32b5d9b02e22e592ffbf3ffe
5
5
  SHA512:
6
- metadata.gz: 3a776e02b0708d566156ce8adc7d0ad5813a7c752f8f19615eeea734b46ee34995d69a8cab263ed1e1ffbba64140eee4a630ff18fdcb6cf54cd5fb0a404d6fe8
7
- data.tar.gz: 4e7869905c50b2f0ea288f404900c3c2b645ca3c8cad6404c2d8aa8913a0ad87874b43288c8f408e1a23252d9ab114fa8664a6a21914f71c2ffbf4ee04bb3d68
6
+ metadata.gz: 27401e952c4f5611ec5443df546d4c2c67f0af7aa40606a8e0f128ae37dc167747d0ba4c94008d993d65c886d4e1d66c6ef3472556ecfa353903779f51b4fe23
7
+ data.tar.gz: d05025bd7442681e14fa8f970fb166898ec9af4a344b8912e10c57f559830833bebe05ccacea85332ef9c88437adabc60152967f8b0b38d01f38f1cc6a7c1257
data/README.md CHANGED
@@ -47,6 +47,15 @@ So, if you change [[1](#with_attribute)] [[2](#with_attributes)] some object att
47
47
  - [Is it possible to inherit the attributes?](#is-it-possible-to-inherit-the-attributes)
48
48
  - [`.attribute!()`](#attribute)
49
49
  - [How to query the attributes?](#how-to-query-the-attributes)
50
+ - [`.attributes`](#attributes)
51
+ - [`.attribute?()`](#attribute-1)
52
+ - [`#attribute?()`](#attribute-2)
53
+ - [`#attributes()`](#attributes-1)
54
+ - [`#attributes(keys_as:)`](#attributeskeys_as)
55
+ - [`#attributes(*names)`](#attributesnames)
56
+ - [`#attributes([names])`](#attributesnames-1)
57
+ - [`#attributes(with:, without)`](#attributeswith-without)
58
+ - [`#defined_attributes`](#defined_attributes)
50
59
  - [Built-in extensions](#built-in-extensions)
51
60
  - [Picking specific features](#picking-specific-features)
52
61
  - [`Micro::Attributes.with`](#microattributeswith)
@@ -75,7 +84,7 @@ gem 'u-attributes'
75
84
 
76
85
  | u-attributes | branch | ruby | activemodel |
77
86
  | -------------- | ------- | -------- | ------------- |
78
- | 2.2.0 | main | >= 2.2.0 | >= 3.2, < 6.1 |
87
+ | 2.3.0 | main | >= 2.2.0 | >= 3.2, < 6.1 |
79
88
  | 1.2.0 | v1.x | >= 2.2.0 | >= 3.2, < 6.1 |
80
89
 
81
90
  > **Note**: The activemodel is an optional dependency, this module [can be enabled](#activemodelvalidation-extension) to validate the attributes.
@@ -419,69 +428,152 @@ beta_person.age # 0
419
428
 
420
429
  ## How to query the attributes?
421
430
 
431
+ All of the methods that will be explained can be used with any of the built-in extensions.
432
+
433
+ **PS:** We will use the class below for all of the next examples.
434
+
422
435
  ```ruby
423
436
  class Person
424
437
  include Micro::Attributes
425
438
 
426
439
  attribute :age
427
- attribute :name, default: 'John Doe'
440
+ attribute :first_name, default: 'John'
441
+ attribute :last_name, default: 'Doe'
428
442
 
429
443
  def initialize(options)
430
444
  self.attributes = options
431
445
  end
446
+
447
+ def name
448
+ "#{first_name} #{last_name}"
449
+ end
432
450
  end
451
+ ```
433
452
 
434
- #---------------#
435
- # .attributes() #
436
- #---------------#
453
+ ### `.attributes`
437
454
 
438
- Person.attributes # ['name', 'age']
455
+ Listing all the class attributes.
439
456
 
440
- #---------------#
441
- # .attribute?() #
442
- #---------------#
457
+ ```ruby
458
+ Person.attributes # ["age", "first_name", "last_name"]
459
+ ```
443
460
 
444
- Person.attribute?(:name) # true
445
- Person.attribute?('name') # true
446
- Person.attribute?('foo') # false
447
- Person.attribute?(:foo) # false
461
+ ### `.attribute?()`
448
462
 
449
- # ---
463
+ Checking the existence of some attribute.
450
464
 
451
- person = Person.new(age: 20)
465
+ ```ruby
466
+ Person.attribute?(:first_name) # true
467
+ Person.attribute?('first_name') # true
452
468
 
453
- #---------------------#
454
- # #defined_attributes #
455
- #---------------------#
469
+ Person.attribute?('foo') # false
470
+ Person.attribute?(:foo) # false
471
+ ```
456
472
 
457
- person.defined_attributes # ['name', 'age']
473
+ ### `#attribute?()`
458
474
 
459
- #---------------#
460
- # #attribute?() #
461
- #---------------#
475
+ Checking the existence of some attribute in an instance.
476
+
477
+ ```ruby
478
+ person = Person.new(age: 20)
462
479
 
463
480
  person.attribute?(:name) # true
464
481
  person.attribute?('name') # true
482
+
465
483
  person.attribute?('foo') # false
466
484
  person.attribute?(:foo) # false
485
+ ```
486
+
487
+ ### `#attributes()`
488
+
489
+ Fetching all the attributes with their values.
490
+
491
+ ```ruby
492
+ person1 = Person.new(age: 20)
493
+ person1.attributes # {"age"=>20, "first_name"=>"John", "last_name"=>"Doe"}
494
+
495
+ person2 = Person.new(first_name: 'Rodrigo', last_name: 'Rodrigues')
496
+ person2.attributes # {"age"=>nil, "first_name"=>"Rodrigo", "last_name"=>"Rodrigues"}
497
+ ```
498
+
499
+ #### `#attributes(keys_as:)`
500
+
501
+ Use the `keys_as:` option with `Symbol` or `String` to transform the attributes hash keys.
502
+
503
+ ```ruby
504
+ person1 = Person.new(age: 20)
505
+ person1.attributes(keys_as: Symbol) # {:age=>20, :first_name=>"John", :last_name=>"Doe"}
467
506
 
468
- #---------------#
469
- # #attributes() #
470
- #---------------#
507
+ person2 = Person.new(first_name: 'Rodrigo', last_name: 'Rodrigues')
508
+ person2.attributes(keys_as: String) # {"age"=>nil, "first_name"=>"Rodrigo", "last_name"=>"Rodrigues"}
509
+ ```
471
510
 
472
- person.attributes # {'age'=>20, 'name'=>'John Doe'}
473
- Person.new(name: 'John').attributes # {'age'=>nil, 'name'=>'John'}
511
+ #### `#attributes(*names)`
474
512
 
475
- #---------------------#
476
- # #attributes(*names) #
477
- #---------------------#
513
+ Slices the attributes to include only the given keys (in their types).
478
514
 
479
- # Slices the attributes to include only the given keys.
480
- # Returns a hash containing the given keys (in their types).
515
+ ```ruby
516
+ person = Person.new(age: 20)
517
+
518
+ person.attributes(:age) # {:age => 20}
519
+ person.attributes(:age, :first_name) # {:age => 20, :first_name => "John"}
520
+ person.attributes('age', 'last_name') # {"age" => 20, "last_name" => "Doe"}
521
+
522
+ person.attributes(:age, 'last_name') # {:age => 20, "last_name" => "Doe"}
523
+
524
+ # You could also use the keys_as: option to ensure the same type for all of the hash keys.
525
+
526
+ person.attributes(:age, 'last_name', keys_as: Symbol) # {:age=>20, :last_name=>"Doe"}
527
+ ```
528
+
529
+ #### `#attributes([names])`
530
+
531
+ As the previous example, this methods accepts a list of keys to slice the attributes.
532
+
533
+ ```ruby
534
+ person = Person.new(age: 20)
535
+
536
+ person.attributes([:age]) # {:age => 20}
537
+ person.attributes([:age, :first_name]) # {:age => 20, :first_name => "John"}
538
+ person.attributes(['age', 'last_name']) # {"age" => 20, "last_name" => "Doe"}
539
+
540
+ person.attributes([:age, 'last_name']) # {:age => 20, "last_name" => "Doe"}
541
+
542
+ # You could also use the keys_as: option to ensure the same type for all of the hash keys.
543
+
544
+ person.attributes([:age, 'last_name'], keys_as: Symbol) # {:age=>20, :last_name=>"Doe"}
545
+ ```
546
+
547
+ #### `#attributes(with:, without)`
548
+
549
+ Use the `with:` option to include any method value of the instance inside of the hash, and,
550
+ you can use the `without:` option to exclude one or more attribute keys from the final hash.
551
+
552
+ ```ruby
553
+ person = Person.new(age: 20)
554
+
555
+ person.attributes(without: :age) # {"first_name"=>"John", "last_name"=>"Doe"}
556
+ person.attributes(without: [:age, :last_name]) # {"first_name"=>"John"}
557
+
558
+ person.attributes(with: [:name], without: [:first_name, :last_name]) # {"age"=>20, "name"=>"John Doe"}
559
+
560
+ # To achieves the same output of the previous example, use the attribute names to slice only them.
561
+
562
+ person.attributes(:age, with: [:name]) # {:age=>20, "name"=>"John Doe"}
563
+
564
+ # You could also use the keys_as: option to ensure the same type for all of the hash keys.
565
+
566
+ person.attributes(:age, with: [:name], keys_as: Symbol) # {:age=>20, :name=>"John Doe"}
567
+ ```
568
+
569
+ ### `#defined_attributes`
570
+
571
+ Listing all the available attributes.
572
+
573
+ ```ruby
574
+ person = Person.new(age: 20)
481
575
 
482
- person.attributes(:age) # {age: 20}
483
- person.attributes(:age, :name) # {age: 20, name: 'John Doe'}
484
- person.attributes('age', 'name') # {'age'=>20, 'name'=>'John Doe'}
576
+ person.defined_attributes # ["age", "first_name", "last_name"]
485
577
  ```
486
578
 
487
579
  [⬆️ Back to Top](#table-of-contents-)
@@ -55,16 +55,32 @@ module Micro
55
55
  raise NameError, "undefined attribute `#{name}"
56
56
  end
57
57
 
58
+ def defined_attributes
59
+ @defined_attributes ||= self.class.attributes
60
+ end
61
+
58
62
  def attributes(*names)
59
63
  return __attributes if names.empty?
60
64
 
61
- names.each_with_object({}) do |name, memo|
62
- memo[name] = attribute(name) if attribute?(name)
65
+ options = names.last.is_a?(Hash) ? names.pop : Kind::Empty::HASH
66
+
67
+ names.flatten!
68
+
69
+ without_option = Array(options.fetch(:without, Kind::Empty::ARRAY))
70
+
71
+ keys = names.empty? ? defined_attributes - without_option.map(&:to_s) : names - without_option
72
+
73
+ data = keys.each_with_object({}) { |key, memo| memo[key] = attribute(key) if attribute?(key) }
74
+
75
+ with_option = Array(options.fetch(:with, Kind::Empty::ARRAY))
76
+
77
+ unless with_option.empty?
78
+ extra = with_option.each_with_object({}) { |key, memo| memo[key.to_s] = public_send(key) }
79
+
80
+ data.merge!(extra)
63
81
  end
64
- end
65
82
 
66
- def defined_attributes
67
- @defined_attributes ||= self.class.attributes
83
+ Utils::Hashes.keys_as(options[:keys_as], data)
68
84
  end
69
85
 
70
86
  protected
@@ -12,6 +12,24 @@ module Micro::Attributes
12
12
  hash.each_with_object({}) { |(key, val), memo| memo[key.to_s] = val }
13
13
  end
14
14
 
15
+ def self.symbolize_keys(arg)
16
+ hash = Kind::Of.(::Hash, arg)
17
+
18
+ return hash if hash.empty?
19
+ return hash.transform_keys(&:to_sym) if hash.respond_to?(:transform_keys)
20
+
21
+ hash.each_with_object({}) { |(key, val), memo| memo[key.to_sym] = val }
22
+ end
23
+
24
+ def self.keys_as(type, hash)
25
+ return Kind::Of.(::Hash, hash) unless type
26
+
27
+ return symbolize_keys(hash) if type == Symbol
28
+ return stringify_keys(hash) if type == String
29
+
30
+ raise ArgumentError, 'first argument must be the class String or Symbol'.freeze
31
+ end
32
+
15
33
  def self.get(hash, key)
16
34
  value = hash[key.to_s]
17
35
 
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Micro
4
4
  module Attributes
5
- VERSION = '2.2.0'.freeze
5
+ VERSION = '2.3.0'.freeze
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: 2.2.0
4
+ version: 2.3.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: 2020-09-02 00:00:00.000000000 Z
11
+ date: 2020-09-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: kind