activerecord-pull-alpha 0.1.1 → 0.1.2
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 +4 -4
- data/.github/workflows/ruby.yml +38 -0
- data/.gitignore +4 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +71 -17
- data/README.md +3 -1
- data/activerecord-pull-alpha.gemspec +1 -1
- data/lib/activerecord/pull/alpha/core.rb +84 -45
- data/lib/activerecord/pull/alpha/core_ext.rb +13 -0
- data/lib/activerecord/pull/alpha/version.rb +3 -1
- metadata +11 -9
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ccb0237045bd530e776a70c9e54572c9914cbb14a62c9a1e2c33ef26ca78a989
|
|
4
|
+
data.tar.gz: fe01b85e846a4ed2860a16c18c8ed235877098e68e460ed618a131bc360ec615
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 53416aabcb2c4e20bbb51fbc771914bb641cba6d6330cc8d8ad0de105c31495d50c5d4e54bb6ce2f15ae9fc611096ea2d7c9c9b48f7d8147493d5cbe4dc3a3ee
|
|
7
|
+
data.tar.gz: 215519fe1cb05dbe49ebac256de0961dc355aec22cf4c382782509b58a8f48168362d8acb1273876b118f26d3a838cb4c7762092072a9bc90b173b9b25692071
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# This workflow uses actions that are not certified by GitHub.
|
|
2
|
+
# They are provided by a third-party and are governed by
|
|
3
|
+
# separate terms of service, privacy policy, and support
|
|
4
|
+
# documentation.
|
|
5
|
+
# This workflow will download a prebuilt Ruby version, install dependencies and run tests with Rake
|
|
6
|
+
# For more information see: https://github.com/marketplace/actions/setup-ruby-jruby-and-truffleruby
|
|
7
|
+
|
|
8
|
+
name: Ruby
|
|
9
|
+
|
|
10
|
+
on:
|
|
11
|
+
push:
|
|
12
|
+
branches: [ "master" ]
|
|
13
|
+
pull_request:
|
|
14
|
+
branches: [ "master" ]
|
|
15
|
+
|
|
16
|
+
permissions:
|
|
17
|
+
contents: read
|
|
18
|
+
|
|
19
|
+
jobs:
|
|
20
|
+
test:
|
|
21
|
+
|
|
22
|
+
runs-on: ubuntu-latest
|
|
23
|
+
strategy:
|
|
24
|
+
matrix:
|
|
25
|
+
ruby-version: ['2.6', '2.7', '3.0']
|
|
26
|
+
|
|
27
|
+
steps:
|
|
28
|
+
- uses: actions/checkout@v3
|
|
29
|
+
- name: Set up Ruby
|
|
30
|
+
# To automatically get bug fixes and new Ruby versions for ruby/setup-ruby,
|
|
31
|
+
# change this to (see https://github.com/ruby/setup-ruby#versioning):
|
|
32
|
+
# uses: ruby/setup-ruby@v1
|
|
33
|
+
uses: ruby/setup-ruby@2b019609e2b0f1ea1a2bc8ca11cb82ab46ada124
|
|
34
|
+
with:
|
|
35
|
+
ruby-version: ${{ matrix.ruby-version }}
|
|
36
|
+
bundler-cache: true # runs 'bundle install' and caches installed gems automatically
|
|
37
|
+
- name: Run tests
|
|
38
|
+
run: bundle exec rake
|
data/.gitignore
CHANGED
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
|
@@ -1,35 +1,89 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
activerecord-pull-alpha (0.1.
|
|
4
|
+
activerecord-pull-alpha (0.1.2)
|
|
5
5
|
|
|
6
6
|
GEM
|
|
7
7
|
remote: https://rubygems.org/
|
|
8
8
|
specs:
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
9
|
+
activemodel (6.1.6.1)
|
|
10
|
+
activesupport (= 6.1.6.1)
|
|
11
|
+
activerecord (6.1.6.1)
|
|
12
|
+
activemodel (= 6.1.6.1)
|
|
13
|
+
activesupport (= 6.1.6.1)
|
|
14
|
+
activesupport (6.1.6.1)
|
|
15
|
+
concurrent-ruby (~> 1.0, >= 1.0.2)
|
|
16
|
+
i18n (>= 1.6, < 2)
|
|
17
|
+
minitest (>= 5.1)
|
|
18
|
+
tzinfo (~> 2.0)
|
|
19
|
+
zeitwerk (~> 2.3)
|
|
20
|
+
ast (2.4.2)
|
|
21
|
+
coderay (1.1.3)
|
|
22
|
+
concurrent-ruby (1.1.10)
|
|
23
|
+
diff-lcs (1.5.0)
|
|
24
|
+
i18n (1.12.0)
|
|
25
|
+
concurrent-ruby (~> 1.0)
|
|
26
|
+
method_source (1.0.0)
|
|
27
|
+
minitest (5.15.0)
|
|
28
|
+
parallel (1.22.1)
|
|
29
|
+
parser (3.1.2.0)
|
|
30
|
+
ast (~> 2.4.1)
|
|
31
|
+
pry (0.14.1)
|
|
32
|
+
coderay (~> 1.1)
|
|
33
|
+
method_source (~> 1.0)
|
|
34
|
+
rainbow (3.1.1)
|
|
35
|
+
rake (13.0.6)
|
|
36
|
+
regexp_parser (2.5.0)
|
|
37
|
+
rexml (3.2.5)
|
|
38
|
+
rspec (3.11.0)
|
|
39
|
+
rspec-core (~> 3.11.0)
|
|
40
|
+
rspec-expectations (~> 3.11.0)
|
|
41
|
+
rspec-mocks (~> 3.11.0)
|
|
42
|
+
rspec-core (3.11.0)
|
|
43
|
+
rspec-support (~> 3.11.0)
|
|
44
|
+
rspec-expectations (3.11.0)
|
|
18
45
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
19
|
-
rspec-support (~> 3.
|
|
20
|
-
rspec-mocks (3.
|
|
46
|
+
rspec-support (~> 3.11.0)
|
|
47
|
+
rspec-mocks (3.11.1)
|
|
21
48
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
22
|
-
rspec-support (~> 3.
|
|
23
|
-
rspec-support (3.
|
|
49
|
+
rspec-support (~> 3.11.0)
|
|
50
|
+
rspec-support (3.11.0)
|
|
51
|
+
rubocop (1.28.2)
|
|
52
|
+
parallel (~> 1.10)
|
|
53
|
+
parser (>= 3.1.0.0)
|
|
54
|
+
rainbow (>= 2.2.2, < 4.0)
|
|
55
|
+
regexp_parser (>= 1.8, < 3.0)
|
|
56
|
+
rexml
|
|
57
|
+
rubocop-ast (>= 1.17.0, < 2.0)
|
|
58
|
+
ruby-progressbar (~> 1.7)
|
|
59
|
+
unicode-display_width (>= 1.4.0, < 3.0)
|
|
60
|
+
rubocop-ast (1.17.0)
|
|
61
|
+
parser (>= 3.1.1.0)
|
|
62
|
+
rubocop-rspec (2.10.0)
|
|
63
|
+
rubocop (~> 1.19)
|
|
64
|
+
ruby-progressbar (1.11.0)
|
|
65
|
+
sqlite3 (1.4.4)
|
|
66
|
+
tzinfo (2.0.5)
|
|
67
|
+
concurrent-ruby (~> 1.0)
|
|
68
|
+
unicode-display_width (2.1.0)
|
|
69
|
+
zeitwerk (2.6.0)
|
|
24
70
|
|
|
25
71
|
PLATFORMS
|
|
26
|
-
|
|
72
|
+
-darwin-21
|
|
73
|
+
arm64-darwin-21
|
|
74
|
+
arm64-darwin-22
|
|
75
|
+
x86_64-linux
|
|
27
76
|
|
|
28
77
|
DEPENDENCIES
|
|
78
|
+
activerecord
|
|
29
79
|
activerecord-pull-alpha!
|
|
30
|
-
bundler (~>
|
|
80
|
+
bundler (~> 2.2)
|
|
81
|
+
pry
|
|
31
82
|
rake (~> 13.0)
|
|
32
83
|
rspec (~> 3.0)
|
|
84
|
+
rubocop
|
|
85
|
+
rubocop-rspec
|
|
86
|
+
sqlite3
|
|
33
87
|
|
|
34
88
|
BUNDLED WITH
|
|
35
|
-
|
|
89
|
+
2.3.8
|
data/README.md
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
[](https://github.com/delonnewman/activerecord-pull/actions/workflows/ruby.yml)
|
|
2
|
+
|
|
1
3
|
# ActiveRecord::Pull::Alpha
|
|
2
4
|
|
|
3
5
|
A simple query interface for pulling deeply nested data from records.
|
|
@@ -67,7 +69,7 @@ Or install it yourself as:
|
|
|
67
69
|
- [GraphQL](https://graphql.org/)
|
|
68
70
|
- [Entity Attribute Value Model][eav-model]
|
|
69
71
|
- [RDF][rdf]
|
|
70
|
-
- [A City is
|
|
72
|
+
- [A City is Not a Tree](https://www.patternlanguage.com/archive/cityisnotatree.html)
|
|
71
73
|
|
|
72
74
|
## License
|
|
73
75
|
|
|
@@ -34,7 +34,7 @@ Gem::Specification.new do |spec|
|
|
|
34
34
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
|
35
35
|
spec.require_paths = ["lib"]
|
|
36
36
|
|
|
37
|
-
spec.add_development_dependency "bundler", "~>
|
|
37
|
+
spec.add_development_dependency "bundler", "~> 2.2"
|
|
38
38
|
spec.add_development_dependency "rake", "~> 13.0"
|
|
39
39
|
spec.add_development_dependency "rspec", "~> 3.0"
|
|
40
40
|
end
|
|
@@ -1,54 +1,89 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module ActiveRecord
|
|
2
4
|
module Pull
|
|
3
5
|
module Alpha
|
|
6
|
+
class SyntaxError < RuntimeError; end
|
|
7
|
+
class ReflectionError < RuntimeError; end
|
|
8
|
+
|
|
4
9
|
module Core
|
|
5
10
|
class << self
|
|
6
|
-
|
|
7
|
-
|
|
11
|
+
# Apply the pull query to a collection of records.
|
|
12
|
+
#
|
|
13
|
+
# @param records [Enumerable<ActiveRecord::Base>]
|
|
14
|
+
# @param query [Symbol, String, Hash, Array]
|
|
15
|
+
#
|
|
16
|
+
# @return [Array<Hash>]
|
|
17
|
+
def pull_many(records, query)
|
|
18
|
+
records.map { |r| pull(r, query) }
|
|
8
19
|
end
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
20
|
+
|
|
21
|
+
# Apply the pull query to the given record.
|
|
22
|
+
#
|
|
23
|
+
# @param record [ActiveRecord::Base]
|
|
24
|
+
# @param query [Symbol, String, Hash, Array]
|
|
25
|
+
#
|
|
26
|
+
# @return [Hash]
|
|
27
|
+
def pull(record, query)
|
|
28
|
+
case query
|
|
12
29
|
when :*, '*'
|
|
13
30
|
pull_all(record)
|
|
14
31
|
when Symbol, String
|
|
15
|
-
pull_symbol(record,
|
|
32
|
+
pull_symbol(record, query)
|
|
16
33
|
when Hash
|
|
17
|
-
pull_hash(record,
|
|
34
|
+
pull_hash(record, query)
|
|
18
35
|
when Array
|
|
19
|
-
|
|
36
|
+
# TODO: add filter_map as a core extension for older Ruby implementations
|
|
37
|
+
query.map { |pat| pull(record, pat) }.reduce(&:merge)
|
|
20
38
|
else
|
|
21
|
-
raise "
|
|
39
|
+
raise SyntaxError, "invalid pull syntax: #{query.inspect}"
|
|
22
40
|
end
|
|
23
41
|
end
|
|
24
|
-
|
|
42
|
+
|
|
25
43
|
private
|
|
26
|
-
|
|
44
|
+
|
|
45
|
+
EMPTY_HASH = {}.freeze
|
|
46
|
+
private_constant :EMPTY_HASH
|
|
47
|
+
|
|
48
|
+
R = ActiveRecord::Reflection
|
|
49
|
+
private_constant :R
|
|
50
|
+
|
|
51
|
+
# @param record [#[]]
|
|
52
|
+
# @param attr [Symbol, String]
|
|
53
|
+
#
|
|
54
|
+
# @return [ActiveRecord::Base, ActiveRecord::Relation, Object, nil]
|
|
27
55
|
def resolved_value(record, attr)
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
56
|
+
val = record[attr]
|
|
57
|
+
return val unless val.nil?
|
|
58
|
+
|
|
59
|
+
reflection = record.class.reflect_on_association(attr)
|
|
60
|
+
return if reflection.nil?
|
|
61
|
+
|
|
62
|
+
model = reflection.class_name.constantize
|
|
63
|
+
|
|
64
|
+
case reflection
|
|
65
|
+
when R::HasManyReflection, R::HasAndBelongsToManyReflection
|
|
66
|
+
model.where(reflection.foreign_key => record[record.class.primary_key])
|
|
67
|
+
when R::BelongsToReflection
|
|
68
|
+
model.find_by(model.primary_key => record[reflection.foreign_key])
|
|
41
69
|
else
|
|
42
|
-
|
|
70
|
+
raise ReflectionError, "don't know how to resolve value for reflection: #{reflection.inspect}"
|
|
43
71
|
end
|
|
44
72
|
end
|
|
45
|
-
|
|
73
|
+
|
|
46
74
|
def ref_type?(value)
|
|
47
75
|
value.is_a?(ActiveRecord::Relation) || value.is_a?(ActiveRecord::Base)
|
|
48
76
|
end
|
|
49
|
-
|
|
77
|
+
|
|
78
|
+
# @param record [#[]]
|
|
79
|
+
# @param attr [Symbol, String]
|
|
80
|
+
#
|
|
81
|
+
# @return [Hash]
|
|
50
82
|
def pull_symbol(record, attr)
|
|
51
|
-
|
|
83
|
+
attr = attr.to_sym
|
|
84
|
+
val = resolved_value(record, attr)
|
|
85
|
+
return EMPTY_HASH if val.nil?
|
|
86
|
+
|
|
52
87
|
if ref_type?(val) && val.is_a?(Enumerable)
|
|
53
88
|
{ attr => val.map { |v| pull_all(v) } }
|
|
54
89
|
elsif ref_type?(val)
|
|
@@ -57,7 +92,11 @@ module ActiveRecord
|
|
|
57
92
|
{ attr => val }
|
|
58
93
|
end
|
|
59
94
|
end
|
|
60
|
-
|
|
95
|
+
|
|
96
|
+
# @param record [#[]]
|
|
97
|
+
# @param hash [Hash{Symbol, String => Symbol, String, Hash, Array}]
|
|
98
|
+
#
|
|
99
|
+
# @return [Hash]
|
|
61
100
|
def pull_hash(record, hash)
|
|
62
101
|
hash.reduce({}) do |h, (attr, pat)|
|
|
63
102
|
val = resolved_value(record, attr)
|
|
@@ -72,25 +111,25 @@ module ActiveRecord
|
|
|
72
111
|
end
|
|
73
112
|
end
|
|
74
113
|
end
|
|
75
|
-
|
|
76
|
-
#
|
|
114
|
+
|
|
115
|
+
# @param [ActiveRecord::Base]
|
|
116
|
+
#
|
|
117
|
+
# @return [Hash]
|
|
77
118
|
def pull_all(record)
|
|
78
|
-
names = record.class.attribute_names
|
|
119
|
+
names = record.class.attribute_names.map(&:to_sym)
|
|
79
120
|
nested = record.class.nested_attributes_options
|
|
80
121
|
attrs = pull(record, names)
|
|
81
|
-
|
|
82
|
-
if nested.empty?
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
h.merge!(assoc => pull_all(assoc_val))
|
|
93
|
-
end
|
|
122
|
+
|
|
123
|
+
return attrs if nested.empty?
|
|
124
|
+
|
|
125
|
+
nested.keys.reduce(attrs) do |h, assoc|
|
|
126
|
+
assoc_val = record.send(assoc)
|
|
127
|
+
if assoc_val.nil? || assoc_val.is_a?(Enumerable) && assoc_val.empty?
|
|
128
|
+
h
|
|
129
|
+
elsif assoc_val.is_a?(Enumerable)
|
|
130
|
+
h.merge!(assoc => assoc_val.filter_map { |rec| pull_all(rec) })
|
|
131
|
+
else
|
|
132
|
+
h.merge!(assoc => pull_all(assoc_val))
|
|
94
133
|
end
|
|
95
134
|
end
|
|
96
135
|
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
require 'activerecord/pull/alpha/core'
|
|
2
|
+
|
|
3
|
+
module Enumerable
|
|
4
|
+
def pull(*pattern)
|
|
5
|
+
ActiveRecord::Pull::Alpha::Core.pull_many(self, pattern)
|
|
6
|
+
end
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
class Object
|
|
10
|
+
def pull(*pattern)
|
|
11
|
+
ActiveRecord::Pull::Alpha::Core.pull(self, pattern)
|
|
12
|
+
end
|
|
13
|
+
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: activerecord-pull-alpha
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Delon Newman
|
|
8
|
-
autorequire:
|
|
8
|
+
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2023-08-31 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bundler
|
|
@@ -16,14 +16,14 @@ dependencies:
|
|
|
16
16
|
requirements:
|
|
17
17
|
- - "~>"
|
|
18
18
|
- !ruby/object:Gem::Version
|
|
19
|
-
version: '
|
|
19
|
+
version: '2.2'
|
|
20
20
|
type: :development
|
|
21
21
|
prerelease: false
|
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
23
|
requirements:
|
|
24
24
|
- - "~>"
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
|
-
version: '
|
|
26
|
+
version: '2.2'
|
|
27
27
|
- !ruby/object:Gem::Dependency
|
|
28
28
|
name: rake
|
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -52,13 +52,14 @@ dependencies:
|
|
|
52
52
|
- - "~>"
|
|
53
53
|
- !ruby/object:Gem::Version
|
|
54
54
|
version: '3.0'
|
|
55
|
-
description:
|
|
55
|
+
description:
|
|
56
56
|
email:
|
|
57
57
|
- contact@delonnewman.name
|
|
58
58
|
executables: []
|
|
59
59
|
extensions: []
|
|
60
60
|
extra_rdoc_files: []
|
|
61
61
|
files:
|
|
62
|
+
- ".github/workflows/ruby.yml"
|
|
62
63
|
- ".gitignore"
|
|
63
64
|
- ".rspec"
|
|
64
65
|
- Gemfile
|
|
@@ -69,6 +70,7 @@ files:
|
|
|
69
70
|
- activerecord-pull-alpha.gemspec
|
|
70
71
|
- lib/activerecord/pull/alpha.rb
|
|
71
72
|
- lib/activerecord/pull/alpha/core.rb
|
|
73
|
+
- lib/activerecord/pull/alpha/core_ext.rb
|
|
72
74
|
- lib/activerecord/pull/alpha/version.rb
|
|
73
75
|
homepage: https://github.com/delonnewman/activerecord-pull
|
|
74
76
|
licenses:
|
|
@@ -78,7 +80,7 @@ metadata:
|
|
|
78
80
|
homepage_uri: https://github.com/delonnewman/activerecord-pull
|
|
79
81
|
source_code_uri: https://github.com/delonnewman/activerecord-pull
|
|
80
82
|
changelog_uri: https://github.com/delonnewman/activerecord-pull#changelog
|
|
81
|
-
post_install_message:
|
|
83
|
+
post_install_message:
|
|
82
84
|
rdoc_options: []
|
|
83
85
|
require_paths:
|
|
84
86
|
- lib
|
|
@@ -93,8 +95,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
93
95
|
- !ruby/object:Gem::Version
|
|
94
96
|
version: '0'
|
|
95
97
|
requirements: []
|
|
96
|
-
rubygems_version: 3.
|
|
97
|
-
signing_key:
|
|
98
|
+
rubygems_version: 3.4.17
|
|
99
|
+
signing_key:
|
|
98
100
|
specification_version: 4
|
|
99
101
|
summary: A simple query interface for pulling deeply nested data from records.
|
|
100
102
|
test_files: []
|