Skip to content

Instantly share code, notes, and snippets.

@inopinatus
Created April 25, 2019 07:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save inopinatus/c3996fa976a26aa1e1011fb2a567fd4c to your computer and use it in GitHub Desktop.
Save inopinatus/c3996fa976a26aa1e1011fb2a567fd4c to your computer and use it in GitHub Desktop.
SHA digest queries for ActiveRecord + postgresql
# frozen_string_literal: true
module DigestQueries
def predicate_builder
@predicate_builder ||= super.tap do |pb|
pb.register_handler(Digest::Instance, DigestHandler.new(pb))
end
end
class DigestHandler
def initialize(predicate_builder)
@predicate_builder = predicate_builder
end
def call(attribute, value)
type = case value
when Digest::MD5; 'md5'
when Digest::SHA1; 'sha1'
when Digest::SHA2; "sha#{value.length * 8}"
when Digest::SHA256; 'sha256'
when Digest::SHA384; 'sha384'
when Digest::SHA512; 'sha512'
else
raise ArgumentError, "Did not recognise #{value.inspect} as a Digest object"
end
binvalue = ActiveModel::Type::Binary::Data.new(value.digest)
bind = predicate_builder.build_bind_attribute(attribute.name, binvalue)
digest(attribute, type).eq(bind)
end
private
attr_reader :predicate_builder
def digest(attribute, type)
Arel::Nodes::NamedFunction.new("digest", [attribute, Arel::Nodes::Quoted.new(type)])
end
end
end
ActiveRecord::Base.extend(DigestQueries)
@inopinatus
Copy link
Author

enables MyModel.where(text: Digest::SHA256.new.update(text)) c.f. https://www.reddit.com/r/rails/comments/bgtn9o/best_and_fastest_way_to_search_for_text_in/elouksy/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment