lib/wise_gopher/base.rb in wise_gopher-0.1.0 vs lib/wise_gopher/base.rb in wise_gopher-0.2.0

- old
+ new

@@ -5,30 +5,41 @@ module WiseGopher # Main inteface of the gem. Class to be inherited by the query class class Base def self.inherited(base) base.class_eval do - @params = {} + @raw_params = {} + @params = {} end base.include Methods base.extend ClassMethods end # class methods for WiseGopher::Base module ClassMethods - attr_reader :row_class, :params + attr_reader :row_class, :params, :raw_params def query(query) const_set "QUERY", query.freeze end def param(name, type, transform = nil) - param = WiseGopher::Param.new(name, type, transform) + new_param = WiseGopher::Param.new(name, type, transform) - params[param.name] = param + ensure_param_name_is_available(new_param.name) + + params[new_param.name] = new_param end + def raw_param(name, **kwargs) + raw_param = WiseGopher::RawParam.new(name, **kwargs) + + ensure_param_name_is_available(raw_param.name) + + raw_params[raw_param.name] = raw_param + end + def row(base = nil, &block) @row_class ||= base || define_generic_row_class @row_class.include WiseGopher::Row @@ -45,21 +56,31 @@ ensure_all_params_are_given(inputs) new(inputs).execute end + def ensure_all_params_are_given(inputs = {}) + missing_params = required_params.keys - inputs.keys.map(&:to_s) + + raise WiseGopher::ArgumentError, required_params.slice(*missing_params) if missing_params.any? + end + private def define_generic_row_class @row_class = const_set "Row", Class.new end - def ensure_all_params_are_given(inputs = {}) - missing_params = params.keys - inputs.keys.map(&:to_s) + def ensure_param_name_is_available(name) + return unless params[name] || raw_params[name] - raise WiseGopher::ArgumentError, params.slice(*missing_params) if missing_params.any? + raise WiseGopher::ParamAlreadyDeclared, name end + + def required_params + params.merge(raw_params.reject { |_name, raw_param| raw_param.optional? }) + end end # instance methods for WiseGopher::Base module Methods extend ::Forwardable @@ -70,44 +91,54 @@ @inputs = inputs @binds = [] @bind_symbol = WiseGopher.postgresql? ? +"$1" : "?" @query_prepared = false + self.class.ensure_all_params_are_given(inputs) + prepare_query end def execute ensure_row_class_is_declared - result = connection.exec_query(@query.squish, query_class.to_s, @binds, prepare: true) + result = connection.exec_query(query.squish, query_class.to_s, @binds, prepare: true) ensure_all_columns_are_declared(result) result.entries.map { |entry| row_class.new(entry) } end def prepare_query return if @query_prepared - @query = query_class::QUERY.dup + prepare_raw_params + prepare_params + + @query_prepared = true + end + + private + + def prepare_params query_class.params.each do |name, param| name = name.to_sym value = @inputs[name] bind_params(value, param) end - - @query_prepared = true end - private - def query_class self.class end + def query + @query ||= query_class::QUERY.dup + end + def bind_params(value, param) if value.is_a? Array bind_collection_param(value, param) else bind_single_param(value, param) @@ -115,23 +146,23 @@ end def bind_collection_param(values, param) bindings = values.map { use_bind_symbol } - replace_binding_placeholder(param.name, bindings.join(", ")) + replace_placeholder(param.name, bindings.join(", ")) values.each { |value| register_binding(value, param) } end def bind_single_param(value, param) - replace_binding_placeholder(param.name, use_bind_symbol) + replace_placeholder(param.name, use_bind_symbol) register_binding(value, param) end - def replace_binding_placeholder(name, binding_symbol) - @query.gsub!(/{{ ?#{name} ?}}/, binding_symbol) + def replace_placeholder(name, value_to_insert) + query.gsub!(/{{ ?#{name} ?}}/, value_to_insert) end def register_binding(value, param) @binds << param.build_bind(value) end @@ -158,9 +189,18 @@ raise UndeclaredColumns, undeclared_columns if undeclared_columns.any? end def connection ActiveRecord::Base.connection + end + + def prepare_raw_params + query_class.raw_params.each do |name, param| + name = name.to_sym + value = @inputs[name] + + replace_placeholder(name, param.to_s(value)) + end end end end end