Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #26 from khiav223577/adjust/coding_style
Add rubocop.yml and adjust coding style
- Loading branch information
Showing
9 changed files
with
1,419 additions
and
188 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,119 +1,60 @@ | ||
require "rails_or/version" | ||
require "rails_or/where_binding_mixs" | ||
require 'rails_or/version' | ||
require 'rails_or/where_binding_mixs' | ||
require 'active_record' | ||
require 'rails_or/patches/null_relation' if defined?(ActiveRecord::NullRelation) | ||
require 'rails_or/active_record/extension' | ||
|
||
if defined?(ActiveRecord::NullRelation) | ||
module ActiveRecord::NullRelation | ||
if method_defined?(:or) | ||
if not method_defined?(:rails5_or) | ||
alias_method :rails5_or, :or | ||
def or(*other) | ||
rails5_or(rails_or_parse_parameter(*other)) | ||
end | ||
end | ||
end | ||
end | ||
end | ||
|
||
class ActiveRecord::Relation | ||
module RailsOr | ||
IS_RAILS3_FLAG = Gem::Version.new(ActiveRecord::VERSION::STRING) < Gem::Version.new('4.0.0') | ||
IS_RAILS5_FLAG = Gem::Version.new(ActiveRecord::VERSION::STRING) >= Gem::Version.new('5.0.0') | ||
FROM_VALUE_METHOD = %i[from_value from_clause].find{|s| method_defined?(s) } | ||
FROM_VALUE_METHOD = %i[from_value from_clause].find{|s| ActiveRecord::Relation.method_defined?(s) } | ||
ASSIGN_FROM_VALUE = :"#{FROM_VALUE_METHOD}=" | ||
if method_defined?(:or) | ||
if not method_defined?(:rails5_or) | ||
alias_method :rails5_or, :or | ||
def or(*other) | ||
return rails5_or(rails_or_parse_parameter(*other)) | ||
end | ||
end | ||
else | ||
def or(*other) | ||
other = rails_or_parse_parameter(*other) | ||
combining = group_values.any? ? :having : :where | ||
left = RailsOr::WhereBindingMixs.new(self.send("#{combining}_values"), self.bind_values) | ||
right = RailsOr::WhereBindingMixs.new(other.send("#{combining}_values"), other.bind_values) | ||
common = left & right | ||
|
||
left -= common | ||
right -= common | ||
|
||
if left.where_values.any? && right.where_values.any? | ||
arel_or = Arel::Nodes::Or.new( | ||
rails_or_values_to_arel(left.where_values), | ||
rails_or_values_to_arel(right.where_values), | ||
) | ||
common += RailsOr::WhereBindingMixs.new([arel_or], left.bind_values + right.bind_values) | ||
end | ||
|
||
relation = rails_or_get_current_scope | ||
if defined?(ActiveRecord::NullRelation) # Rails 3 does not have ActiveRecord::NullRelation | ||
return other if relation.is_a?(ActiveRecord::NullRelation) | ||
return relation if other.is_a?(ActiveRecord::NullRelation) | ||
end | ||
relation.send("#{combining}_values=", common.where_values) | ||
relation.bind_values = common.bind_values | ||
return relation | ||
class << self | ||
def values_to_arel(values) | ||
values.map!{|x| wrap_arel(x) } | ||
return (values.size > 1 ? Arel::Nodes::And.new(values) : values) | ||
end | ||
end | ||
|
||
def or_not(*args) # Works in Rails 4+ | ||
self.or(klass.where.not(*args)) | ||
end | ||
|
||
def or_having(hash) | ||
self.or(rails_or_spwan_relation(:having, hash)) | ||
end | ||
|
||
private | ||
|
||
def rails_or_values_to_arel(values) | ||
values.map!{|x| rails_or_wrap_arel(x) } | ||
return (values.size > 1 ? Arel::Nodes::And.new(values) : values) | ||
end | ||
|
||
def rails_or_wrap_arel(node) | ||
return node if Arel::Nodes::Equality === node | ||
return Arel::Nodes::Grouping.new(String === node ? Arel.sql(node) : node) | ||
end | ||
def spwan_relation(relation, method, condition) | ||
new_relation = relation.klass.send(method, condition) | ||
new_relation.send(ASSIGN_FROM_VALUE, relation.send(FROM_VALUE_METHOD)) | ||
copy_values(new_relation, relation) if IS_RAILS5_FLAG | ||
return new_relation | ||
end | ||
|
||
def rails_or_parse_parameter(*other) | ||
other = other.first if other.size == 1 | ||
case other | ||
when Hash ; rails_or_spwan_relation(:where, other) | ||
when Array ; rails_or_spwan_relation(:where, other) | ||
when String ; rails_or_spwan_relation(:where, other) | ||
else ; other | ||
def get_current_scope(relation) | ||
return relation.clone if IS_RAILS3_FLAG | ||
# ref: https://github.com/rails/rails/blob/17ef58db1776a795c9f9e31a1634db7bcdc3ecdf/activerecord/lib/active_record/scoping/named.rb#L26 | ||
# return relation.all # <- cannot use this because some gem changes this method's behavior | ||
return (relation.current_scope || relation.default_scoped).clone | ||
end | ||
end | ||
|
||
def rails_or_copy_values_to(relation) # For Rails 5 | ||
relation.joins_values = self.joins_values | ||
relation.limit_value = self.limit_value | ||
relation.group_values = self.group_values | ||
relation.distinct_value = self.distinct_value | ||
relation.order_values = self.order_values | ||
relation.offset_value = self.offset_value | ||
relation.references_values = self.references_values | ||
end | ||
def parse_parameter(relation, *other) | ||
other = other.first if other.size == 1 | ||
case other | ||
when Hash ; spwan_relation(relation, :where, other) | ||
when Array ; spwan_relation(relation, :where, other) | ||
when String ; spwan_relation(relation, :where, other) | ||
else ; other | ||
end | ||
end | ||
|
||
def rails_or_spwan_relation(method, condition) | ||
relation = klass.send(method, condition) | ||
relation.send(ASSIGN_FROM_VALUE, send(FROM_VALUE_METHOD)) | ||
rails_or_copy_values_to(relation) if IS_RAILS5_FLAG | ||
return relation | ||
end | ||
private | ||
|
||
def rails_or_get_current_scope | ||
return self.clone if IS_RAILS3_FLAG | ||
# ref: https://github.com/rails/rails/blob/17ef58db1776a795c9f9e31a1634db7bcdc3ecdf/activerecord/lib/active_record/scoping/named.rb#L26 | ||
# return self.all # <- cannot use this because some gem changes this method's behavior | ||
return (self.current_scope || self.default_scoped).clone | ||
end | ||
end | ||
def wrap_arel(node) | ||
return node if Arel::Nodes::Equality === node | ||
return Arel::Nodes::Grouping.new(String === node ? Arel.sql(node) : node) | ||
end | ||
|
||
class ActiveRecord::Base | ||
def self.or(*args) | ||
self.where('').or(*args) | ||
def copy_values(to, from) # For Rails 5 | ||
to.joins_values = from.joins_values | ||
to.limit_value = from.limit_value | ||
to.group_values = from.group_values | ||
to.distinct_value = from.distinct_value | ||
to.order_values = from.order_values | ||
to.offset_value = from.offset_value | ||
to.references_values = from.references_values | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
class ActiveRecord::Relation | ||
if method_defined?(:or) | ||
if not method_defined?(:rails5_or) | ||
alias rails5_or or | ||
def or(*other) | ||
rails5_or(RailsOr.parse_parameter(self, *other)) | ||
end | ||
end | ||
else | ||
def or(*other) | ||
other = RailsOr.parse_parameter(self, *other) | ||
combining = group_values.any? ? :having : :where | ||
left = RailsOr::WhereBindingMixs.new(send("#{combining}_values"), bind_values) | ||
right = RailsOr::WhereBindingMixs.new(other.send("#{combining}_values"), other.bind_values) | ||
common = left & right | ||
|
||
left -= common | ||
right -= common | ||
|
||
if left.where_values.any? && right.where_values.any? | ||
arel_or = Arel::Nodes::Or.new( | ||
RailsOr.values_to_arel(left.where_values), | ||
RailsOr.values_to_arel(right.where_values), | ||
) | ||
common += RailsOr::WhereBindingMixs.new([arel_or], left.bind_values + right.bind_values) | ||
end | ||
|
||
relation = RailsOr.get_current_scope(self) | ||
if defined?(ActiveRecord::NullRelation) # Rails 3 does not have ActiveRecord::NullRelation | ||
return other if relation.is_a?(ActiveRecord::NullRelation) | ||
return relation if other.is_a?(ActiveRecord::NullRelation) | ||
end | ||
relation.send("#{combining}_values=", common.where_values) | ||
relation.bind_values = common.bind_values | ||
return relation | ||
end | ||
end | ||
|
||
def or_not(*args) # Works in Rails 4+ | ||
self.or(klass.where.not(*args)) | ||
end | ||
|
||
def or_having(hash) | ||
self.or(RailsOr.spwan_relation(self, :having, hash)) | ||
end | ||
end | ||
|
||
class ActiveRecord::Base | ||
def self.or(*args) | ||
where('').or(*args) | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
module ActiveRecord::NullRelation | ||
if method_defined?(:or) and not method_defined?(:rails5_or) | ||
alias rails5_or or | ||
def or(*other) | ||
rails5_or(RailsOr.parse_parameter(self, *other)) | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,3 @@ | ||
module RailsOr | ||
VERSION = "1.1.8" | ||
VERSION = '1.1.8' | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.