Skip to content

Commit

Permalink
Merge pull request #26 from khiav223577/adjust/coding_style
Browse files Browse the repository at this point in the history
Add rubocop.yml and adjust coding style
  • Loading branch information
khiav223577 committed Oct 24, 2018
2 parents ed2c53e + 3bd3412 commit 7ee85ba
Show file tree
Hide file tree
Showing 9 changed files with 1,419 additions and 188 deletions.
1,225 changes: 1,225 additions & 0 deletions .rubocop.yml

Large diffs are not rendered by default.

147 changes: 44 additions & 103 deletions lib/rails_or.rb
@@ -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
52 changes: 52 additions & 0 deletions lib/rails_or/active_record/extension.rb
@@ -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
8 changes: 8 additions & 0 deletions lib/rails_or/patches/null_relation.rb
@@ -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
2 changes: 1 addition & 1 deletion lib/rails_or/version.rb
@@ -1,3 +1,3 @@
module RailsOr
VERSION = "1.1.8"
VERSION = '1.1.8'
end
4 changes: 2 additions & 2 deletions lib/rails_or/where_binding_mixs.rb
Expand Up @@ -12,12 +12,12 @@ def +(other)
end

def -(other)
self.select{|node| !other.where_values.include?(node) }
select{|node| !other.where_values.include?(node) }
end

def &(other)
common_where_values = @where_values & other.where_values
return self.select{|node| common_where_values.include?(node) }
return select{|node| common_where_values.include?(node) }
end

def select
Expand Down

0 comments on commit 7ee85ba

Please sign in to comment.