q_hash 0.1.2 → 0.2.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: 45090f151f081e5c9c4d6a744d745736f7a652a68d777886b87a0750fb8a4995
4
- data.tar.gz: 98a176a62849a2ba100a63c779ec2e4d815f699071dd6ecb0f91e5914a788c95
3
+ metadata.gz: 4b5ef11c5099019641fbe1de713e1be087f9775f58571cb87a1554ad0155956e
4
+ data.tar.gz: 4ddad57fda9b5b8ffdf078cf432ed1b5ebf960928be1058341a54ae567ad43f0
5
5
  SHA512:
6
- metadata.gz: 4512ee4a037ca7fc5dd0cca860d5ac35a8afdda22e76a99ef5a6b07c1dd8beb379edaf3c40664bc91badadf4e13ccc00b25d590b1941bad44b825fe6b164aa24
7
- data.tar.gz: a85e3d75b37ac15d953ce2e624597278b7c3df57906dc5eb88241d44d28216d87191905e00309add8201a3a7590e61d724cf226797574ad572dc7c04125141f2
6
+ metadata.gz: edc0f7958090f8cb5720385622759bdc840c88d348c4c9fc519f4496f264d2dc8b15ca2fe952f7da9441a21bf1ba30eec667d53554a9bd9d5170b917ff232e81
7
+ data.tar.gz: 13fb94e70543d0a5dfe64add5cefdab276d906df332e48386a78933dabd1dd04f52f1960118e5d0da1a7e9e228ef82c7387d437248de56a2db04fd13932aa674
@@ -16,5 +16,9 @@ jobs:
16
16
  with:
17
17
  ruby-version: ${{ matrix.ruby }}
18
18
  bundler-cache: true
19
- - name: Run the default task
20
- run: bundle exec rake
19
+ - name: Linter
20
+ run: bundle exec rake standard
21
+ - name: Test
22
+ run: bundle exec rake spec
23
+ - name: Type Check
24
+ run: bundle exec rake steep
data/Gemfile CHANGED
@@ -5,10 +5,16 @@ source "https://rubygems.org"
5
5
  # Specify your gem's dependencies in q_hash.gemspec
6
6
  gemspec
7
7
 
8
+ gem "activesupport", "< 7.0"
9
+
8
10
  gem "rake", "~> 13.0"
9
11
 
12
+ gem "rbs"
13
+
10
14
  gem "rspec", "~> 3.0"
11
15
 
16
+ gem "simplecov"
17
+
12
18
  gem "standard"
13
19
 
14
- gem "simplecov"
20
+ gem "steep"
data/Gemfile.lock CHANGED
@@ -1,20 +1,39 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- q_hash (0.1.2)
4
+ q_hash (0.2.0)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
8
8
  specs:
9
+ activesupport (6.1.6)
10
+ concurrent-ruby (~> 1.0, >= 1.0.2)
11
+ i18n (>= 1.6, < 2)
12
+ minitest (>= 5.1)
13
+ tzinfo (~> 2.0)
14
+ zeitwerk (~> 2.3)
9
15
  ast (2.4.2)
16
+ concurrent-ruby (1.1.10)
10
17
  diff-lcs (1.5.0)
11
18
  docile (1.4.0)
19
+ ffi (1.15.5)
20
+ i18n (1.10.0)
21
+ concurrent-ruby (~> 1.0)
22
+ language_server-protocol (3.16.0.3)
23
+ listen (3.7.1)
24
+ rb-fsevent (~> 0.10, >= 0.10.3)
25
+ rb-inotify (~> 0.9, >= 0.9.10)
26
+ minitest (5.15.0)
12
27
  parallel (1.22.1)
13
- parser (3.1.1.0)
28
+ parser (3.1.2.0)
14
29
  ast (~> 2.4.1)
15
30
  rainbow (3.1.1)
16
31
  rake (13.0.6)
17
- regexp_parser (2.3.0)
32
+ rb-fsevent (0.11.1)
33
+ rb-inotify (0.10.1)
34
+ ffi (~> 1.0)
35
+ rbs (2.5.0)
36
+ regexp_parser (2.4.0)
18
37
  rexml (3.2.5)
19
38
  rspec (3.11.0)
20
39
  rspec-core (~> 3.11.0)
@@ -29,16 +48,16 @@ GEM
29
48
  diff-lcs (>= 1.2.0, < 2.0)
30
49
  rspec-support (~> 3.11.0)
31
50
  rspec-support (3.11.0)
32
- rubocop (1.26.1)
51
+ rubocop (1.29.1)
33
52
  parallel (~> 1.10)
34
53
  parser (>= 3.1.0.0)
35
54
  rainbow (>= 2.2.2, < 4.0)
36
55
  regexp_parser (>= 1.8, < 3.0)
