omg-attrs 0.1.0 → 0.1.1

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: f3eaed4c8a55dca3f9d6e4c6ecd00781116986cc1c81d1105960225bbfb74a85
4
- data.tar.gz: 65c6269712e3e992694866d0c95a96b8d27b3542e78807c7a842cc1bcc4fbc25
3
+ metadata.gz: 46eb3e016278c743e4eef8261a80305e04df785d995a3296ddabc657abd7d1c0
4
+ data.tar.gz: 4ea3a9f88a0b4d606a81bdfa8b1a8834f95af409be473f570388cd202dc2805f
5
5
  SHA512:
6
- metadata.gz: 4c5c5c1d6c2b3fa0604cb1c930f87b3953b62c3679066deca0818e132187cc37579037886f8ff0d1e0daaf4c426d7a0c68de0da2997b4380b41cc7d209754fa2
7
- data.tar.gz: 04c77582e0256724d3ed1dfa090dd398a3b5da7e5c5e0b450b94bf388532ca076fa7f3a03dbf51ddf0e04201e81b9268284a88e6970105d6785ccff4a61b2ea5
6
+ metadata.gz: 521c7d6cf9f04759159669879341e6de02aa9996e05c52492dfeed32d14efb02f896eeb82ab80f6ac67a8fe6672656bad57f265f1d0058ac003b7a4a0cc73be5
7
+ data.tar.gz: 838d9945288f976fd547b7f817672dc391c95875c60d0743bb6022ebaf78c6fe49aa71de33eba721dd2e532d80199cae750a0177e3cc4c26244e7758854e3839
data/lib/attrs.rb CHANGED
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'pry-byebug'
4
+
3
5
  module Attrs
4
6
  def self.included(base)
5
7
  base.include(InstanceMethods)
@@ -7,8 +9,8 @@ module Attrs
7
9
 
8
10
  module InstanceMethods
9
11
  def attrs(*attrs)
10
- return map { |i| i.attrs(*attrs) } if is_list?(self)
11
-
12
+ return list_attrs(attrs) if is_list?
13
+
12
14
  base_attrs, nested_attrs = attrs.partition { |attr| attr.is_a?(Symbol) }
13
15
  nested_attrs.map! do |attr|
14
16
  if attr.is_a?(Hash)
@@ -21,25 +23,42 @@ module Attrs
21
23
  raise ArgumentError, "Invalid attribute: #{attr}"
22
24
  end
23
25
  end
24
-
25
- base_attrs = base_attrs.to_h { |attr| [attr, get(attr)] }
26
+
27
+ base_attrs = base_attrs.to_h do |attr|
28
+ [attr, get(attr)]
29
+ end
26
30
  nested_attrs.reduce(base_attrs, :merge)
27
31
  end
28
32
 
29
33
  private
30
34
 
31
- def nested_attrs(attr)
32
- attr.to_h do |key, value|
33
- records = get(key)
35
+ ##
36
+ # Returns a hash containing attributes on the list and attributes on individual items.
37
+ # @param attrs [Array]
38
+ # @return [Hash]
39
+ def list_attrs(attrs)
40
+ list, nested = attrs.partition { |attr| attr.is_a?(Symbol) && respond_to?(attr) }
41
+ list_attrs = list.empty? ? {} : list.to_h { |key| [key, get(key)] }
42
+ nested_attrs = nested.empty? ? {} : { items: map { |i| i.attrs(*nested) } }
34
43
 
35
- values = is_list?(records) ?
36
- records.map { |record| record.attrs(*value) } :
37
- records.attrs(*value)
44
+ list_attrs.merge(nested_attrs)
45
+ end
38
46
 
39
- [key, values]
47
+ ##
48
+ # Recursively retrieves nested attributes.
49
+ #
50
+ # @param attr [Array | Hash]
51
+ def nested_attrs(attr)
52
+ attr.to_h do |key, value|
53
+ [key, get(key).attrs(*value)]
40
54
  end
41
55
  end
42
56
 
57
+ ##
58
+ # Gets a single attribute for any object. If the object is a hash, it will return the value for the key.
59
+ #
60
+ # @param key [Symbol]
61
+ # @return [Object]
43
62
  def get(key)
44
63
  if respond_to?(key)
45
64
  send(key)
@@ -51,8 +70,11 @@ module Attrs
51
70
  end
52
71
  end
53
72
 
54
- def is_list?(object)
55
- object.is_a?(Enumerable) && !object.is_a?(Hash)
73
+ ##
74
+ # Hacky way of determining if a non-hash object is a list but is not
75
+ # technically an Array or Enumerable (e.g. ActiveRecord::Relation)
76
+ def is_list?
77
+ respond_to?(:each) && !is_a?(Hash)
56
78
  end
57
79
  end
58
80
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: omg-attrs
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matthew Greenfield
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-04-30 00:00:00.000000000 Z
11
+ date: 2024-08-13 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Makes it easy to slice and dice objects and collections of objects
14
14
  email:
@@ -17,18 +17,12 @@ executables: []
17
17
  extensions: []
18
18
  extra_rdoc_files: []
19
19
  files:
20
- - ".rspec"
21
- - ".rubocop.yml"
22
- - README.md
23
- - attrs.gemspec
24
20
  - lib/attrs.rb
25
- - spec/attrs_spec.rb
26
- - spec/spec_helper.rb
27
- homepage: https://github.com/omgreenfield/omg-util/tree/main/attrs
21
+ homepage: https://github.com/omgreenfield/attrs
28
22
  licenses:
29
23
  - MIT
30
24
  metadata:
