rails_or 1.1.8 → 1.1.9

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile CHANGED
@@ -1,10 +1,10 @@
1
- require "bundler/gem_tasks"
2
- require "rake/testtask"
1
+ require 'bundler/gem_tasks'
2
+ require 'rake/testtask'
3
3
 
4
4
  Rake::TestTask.new(:test) do |t|
5
- t.libs << "test"
6
- t.libs << "lib"
5
+ t.libs << 'test'
6
+ t.libs << 'lib'
7
7
  t.test_files = FileList['test/**/*_test.rb']
8
8
  end
9
9
 
10
- task :default => :test
10
+ task default: :test
data/bin/console CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require "bundler/setup"
4
- require "rails_or"
3
+ require 'bundler/setup'
4
+ require 'rails_or'
5
5
 
6
6
  # You can add fixtures and/or initialization code here to make experimenting
7
7
  # with your gem easier. You can also use a different console, if you like.
@@ -10,5 +10,5 @@ require "rails_or"
10
10
  # require "pry"
11
11
  # Pry.start
12
12
 
13
- require "irb"
13
+ require 'irb'
14
14
  IRB.start
data/bin/setup CHANGED
@@ -1,8 +1,8 @@
1
- #!/usr/bin/env bash
2
- set -euo pipefail
3
- IFS=$'\n\t'
4
- set -vx
5
-
6
- bundle install --gemfile=gemfiles/4.2.gemfile
7
-
8
- # Do any other automated setup that you need to do here
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install --gemfile=gemfiles/4.2.gemfile
7
+
8
+ # Do any other automated setup that you need to do here
data/gemfiles/3.2.gemfile CHANGED
@@ -1,13 +1,10 @@
1
- source 'https://rubygems.org'
2
-
3
- # Specify your gem's dependencies in rails_or.gemspec
4
-
5
- gem "activerecord", "~> 3.2"
6
-
7
- group :test do
8
- gem "simplecov"
9
- gem "codeclimate-test-reporter", "~> 1.0.0"
10
- end
11
-
12
- gemspec :path => "../"
13
-
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'activerecord', '~> 3.2.0'
4
+
5
+ group :test do
6
+ gem 'simplecov', '< 0.18'
7
+ gem 'sqlite3', '~> 1.3.6'
8
+ end
9
+
10
+ gemspec path: '../'
data/gemfiles/4.2.gemfile CHANGED
@@ -1,13 +1,10 @@
1
- source 'https://rubygems.org'
2
-
3
- # Specify your gem's dependencies in rails_or.gemspec
4
-
5
- gem "activerecord", "~> 4.2"
6
-
7
- group :test do
8
- gem "simplecov"
9
- gem "codeclimate-test-reporter", "~> 1.0.0"
10
- end
11
-
12
- gemspec :path => "../"
13
-
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'activerecord', '~> 4.2.0'
4
+
5
+ group :test do
6
+ gem 'simplecov', '< 0.18'
7
+ gem 'sqlite3', '~> 1.3.6'
8
+ end
9
+
10
+ gemspec path: '../'
data/gemfiles/5.0.gemfile CHANGED
@@ -1,13 +1,10 @@
1
- source 'https://rubygems.org'
2
-
3
- # Specify your gem's dependencies in rails_or.gemspec
4
-
5
- gem "activerecord", "~> 5.0"
6
-
7
- group :test do
8
- gem "simplecov"
9
- gem "codeclimate-test-reporter", "~> 1.0.0"
10
- end
11
-
12
- gemspec :path => "../"
13
-
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'activerecord', '~> 5.0.0'
4
+
5
+ group :test do
6
+ gem 'simplecov', '< 0.18'
7
+ gem 'sqlite3', '~> 1.3.6'
8
+ end
9
+
10
+ gemspec path: '../'
data/gemfiles/5.1.gemfile CHANGED
@@ -1,13 +1,10 @@
1
- source 'https://rubygems.org'
2
-
3
- # Specify your gem's dependencies in rails_or.gemspec
4
-
5
- gem "activerecord", "~> 5.1"
6
-
7
- group :test do
8
- gem "simplecov"
9
- gem "codeclimate-test-reporter", "~> 1.0.0"
10
- end
11
-
12
- gemspec :path => "../"
13
-
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'activerecord', '~> 5.1.0'
4
+
5
+ group :test do
6
+ gem 'simplecov', '< 0.18'
7
+ gem 'sqlite3', '~> 1.3.6'
8
+ end
9
+
10
+ gemspec path: '../'
@@ -0,0 +1,10 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'activerecord', '~> 5.2.0'
4
+
5
+ group :test do
6
+ gem 'simplecov', '< 0.18'
7
+ gem 'sqlite3', '~> 1.3.6'
8
+ end
9
+
10
+ gemspec path: '../'
@@ -0,0 +1,10 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'activerecord', '~> 6.0.0'
4
+
5
+ group :test do
6
+ gem 'simplecov', '< 0.18'
7
+ gem 'sqlite3', '~> 1.4.1'
8
+ end
9
+
10
+ gemspec path: '../'
@@ -0,0 +1,10 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'activerecord', '~> 6.1.0'
4
+
5
+ group :test do
6
+ gem 'simplecov', '< 0.18'
7
+ gem 'sqlite3', '~> 1.4.1'
8
+ end
9
+
10
+ gemspec path: '../'
data/lib/rails_or.rb CHANGED
@@ -1,119 +1,63 @@
1
- require "rails_or/version"
2
- require "rails_or/where_binding_mixs"
3
- require 'active_record'
4
-
5
- if defined?(ActiveRecord::NullRelation)
6
- module ActiveRecord::NullRelation
7
- if method_defined?(:or)
8
- if not method_defined?(:rails5_or)
9
- alias_method :rails5_or, :or
10
- def or(*other)
11
- rails5_or(rails_or_parse_parameter(*other))
12
- end
13
- end
14
- end
15
- end
16
- end
17
-
18
- class ActiveRecord::Relation
19
- IS_RAILS3_FLAG = Gem::Version.new(ActiveRecord::VERSION::STRING) < Gem::Version.new('4.0.0')
20
- IS_RAILS5_FLAG = Gem::Version.new(ActiveRecord::VERSION::STRING) >= Gem::Version.new('5.0.0')
21
- FROM_VALUE_METHOD = %i[from_value from_clause].find{|s| method_defined?(s) }
22
- ASSIGN_FROM_VALUE = :"#{FROM_VALUE_METHOD}="
23
- if method_defined?(:or)
24
- if not method_defined?(:rails5_or)
25
- alias_method :rails5_or, :or
26
- def or(*other)
27
- return rails5_or(rails_or_parse_parameter(*other))
28
- end
29
- end
30
- else
31
- def or(*other)
32
- other = rails_or_parse_parameter(*other)
33
- combining = group_values.any? ? :having : :where
34
- left = RailsOr::WhereBindingMixs.new(self.send("#{combining}_values"), self.bind_values)
35
- right = RailsOr::WhereBindingMixs.new(other.send("#{combining}_values"), other.bind_values)
36
- common = left & right
37
-
38
- left -= common
39
- right -= common
40
-
41
- if left.where_values.any? && right.where_values.any?
42
- arel_or = Arel::Nodes::Or.new(
43
- rails_or_values_to_arel(left.where_values),
44
- rails_or_values_to_arel(right.where_values),
45
- )
46
- common += RailsOr::WhereBindingMixs.new([arel_or], left.bind_values + right.bind_values)
47
- end
48
-
49
- relation = rails_or_get_current_scope
50
- if defined?(ActiveRecord::NullRelation) # Rails 3 does not have ActiveRecord::NullRelation
51
- return other if relation.is_a?(ActiveRecord::NullRelation)
52
- return relation if other.is_a?(ActiveRecord::NullRelation)
53
- end
54
- relation.send("#{combining}_values=", common.where_values)
55
- relation.bind_values = common.bind_values
56
- return relation
57
- end
58
- end
59
-
60
- def or_not(*args) # Works in Rails 4+
61
- self.or(klass.where.not(*args))
62
- end
63
-
64
- def or_having(hash)
65
- self.or(rails_or_spwan_relation(:having, hash))
66
- end
67
-
68
- private
69
-
70
- def rails_or_values_to_arel(values)
71
- values.map!{|x| rails_or_wrap_arel(x) }
72
- return (values.size > 1 ? Arel::Nodes::And.new(values) : values)
73
- end
74
-
75
- def rails_or_wrap_arel(node)
76
- return node if Arel::Nodes::Equality === node
77
- return Arel::Nodes::Grouping.new(String === node ? Arel.sql(node) : node)
78
- end
79
-
80
- def rails_or_parse_parameter(*other)
81
- other = other.first if other.size == 1
82
- case other
83
- when Hash ; rails_or_spwan_relation(:where, other)
84
- when Array ; rails_or_spwan_relation(:where, other)
85
- when String ; rails_or_spwan_relation(:where, other)
86
- else ; other
87
- end
88
- end
89
-
90
- def rails_or_copy_values_to(relation) # For Rails 5
91
- relation.joins_values = self.joins_values
92
- relation.limit_value = self.limit_value
93
- relation.group_values = self.group_values
94
- relation.distinct_value = self.distinct_value
95
- relation.order_values = self.order_values
96
- relation.offset_value = self.offset_value
97
- relation.references_values = self.references_values
98
- end
99
-
100
- def rails_or_spwan_relation(method, condition)
101
- relation = klass.send(method, condition)
102
- relation.send(ASSIGN_FROM_VALUE, send(FROM_VALUE_METHOD))
103
- rails_or_copy_values_to(relation) if IS_RAILS5_FLAG
104
- return relation
105
- end
106
-
107
- def rails_or_get_current_scope
108
- return self.clone if IS_RAILS3_FLAG
109
- # ref: https://github.com/rails/rails/blob/17ef58db1776a795c9f9e31a1634db7bcdc3ecdf/activerecord/lib/active_record/scoping/named.rb#L26
110
- # return self.all # <- cannot use this because some gem changes this method's behavior
111
- return (self.current_scope || self.default_scoped).clone
112
- end
113
- end
114
-
115
- class ActiveRecord::Base
116
- def self.or(*args)
117
- self.where('').or(*args)
118
- end
119
- end
1
+ require 'rails_or/version'
2
+ require 'rails_or/where_binding_mixs'
3
+ require 'active_record'
4
+ require 'rails_or/patches/null_relation' if defined?(ActiveRecord::NullRelation)
5
+ require 'rails_or/active_record/extension'
6
+
7
+ module RailsOr
8
+ IS_RAILS3_FLAG = Gem::Version.new(ActiveRecord::VERSION::STRING) < Gem::Version.new('4.0.0')
9
+ IS_RAILS5_FLAG = Gem::Version.new(ActiveRecord::VERSION::STRING) >= Gem::Version.new('5.0.0')
10
+ FROM_VALUE_METHOD = %i[from_value from_clause].find{|s| ActiveRecord::Relation.method_defined?(s) }
11
+ ASSIGN_FROM_VALUE = :"#{FROM_VALUE_METHOD}="
12
+
13
+ class << self
14
+ def values_to_arel(values)
15
+ values.map!{|x| wrap_arel(x) }
16
+ return (values.size > 1 ? Arel::Nodes::And.new(values) : values)
17
+ end
18
+
19
+ def spawn_relation(relation, method, condition)
20
+ new_relation = relation.klass.send(method, condition)
21
+
22
+ from_value = relation.send(FROM_VALUE_METHOD)
23
+ new_relation.send(ASSIGN_FROM_VALUE, from_value) if from_value.present?
24
+
25
+ copy_values(new_relation, relation) if IS_RAILS5_FLAG
26
+ return new_relation
27
+ end
28
+
29
+ def get_current_scope(relation)
30
+ return relation.clone if IS_RAILS3_FLAG
31
+ # ref: https://github.com/rails/rails/blob/17ef58db1776a795c9f9e31a1634db7bcdc3ecdf/activerecord/lib/active_record/scoping/named.rb#L26
32
+ # return relation.all # <- cannot use this because some gem changes this method's behavior
33
+ return (relation.current_scope || relation.default_scoped).clone
34
+ end
35
+
36
+ def parse_parameter(relation, *other)
37
+ other = other.first if other.size == 1
38
+ case other
39
+ when Hash ; spawn_relation(relation, :where, other)
40
+ when Array ; spawn_relation(relation, :where, other)
41
+ when String ; spawn_relation(relation, :where, other)
42
+ else ; other
43
+ end
44
+ end
45
+
46
+ private
47
+
48
+ def wrap_arel(node)
49
+ return node if Arel::Nodes::Equality === node
50
+ return Arel::Nodes::Grouping.new(String === node ? Arel.sql(node) : node)
51
+ end
52
+
53
+ def copy_values(to, from) # For Rails 5, 6
54
+ to.joins_values = from.joins_values if from.joins_values.any?
55
+ to.limit_value = from.limit_value
56
+ to.group_values = from.group_values if from.group_values.any?
57
+ to.distinct_value = from.distinct_value
58
+ to.order_values = from.order_values if from.order_values.any?
59
+ to.offset_value = from.offset_value
60
+ to.references_values = from.references_values
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,52 @@
1
+ class ActiveRecord::Relation
2
+ if method_defined?(:or)
3
+ if not method_defined?(:rails5_or)
4
+ alias rails5_or or
5
+ def or(*other)
6
+ rails5_or(RailsOr.parse_parameter(self, *other))
7
+ end
8
+ end
9
+ else
10
+ def or(*other)
11
+ other = RailsOr.parse_parameter(self, *other)
12
+ combining = group_values.any? ? :having : :where
13
+ left = RailsOr::WhereBindingMixs.new(send("#{combining}_values"), bind_values)
14
+ right = RailsOr::WhereBindingMixs.new(other.send("#{combining}_values"), other.bind_values)
15
+ common = left & right
16
+
17
+ left -= common
18
+ right -= common
19
+
20
+ if left.where_values.any? && right.where_values.any?
21
+ arel_or = Arel::Nodes::Or.new(
22
+ RailsOr.values_to_arel(left.where_values),
23
+ RailsOr.values_to_arel(right.where_values),
24
+ )
25
+ common += RailsOr::WhereBindingMixs.new([arel_or], left.bind_values + right.bind_values)
26
+ end
27
+
28
+ relation = RailsOr.get_current_scope(self)
29
+ if defined?(ActiveRecord::NullRelation) # Rails 3 does not have ActiveRecord::NullRelation
30
+ return other if relation.is_a?(ActiveRecord::NullRelation)
31
+ return relation if other.is_a?(ActiveRecord::NullRelation)
32
+ end
33
+ relation.send("#{combining}_values=", common.where_values)
34
+ relation.bind_values = common.bind_values
35
+ return relation
36
+ end
37
+ end
38
+
39
+ def or_not(*args) # Works in Rails 4+
40
+ self.or(klass.where.not(*args))
41
+ end
42
+
43
+ def or_having(hash)
44
+ self.or(RailsOr.spawn_relation(self, :having, hash))
45
+ end
46
+ end
47
+
48
+ class ActiveRecord::Base
49
+ def self.or(*args)
50
+ where('').or(*args)
51
+ end
52
+ end
@@ -0,0 +1,8 @@
1
+ module ActiveRecord::NullRelation
2
+ if method_defined?(:or) and not method_defined?(:rails5_or)
3
+ alias rails5_or or
4
+ def or(*other)
5
+ rails5_or(RailsOr.parse_parameter(self, *other))
6
+ end
7
+ end
8
+ end
@@ -1,3 +1,3 @@
1
- module RailsOr
2
- VERSION = "1.1.8"
3
- end
1
+ module RailsOr
2
+ VERSION = '1.1.9'
3
+ end
@@ -1,38 +1,38 @@
1
- class RailsOr::WhereBindingMixs
2
- attr_reader :where_values
3
- attr_reader :bind_values
4
-
5
- def initialize(where_values, bind_values)
6
- @where_values = where_values
7
- @bind_values = bind_values
8
- end
9
-
10
- def +(other)
11
- self.class.new(@where_values + other.where_values, @bind_values + other.bind_values)
12
- end
13
-
14
- def -(other)
15
- self.select{|node| !other.where_values.include?(node) }
16
- end
17
-
18
- def &(other)
19
- common_where_values = @where_values & other.where_values
20
- return self.select{|node| common_where_values.include?(node) }
21
- end
22
-
23
- def select
24
- binds_index = 0
25
- new_bind_values = []
26
- new_where_values = @where_values.select do |node|
27
- flag = yield(node)
28
- if not node.is_a?(String)
29
- binds_contains = node.grep(Arel::Nodes::BindParam).size
30
- pre_binds_index = binds_index
31
- binds_index += binds_contains
32
- (pre_binds_index...binds_index).each{|i| new_bind_values << @bind_values[i] } if flag
33
- end
34
- next flag
35
- end
36
- return self.class.new(new_where_values, new_bind_values)
37
- end
38
- end
1
+ class RailsOr::WhereBindingMixs
2
+ attr_reader :where_values
3
+ attr_reader :bind_values
4
+
5
+ def initialize(where_values, bind_values)
6
+ @where_values = where_values
7
+ @bind_values = bind_values
8
+ end
9
+
10
+ def +(other)
11
+ self.class.new(@where_values + other.where_values, @bind_values + other.bind_values)
12
+ end
13
+
14
+ def -(other)
15
+ select{|node| !other.where_values.include?(node) }
16
+ end
17
+
18
+ def &(other)
19
+ common_where_values = @where_values & other.where_values
20
+ return select{|node| common_where_values.include?(node) }
21
+ end
22
+
23
+ def select
24
+ binds_index = 0
25
+ new_bind_values = []
26
+ new_where_values = @where_values.select do |node|
27
+ flag = yield(node)
28
+ if not node.is_a?(String)
29
+ binds_contains = node.grep(Arel::Nodes::BindParam).size
30
+ pre_binds_index = binds_index
31
+ binds_index += binds_contains
32
+ (pre_binds_index...binds_index).each{|i| new_bind_values << @bind_values[i] } if flag
33
+ end
34
+ next flag
35
+ end
36
+ return self.class.new(new_where_values, new_bind_values)
37
+ end
38
+ end