active_record_relation_in 0.1.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 9ce1d6dc9172035c97ed5360be175b27798667d8aaca6a88d3dc6077fb3d1f84
4
+ data.tar.gz: a68c0e828707ee8010ebf1a4371523948baf3a24beb991dca01e47e00fa1a3b8
5
+ SHA512:
6
+ metadata.gz: 84a88ba27d53ee59bb12aa6a753ef1c3d017a00b8ee6dec66d1a3baaab859877e438f685e1aa37da4151d72b5e76482767b0ab710405db21845d648818501ec9
7
+ data.tar.gz: 1fd5a4e73d28459c59c7e97cb4e08459c1f94acd4d775724842fdcc7f5acd69f5eb8969b140eb6dfbbb11c5dc1a9458bb65f2ad053603884c1df7e8b05ff7fb4
data/README.md ADDED
@@ -0,0 +1,75 @@
1
+ ## Index
2
+ - [Description and history](#description-and-history)
3
+ - [Compatibility](#compatibility)
4
+ - [Installation](#installation)
5
+ - [Usage](#usage)
6
+ - [Scope Modifiers](#scope-modifiers)
7
+ - [Combine With IN](#combine-with-in)
8
+
9
+ ## Description and History
10
+
11
+ Active Record Relation In grew out of the frustration that certain combining of scopes would make them not function.
12
+
13
+ By default ActiveRecord combines different where statements with an AND statement. This makes it hard to write scopes that can be combined without doing a lot of trickery.
14
+
15
+ Active Record Relation In is the continuation of maintaining and improving the work done by **George Protacio-Karaszi**, the original author of [active_record_extended](https://github.com/GeorgeKaraszi/ActiveRecordExtended).
16
+
17
+ Since it's a great start of how to make sure combines correctly with Active Record and this feature was a bit to specific for them to want in their gem.
18
+
19
+ ## Compatibility
20
+
21
+ This package is designed align and work with any officially supported Ruby and Rails versions.
22
+ - Minimum Ruby Version: 3.1.x **(EOL warning!)**
23
+ - Minimum Rails Version: 6.1.x **(EOL warning!)**
24
+ - Minimum Postgres Version: 12.x **(EOL warning!)**
25
+ - Latest Ruby supported: 3.3.x
26
+ - Latest Rails supported: 7.1.x
27
+ - Postgres: 11-current(16) (probably works with most older versions to a certain point)
28
+
29
+ ## Installation
30
+
31
+ Add this line to your application's Gemfile:
32
+
33
+ ```ruby
34
+ gem 'active_record_relation_in'
35
+ ```
36
+
37
+ And then execute:
38
+
39
+ $ bundle
40
+
41
+ ## Usage
42
+
43
+ #### Scope Modifiers
44
+
45
+ #### Combine With IN
46
+
47
+ When you want to combine with statement with an IN statement instead of the usual AND statement
48
+
49
+ `.combine_with_in/0`
50
+
51
+ ```ruby
52
+ class User < ApplicationRecord
53
+ end
54
+
55
+
56
+ class Tag < ApplicationRecord
57
+ belongs_to :user
58
+ scope :for_users, ->(user_ids) { where(user_id: user_ids).combine_with_in }
59
+ end
60
+
61
+ Tag.where(id: 1).for_users([1, 2]).for_users(3)
62
+ ```
63
+
64
+ Query Output
65
+ ```sql
66
+ SELECT "tags".*
67
+ FROM "tags"
68
+ WHERE
69
+ "tags"."id" = 1 AND
70
+ "tags"."user_id" IN (1, 2, 3)
71
+ ```
72
+
73
+ ## License
74
+
75
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecordRelationIn
4
+ VERSION = "0.1.0"
5
+ end
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecordRelationIn
4
+ module WhereClause
5
+ class CombineWithInRelation < ActiveRecord::Relation::WhereClause
6
+ def ast
7
+ predicates = predicates_with_wrapped_sql_literals
8
+ return predicates.first if predicates.one?
9
+
10
+ equality_predicats, other_predicats = split_predicates(predicates)
11
+
12
+ return Arel::Nodes::And.new(predicates) if equality_predicats.empty?
13
+
14
+ ast_for_equality_predicates(equality_predicats, other_predicats)
15
+ end
16
+
17
+ private
18
+
19
+ def ast_for_equality_predicates(equality_predicats, other_predicats)
20
+ grouped_equality_predicates = equality_predicats.group_by { |equality_predicat| equality_predicat.right.name }
21
+ if grouped_equality_predicates.one? && other_predicats.empty?
22
+ values = predicate_values(predicates)
23
+ attribute = predicates.first.left
24
+ Arel::Nodes::HomogeneousIn.new(values, attribute, :in)
25
+ else
26
+ combined_predicates = other_predicats + equality_predicates(grouped_equality_predicates)
27
+ Arel::Nodes::And.new(combined_predicates)
28
+ end
29
+ end
30
+
31
+ def predicate_values(predicates)
32
+ predicates.map do |predicate|
33
+ value = predicate.right.value
34
+ if value.instance_of?(Hash)
35
+ value.map { |key, hash_values| hash_values.map { |hash_value| hash_value[key] } }
36
+ else
37
+ value
38
+ end
39
+ end.flatten
40
+ end
41
+
42
+ def split_predicates(predicates)
43
+ predicates.each_with_object([[], []]) do |predicate, acc|
44
+ if predicate.instance_of?(Arel::Nodes::Equality)
45
+ [acc.first.push(predicate), acc.last]
46
+ else
47
+ [acc.first, acc.last.push(predicate)]
48
+ end
49
+ end
50
+ end
51
+
52
+ def equality_predicates(grouped_equality_predicates)
53
+ grouped_equality_predicates.values.map do |predicates_by_name|
54
+ if predicates_by_name.one?
55
+ predicates_by_name.first
56
+ else
57
+ values = predicate_values(predicates_by_name)
58
+ attribute = predicates_by_name.first.left
59
+ Arel::Nodes::HomogeneousIn.new(values, attribute, :in)
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecordRelationIn
4
+ module WhereClause
5
+ module RelationPatch
6
+ module RelationCombineInPatch
7
+ def combine_with_in
8
+ self.where_clause = where_clause.combine_with_in
9
+
10
+ self
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
16
+
17
+ ActiveRecord::Relation.prepend(ActiveRecordRelationIn::WhereClause::RelationPatch::RelationCombineInPatch)
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecordRelationIn
4
+ module WhereClause
5
+ module WhereClausePatch
6
+ def combine_with_in
7
+ ActiveRecordRelationIn::WhereClause::CombineWithInRelation.new(@predicates)
8
+ end
9
+ end
10
+ end
11
+ end
12
+
13
+ ActiveRecord::Relation::WhereClause.prepend(ActiveRecordRelationIn::WhereClause::WhereClausePatch)
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "active_record_relation_in/version"
4
+
5
+ require "active_record"
6
+
7
+ module ActiveRecordRelationIn
8
+ extend ActiveSupport::Autoload
9
+
10
+ AR_VERSION_GTE_6_1 = Gem::Requirement.new(">= 6.1").satisfied_by?(ActiveRecord.gem_version)
11
+
12
+ module WhereClause
13
+ extend ActiveSupport::Autoload
14
+
15
+ eager_autoload do
16
+ autoload :RelationPatch
17
+ autoload :WhereClausePatch
18
+ autoload :CombineWithInRelation
19
+ end
20
+ end
21
+
22
+ def self.eager_load!
23
+ super
24
+ ActiveRecordRelationIn::WhereClause.eager_load!
25
+ end
26
+ end
27
+
28
+ ActiveSupport.on_load(:active_record) do
29
+ ActiveRecordRelationIn.eager_load!
30
+ end
metadata ADDED
@@ -0,0 +1,81 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: active_record_relation_in
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Olafur Arason
8
+ bindir: bin
9
+ cert_chain: []
10
+ date: 2025-03-16 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: activerecord
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - ">="
17
+ - !ruby/object:Gem::Version
18
+ version: '5.2'
19
+ - - "<"
20
+ - !ruby/object:Gem::Version
21
+ version: '8.1'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ version: '5.2'
29
+ - - "<"
30
+ - !ruby/object:Gem::Version
31
+ version: '8.1'
32
+ - !ruby/object:Gem::Dependency
33
+ name: pg
34
+ requirement: !ruby/object:Gem::Requirement
35
+ requirements:
36
+ - - "<"
37
+ - !ruby/object:Gem::Version
38
+ version: '3.0'
39
+ type: :runtime
40
+ prerelease: false
41
+ version_requirements: !ruby/object:Gem::Requirement
42
+ requirements:
43
+ - - "<"
44
+ - !ruby/object:Gem::Version
45
+ version: '3.0'
46
+ description: Adds relation in functionality to Activerecord Postgres implementation
47
+ email:
48
+ - olafura@olafura.com
49
+ executables: []
50
+ extensions: []
51
+ extra_rdoc_files: []
52
+ files:
53
+ - README.md
54
+ - lib/active_record_relation_in.rb
55
+ - lib/active_record_relation_in/version.rb
56
+ - lib/active_record_relation_in/where_clause/combine_with_in_relation.rb
57
+ - lib/active_record_relation_in/where_clause/relation_patch.rb
58
+ - lib/active_record_relation_in/where_clause/where_clause_patch.rb
59
+ homepage: https://github.com/olafura/active_record_relation_in
60
+ licenses:
61
+ - MIT
62
+ metadata:
63
+ rubygems_mfa_required: 'true'
64
+ rdoc_options: []
65
+ require_paths:
66
+ - lib
67
+ required_ruby_version: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ version: '3.1'
72
+ required_rubygems_version: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ requirements: []
78
+ rubygems_version: 3.6.2
79
+ specification_version: 4
80
+ summary: Adds relation in functionality to Activerecord Postgres implementation
81
+ test_files: []