Skip to content

Commit

Permalink
Merge pull request #3 from hopsoft/hopsoft/arel
Browse files Browse the repository at this point in the history
Remove string interpolation in queries
  • Loading branch information
hopsoft committed Feb 11, 2019
2 parents 8177dcc + cbc95a7 commit c6f76a3
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 26 deletions.
2 changes: 1 addition & 1 deletion Gemfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
source 'https://rubygems.org'
source "https://rubygems.org"

# Specify your gem's dependencies in tag_columns.gemspec
gemspec
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[![Lines of Code](http://img.shields.io/badge/lines_of_code-53-brightgreen.svg?style=flat)](http://blog.codinghorror.com/the-best-code-is-no-code-at-all/)
[![Lines of Code](http://img.shields.io/badge/lines_of_code-68-brightgreen.svg?style=flat)](http://blog.codinghorror.com/the-best-code-is-no-code-at-all/)
[![Maintainability](https://api.codeclimate.com/v1/badges/7503486b1bb494b5d976/maintainability)](https://codeclimate.com/github/hopsoft/tag_columns/maintainability)
[![Build Status](http://img.shields.io/travis/hopsoft/tag_columns.svg?style=flat)](https://travis-ci.org/hopsoft/tag_columns)
[![Coverage Status](https://img.shields.io/coveralls/hopsoft/tag_columns.svg?style=flat)](https://coveralls.io/r/hopsoft/tag_columns?branch=master)
Expand Down
61 changes: 39 additions & 22 deletions lib/tag_columns.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
require "tag_columns/version"

module TagColumns
extend ::ActiveSupport::Concern
extend ActiveSupport::Concern

module ClassMethods
def tag_columns_sanitize_list(values=[])
def tag_columns_sanitize_list(values = [])
values.select(&:present?).map(&:to_s).uniq.sort
end

Expand All @@ -20,29 +20,46 @@ def tag_columns(*column_names)
@tag_columns.each do |column_name, initialized|
next if initialized

column_name = column_name.to_s
method_name = column_name.downcase
quoted_column_name = "#{quoted_table_name}.#{connection.quote_column_name column_name}"

define_singleton_method :"unique_#{method_name}" do |conditions='true'|
result = connection.execute <<~QUERY
SELECT DISTINCT unnest(#{quoted_column_name}) AS unique_#{method_name}
FROM #{quoted_table_name}
WHERE #{where(conditions).to_sql.split(/ WHERE /i).last}
AND #{quoted_column_name} IS NOT NULL
AND #{quoted_column_name} != '{}'
ORDER BY unique_#{method_name}
QUERY
result.values.flatten

define_singleton_method :"unique_#{method_name}" do |conditions = "true"|
unnest = Arel::Nodes::NamedFunction.new("unnest", [arel_table[column_name]])
query = distinct.select(unnest).
where(conditions).
where.not(arel_table[column_name].eq(nil)).
where.not(arel_table[column_name].eq("{}"))
connection.execute(query.to_sql).values.flatten.sort
end

scope :"with_#{method_name}", -> { where("#{quoted_column_name}::text[] IS NOT NULL").where("#{quoted_column_name}::text[] != '{}'") }
scope :"without_#{method_name}", -> { where("#{quoted_column_name}::text[] IS NULL").or where("#{quoted_column_name}::text[] = '{}'") }
scope :"with_any_#{method_name}", ->(*tags) { where "#{quoted_column_name}::text[] && ARRAY[?]::text[]", tag_columns_sanitize_list(tags) }
scope :"with_all_#{method_name}", ->(*tags) { where "#{quoted_column_name}::text[] @> ARRAY[?]::text[]", tag_columns_sanitize_list(tags) }
scope :"without_any_#{method_name}", ->(*tags) { where.not "#{quoted_column_name}::text[] && ARRAY[?]::text[]", tag_columns_sanitize_list(tags) }
scope :"without_all_#{method_name}", ->(*tags) { where.not "#{quoted_column_name}::text[] @> ARRAY[?]::text[]", tag_columns_sanitize_list(tags) }
scope :"with_#{method_name}", -> {
where.not(arel_table[column_name].eq(nil)).where.not(arel_table[column_name].eq("{}"))
}

scope :"without_#{method_name}", -> {
where(arel_table[column_name].eq(nil)).or(where(arel_table[column_name].eq("{}")))
}

scope :"with_any_#{method_name}", ->(*tags) {
column_cast = Arel::Nodes::NamedFunction.new("CAST", [arel_table[column_name].as("text[]")])
value = Arel::Nodes::SqlLiteral.new(sanitize_sql_array(["ARRAY[?]", tag_columns_sanitize_list(tags)]))
value_cast = Arel::Nodes::NamedFunction.new("CAST", [value.as("text[]")])
overlap = Arel::Nodes::InfixOperation.new("&&", column_cast, value_cast)
where overlap
}

before_validation Proc.new { self[column_name] = self.class.tag_columns_sanitize_list(self[column_name]) }
scope :"with_all_#{method_name}", ->(*tags) {
column_cast = Arel::Nodes::NamedFunction.new("CAST", [arel_table[column_name].as("text[]")])
value = Arel::Nodes::SqlLiteral.new(sanitize_sql_array(["ARRAY[?]", tag_columns_sanitize_list(tags)]))
value_cast = Arel::Nodes::NamedFunction.new("CAST", [value.as("text[]")])
contains = Arel::Nodes::InfixOperation.new("@>", column_cast, value_cast)
where contains
}

scope :"without_any_#{method_name}", ->(*tags) { where.not id: public_send(:"with_any_#{method_name}", *tags) }
scope :"without_all_#{method_name}", ->(*tags) { where.not id: public_send(:"with_all_#{method_name}", *tags) }

before_validation -> { self[column_name] = self.class.tag_columns_sanitize_list(self[column_name]) }

define_method :"has_any_#{method_name}?" do |*values|
values = self.class.tag_columns_sanitize_list(values)
Expand All @@ -54,7 +71,7 @@ def tag_columns(*column_names)
values = self.class.tag_columns_sanitize_list(values)
existing = self.class.tag_columns_sanitize_list(self[column_name] || [])
(values & existing).size == values.size
end
end

alias_method :"has_#{method_name.singularize}?", :"has_all_#{method_name}?"

Expand Down
2 changes: 1 addition & 1 deletion lib/tag_columns/version.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module TagColumns
VERSION = "0.1.6"
VERSION = "0.1.7"
end
1 change: 0 additions & 1 deletion tag_columns.gemspec
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
# coding: utf-8
require File.expand_path("../lib/tag_columns/version", __FILE__)

Gem::Specification.new do |gem|
Expand Down

0 comments on commit c6f76a3

Please sign in to comment.