37
- rexml
38
- rubocop-ast (>= 1.16.0, < 2.0)
56
+ rexml (>= 3.2.5, < 4.0)
57
+ rubocop-ast (>= 1.17.0, < 2.0)
39
58
  ruby-progressbar (~> 1.7)
40
59
  unicode-display_width (>= 1.4.0, < 3.0)
41
- rubocop-ast (1.16.0)
60
+ rubocop-ast (1.18.0)
42
61
  parser (>= 3.1.1.0)
43
62
  rubocop-performance (1.13.3)
44
63
  rubocop (>= 1.7.0, < 2.0)
@@ -50,21 +69,38 @@ GEM
50
69
  simplecov_json_formatter (~> 0.1)
51
70
  simplecov-html (0.12.3)
52
71
  simplecov_json_formatter (0.1.4)
53
- standard (1.9.1)
54
- rubocop (= 1.26.1)
72
+ standard (1.12.1)
73
+ rubocop (= 1.29.1)
55
74
  rubocop-performance (= 1.13.3)
75
+ steep (1.0.0)
76
+ activesupport (>= 5.1)
77
+ language_server-protocol (>= 3.15, < 4.0)
78
+ listen (~> 3.0)
79
+ parallel (>= 1.0.0)
80
+ parser (>= 3.0)
81
+ rainbow (>= 2.2.2, < 4.0)
82
+ rbs (>= 2.3.2)
83
+ terminal-table (>= 2, < 4)
84
+ terminal-table (3.0.2)
85
+ unicode-display_width (>= 1.1.1, < 3)
86
+ tzinfo (2.0.4)
87
+ concurrent-ruby (~> 1.0)
56
88
  unicode-display_width (2.1.0)
89
+ zeitwerk (2.5.4)
57
90
 
58
91
  PLATFORMS
59
92
  x86_64-darwin-20
60
93
  x86_64-linux
61
94
 
62
95
  DEPENDENCIES
96
+ activesupport (< 7.0)
63
97
  q_hash!
64
98
  rake (~> 13.0)
99
+ rbs
65
100
  rspec (~> 3.0)
66
101
  simplecov
67
102
  standard
103
+ steep
68
104
 
69
105
  BUNDLED WITH
70
106
  2.3.11
data/README.md CHANGED
@@ -1,10 +1,37 @@
1
1
  # QHash - [ActiveRecord](https://github.com/rails/rails/tree/main/activerecord) style query interface for Hash
2
2
 