31
- homepage_uri: https://github.com/omgreenfield/omg-util/tree/main/attrs
25
+ homepage_uri: https://github.com/omgreenfield/attrs
32
26
  rubygems_mfa_required: 'true'
33
27
  post_install_message:
34
28
  rdoc_options: []
@@ -45,7 +39,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
45
39
  - !ruby/object:Gem::Version
46
40
  version: '0'
47
41
  requirements: []
48
- rubygems_version: 3.5.9
42
+ rubygems_version: 3.5.17
49
43
  signing_key:
50
44
  specification_version: 4
51
45
  summary: Allows all objects to call `.attrs` which acts as a recursive `.slice` method
data/.rspec DELETED
@@ -1,3 +0,0 @@
1
- --format documentation
2
- --color
3
- --require spec_helper
data/.rubocop.yml DELETED
@@ -1,13 +0,0 @@
1
- AllCops:
2
- TargetRubyVersion: 2.7.8
3
-
4
- Style/StringLiterals:
5
- Enabled: true
6
- EnforcedStyle: single_quotes
7
-
8
- Style/StringLiteralsInInterpolation:
9
- Enabled: true
10
- EnforcedStyle: single_quotes
11
-
12
- Layout/LineLength:
13
- Max: 120
data/README.md DELETED
@@ -1,45 +0,0 @@
1
- # Attrs
2
-
3
- ## Installation
4
-
5
- ### Testing locally
6
- ```sh
7
- # Build gem
8
- gem build attrs.gemspec
9
-
10
- # Install gem
11
- gem i -l /path/to/this/folder/omg-attrs-0.1.0.gem
12
- ```
13
-
14
- ## Usage
15
-
16
- ```ruby
17
- dad_hash = {
18
- age: 35,
19
- hair_color: 'brown',
20
- children: [
21
- { age: 7, hair_color: 'blonde' },
22
- { age: 3, hair_color: 'brown' }
23
- ],
24
- wife: { age: 35, hair_color: 'brown' }
25
- }
26
-
27
- dad_hash.attrs(:age) # => 35
28
- dad_hash.attrs(wife: :age, children: :hair_color) # =>
29
- # {
30
- # wife: 35,
31
- # children: [
32
- # { hair_color: 'blonde' },
33
- # { hair_color: 'brown' },
34
- # ],
35
- # }
36
- ```
37
-
38
- ## Running tests
39
-
40
- ```ruby
41
- rspec
42
-
43
- # or
44
- bundle exec rspec
45
- ```
data/attrs.gemspec DELETED
@@ -1,26 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- Gem::Specification.new do |spec|
4
- spec.name = 'omg-attrs'
5
- spec.version = '0.1.0'
6
- spec.authors = ['Matthew Greenfield']
7
- spec.email = ['mattgreenfield1@gmail.com']
8
-
9
- spec.summary = 'Allows all objects to call `.attrs` which acts as a recursive `.slice` method'
10
- spec.description = 'Makes it easy to slice and dice objects and collections of objects'
11
-
12
- spec.homepage = 'https://github.com/omgreenfield/omg-util/tree/main/attrs'
13
- spec.license = 'MIT'
14
- spec.required_ruby_version = '>= 2.7.0'
15
-
16
- spec.metadata['homepage_uri'] = spec.homepage
17
- spec.metadata['rubygems_mfa_required'] = 'true'
18
-
19
- spec.files = Dir.chdir(__dir__) do
20
- `git ls-files -z`.split("\x0").reject do |f|
21
- (File.expand_path(f) == __FILE__) ||
22
- f.start_with?(*%w[spec/.git .github Gemfile])
23
- end
24
- end
25
- spec.require_paths = ['lib']
26
- end
data/spec/attrs_spec.rb DELETED
@@ -1,43 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'ostruct'
4
-
5
- RSpec.describe Attrs do
6
- it 'allows recursive slice-like attribute fetching' do
7
- dad_hash = {
8
- age: 35,
9
- hair_color: 'brown',
10
- children: [
11
- { age: 7, hair_color: 'blonde' },
12
- { age: 3, hair_color: 'brown' }
13
- ],
14
- wife: { age: 35, hair_color: 'brown' }
15
- }
16
-
17
- expect(dad_hash.attrs(:age, wife: %i[hair_color age], children: %i[hair_color age])).to eq(
18
- {
19
- age: 35,
20
- wife: { hair_color: 'brown', age: 35 },
21
- children: [
22
- { hair_color: 'blonde', age: 7 },
23
- { hair_color: 'brown', age: 3 },
24
- ],
25
- }
26
- )
27
-
28
- dad_object = OpenStruct.new(dad_hash)
29
- expect(dad_object.attrs(:age, wife: %i[hair_color age], children: %i[hair_color age])).to eq(
30
- {
31
- age: 35,
32
- wife: { hair_color: 'brown', age: 35 },
33
- children: [
34
- { hair_color: 'blonde', age: 7 },
35
- { hair_color: 'brown', age: 3 },
36
- ],
37
- }
38
- )
39
-
40
- children_array = dad_object.children
41
- expect(children_array.attrs(:hair_color, :age)).to eq([{ hair_color: 'blonde', age: 7 }, { hair_color: 'brown', age: 3 }])
42
- end
43
- end
data/spec/spec_helper.rb DELETED
@@ -1,15 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "attrs"
4
-
5
- RSpec.configure do |config|
6
- # Enable flags like --only-failures and --next-failure
7
- config.example_status_persistence_file_path = ".rspec_status"
8
-
9
- # Disable RSpec exposing methods globally on `Module` and `main`
10
- config.disable_monkey_patching!
11
-
12
- config.expect_with :rspec do |c|
13
- c.syntax = :expect
14
- end
15
- end