u-attributes 2.2.0 → 2.3.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: 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