3
3
  [![Ruby](https://github.com/AkihikoITOH/q_hash/actions/workflows/main.yml/badge.svg)](https://github.com/AkihikoITOH/q_hash/actions/workflows/main.yml)
4
+ [![Gem Version](https://badge.fury.io/rb/q_hash.svg)](https://badge.fury.io/rb/q_hash)
4
5
  [![Maintainability](https://api.codeclimate.com/v1/badges/21e195471cca64af0366/maintainability)](https://codeclimate.com/github/AkihikoITOH/q_hash/maintainability)
5
6
 
6
7
  QHash lets you query array of hashes with ActiveRecord-like interface.
7
8
 
9
+ ## What's the point?
10
+
11
+ We often do something like
12
+
13
+ ```ruby
14
+ users.select do |user|
15
+ (dob = user.dig(:personal_data, :date_of_birth)) &&
16
+ dob > Date.new(1990, 1, 1) &&
17
+ user.dig(:address, :country) == "Germany" &&
18
+ user.dig(:address, :city) == "Hamburg"
19
+ end
20
+ ```
21
+
22
+ which can quickly become hard to read.
23
+
24
+ QHash provides syntax sugar that would allow you to do
25
+
26
+ ```ruby
27
+ users.where(
28
+ personal_data: {
29
+ date_of_birth: ->(dob) { dob > Date.new(1990, 1, 1) }
30
+ },
31
+ address: {country: "Germany", city: "Hamburg"}
32
+ )
33
+ ```
34
+
8
35
  ## Installation
9
36
 
10
37
  Add this line to your application's Gemfile:
data/Rakefile CHANGED
@@ -7,4 +7,7 @@ RSpec::Core::RakeTask.new(:spec)
7
7
 
8
8
  require "standard/rake"
9
9
 
10
- task default: %i[standard spec]
10
+ task default: %i[standard spec steep]
11
+ task :steep do
12
+ sh "bundle exec steep check"
13
+ end
data/Steepfile ADDED
@@ -0,0 +1,7 @@
1
+ target :lib do
2
+ signature "sig"
3
+
4
+ check "lib"
5
+
6
+ configure_code_diagnostics(Steep::Diagnostic::Ruby.strict)
7
+ end
data/bin/release ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env sh
2
+
3
+ GEM_VERSION=$(ruby -e '$LOAD_PATH << File.join(File.dirname(__FILE__), "lib"); require "q_hash"; print QHash::VERSION')
4
+
5
+ gem build q_hash.gemspec
6
+
7
+ if [ ! -d "pkg" ]; then
8
+ mkdir pkg
9
+ fi
10
+
11
+ mv q_hash-$GEM_VERSION.gem pkg/q_hash-$GEM_VERSION.gem
12
+
13
+ git tag -m "Release $GEM_VERSION" -a v$GEM_VERSION HEAD
14
+ git push origin --tags
15
+
16
+ gem push pkg/q_hash-$GEM_VERSION.gem
data/lib/q_hash.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class QHash
4
- VERSION = "0.1.2"
4
+ VERSION = "0.2.0"
5
5
 
6
6
  class Error < StandardError; end
7
7
 
@@ -13,18 +13,17 @@ class QHash
13
13
  @data = data
14
14
  end
15
15
 
16
- def find_by(conditions)
17
- data.find do |hash|
18
- conditions.all? { |key, value| query(hash, key, value) }
19
- end
16
+ def find_by(**conditions)
17
+ data.find { |record| apply_conditions(record, conditions) }
20
18
  end
21
19
 
22
- def find_by!(conditions)
23
- find_by(conditions) || raise(RecordNotFound)
20
+ def find_by!(**conditions)
21
+ find_by(**conditions) || raise(RecordNotFound)
24
22
  end
25
23
 
26
- def where(conditions)
27
- self.class.new(filter_by_conditions(conditions))
24
+ def where(**conditions)
25
+ result = data.select { |record| apply_conditions(record, conditions) }
26
+ self.class.new(result)
28
27
  end
29
28
 
30
29
  def each(&block)
@@ -37,30 +36,24 @@ class QHash
37
36
 
38
37
  private
39
38
 
40
- def filter_by_conditions(conditions)
41
- data.select do |hash|
42
- conditions.all? { |key, value| query(hash, key, value) }
43
- end
39
+ attr_reader :data
40
+
41
+ def apply_conditions(record, conditions)
42
+ conditions.all? { |query_key, query_value| query(record, query_key, query_value) }
44
43
  end
45
44
 
46
45
  def query(record, key, value)
47
- return false if record[key].nil?
46
+ return false unless record.key?(key)
48
47
 
49
48
  case value
50
49
  when Proc
51
50
  value.call(record[key])
52
51
  when Hash
53
- value.all? { |nested_key, nested_value| query(record[key], nested_key, nested_value) }
52
+ value.all? { |nested_query_key, nested_query_value| query(record[key], nested_query_key, nested_query_value) }
54
53
  when Array
55
54
  value.include?(record[key])
56
55
  else
57
- record[key] == value
56
+ value == record[key]
58
57
  end
59
58
  end
60
-
61
- def top_level_keys
62
- @top_level_keys ||= array_of_hashes.flat_map(&:keys).uniq
63
- end
64
-
65
- attr_reader :data, :filtered_data
66
59
  end
data/sig/q_hash.rbs ADDED
@@ -0,0 +1,18 @@
1
+ # See the writing guide of rbs: https://github.com/ruby/rbs#guides
2
+ class QHash
3
+ VERSION: String
4
+
5
+ Error: StandardError
6
+ RecordNotFound: StandardError
7
+
8
+ def initialize: (Array[Hash[Symbol, untyped]]) -> void
9
+ def find_by: (**Hash[Symbol, untyped]) -> Hash[Symbol, untyped]?
10
+ def find_by!: (**Hash[Symbol, untyped]) -> Hash[Symbol, untyped]?
11
+ def where: (**Hash[Symbol, untyped]) -> QHash
12
+ def each: () { (Hash[Symbol, untyped]) -> void } -> void
13
+ def inspect: () -> Array[Hash[Symbol, untyped]]
14
+
15
+ private attr_reader data: Array[Hash[Symbol, untyped]]
16
+ private def apply_conditions: (Hash[Symbol, untyped], Hash[Symbol, untyped]) -> bool
17
+ private def query: (Hash[Symbol, untyped], Symbol, untyped) -> bool
18
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: q_hash
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Akihiko Ito
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-04-09 00:00:00.000000000 Z
11
+ date: 2022-05-22 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: QHash lets you query array of hashes with ActiveRecord-like interface
14
14
  email:
@@ -28,10 +28,13 @@ files:
28
28
  - LICENSE.txt
29
29
  - README.md
30
30
  - Rakefile
31
+ - Steepfile
31
32
  - bin/console
33
+ - bin/release
32
34
  - bin/setup
33
35
  - lib/q_hash.rb
34
36
  - q_hash.gemspec
37
+ - sig/q_hash.rbs
35
38
  homepage: https://github.com/AkihikoITOH/q_hash
36
39
  licenses:
37
40
  - MIT