/lib/polo/translator.rb
https://github.com/IFTTT/polo · Ruby · 84 lines · 60 code · 18 blank · 6 comment · 9 complexity · fb71cd2547c2c20eed56d31f41c4079c MD5 · raw file
- require "polo/sql_translator"
- require "polo/configuration"
- module Polo
- class Translator
- # Public: Creates a new Polo::Collector
- #
- # selects - An array of SELECT queries
- #
- def initialize(selects, configuration=Configuration.new)
- @selects = selects
- @configuration = configuration
- end
- # Public: Translates SELECT queries into INSERTS.
- #
- def translate
- SqlTranslator.new(instances, @configuration).to_sql.uniq
- end
- def instances
- active_record_selects, raw_selects = @selects.partition{|s| s[:klass]}
- active_record_instances = active_record_selects.flat_map do |select|
- select[:klass].find_by_sql(select[:sql]).to_a
- end
- if fields = @configuration.blacklist
- obfuscate!(active_record_instances, fields)
- end
- raw_instance_values = raw_selects.flat_map do |select|
- table_name = select[:sql][/^SELECT .* FROM (?:"|`)([^"`]+)(?:"|`)/, 1]
- select[:connection].select_all(select[:sql]).map { |values| {table_name: table_name, values: values} }
- end
- active_record_instances + raw_instance_values
- end
- private
- def obfuscate!(instances, fields)
- instances.each do |instance|
- next if intersection(instance.attributes.keys, fields).empty?
- fields.each do |field, strategy|
- field = field.to_s
- if table = table_name(field)
- field = field_name(field)
- end
- correct_table = table.nil? || instance.class.table_name == table
- if correct_table && instance.attributes[field]
- instance.send("#{field}=", new_field_value(field, strategy, instance))
- end
- end
- end
- end
- def field_name(field)
- field.to_s.include?('.') ? field.split('.').last : field.to_s
- end
- def table_name(field)
- field.to_s.include?('.') ? field.split('.').first : nil
- end
- def intersection(attrs, fields)
- attrs & fields.map { |pair| field_name(pair.first) }
- end
- def new_field_value(field, strategy, instance)
- value = instance.attributes[field]
- if strategy.nil?
- value.split("").shuffle.join
- else
- strategy.arity == 1 ? strategy.call(value) : strategy.call(value, instance)
- end
- end
- end
- end