lib/torque/postgresql/auxiliary_statement.rb in torque-postgresql-0.1.2 vs lib/torque/postgresql/auxiliary_statement.rb in torque-postgresql-0.1.3
- old
+ new
@@ -58,11 +58,11 @@
base.name
end
# Get the arel version of the statement table
def table
- @table ||= Arel::Table.new(table_name)
+ @table ||= ::Arel::Table.new(table_name)
end
# Get the name of the table of the configurated statement
def table_name
@table_name ||= self.name.demodulize.split('_').first.underscore
@@ -78,13 +78,15 @@
@query_table ||= query.arel_table
end
# Project a column on a given table, or use the column table
def project(column, arel_table = nil)
- if column.to_s.include?('.')
+ if column.respond_to?(:as)
+ return column
+ elsif column.to_s.include?('.')
table_name, column = column.to_s.split('.')
- arel_table = Arel::Table.new(table_name)
+ arel_table = ::Arel::Table.new(table_name)
end
arel_table ||= table
arel_table[column.to_s]
end
@@ -100,49 +102,12 @@
defined?(@query) && @query
end
# Setup the class
def setup!
- # attributes key:
- # Provides a map of attributes to be exposed to the main query.
- #
- # For instace, if the statement query has an 'id' column that you
- # want it to be accessed on the main query as 'item_id',
- # you can use:
- # attributes id: :item_id
- #
- # If its statement has more tables, and you want to expose those
- # fields, then:
- # attributes 'table.name': :item_name
- #
- # join_type key:
- # Changes the type of the join and set the constraints
- #
- # The left side of the hash is the source table column, the right
- # side is the statement table column, now it's only accepting '='
- # constraints
- # join id: :user_id
- # join id: :'user.id'
- # join 'post.id': :'user.last_post_id'
- #
- # It's possible to change the default type of join
- # join :left, id: :user_id
- #
- # join key:
- # Changes the type of the join
- #
- # query key:
- # Save the query command to be performand
- #
- # requires key:
- # Indicates dependencies with another statements
- #
- # polymorphic key:
- # Indicates a polymorphic relationship, with will affect the way the
- # auto join works, by giving a polymorphic connection
settings = Settings.new(self)
- @config.call(settings)
+ settings.instance_exec(settings, &@config)
@join_type = settings.join_type || :inner
@requires = Array[settings.requires].flatten.compact
@query = settings.query
@@ -230,39 +195,43 @@
exposed_attributes + @select.values.map(&method(:project))
end
# Build the statement on the given arel and return the WITH statement
def build_arel(arel, base)
- list = []
-
- # Process dependencies
- if requires.present?
- requires.each do |dependent|
- next if base.auxiliary_statements.key?(dependent)
-
- instance = AuxiliaryStatement.instantiate(dependent, base)
- base.auxiliary_statements[dependent] = instance
- list << instance.build_arel(arel, base)
- end
- end
-
# Build the join for this statement
arel.join(table, arel_join).on(*join_columns)
# Return the subquery for this statement
- list << Arel::Nodes::As.new(table, mount_query)
+ ::Arel::Nodes::As.new(table, mount_query)
end
+ # Get the bound attributes from statement qeury
+ def bound_attributes
+ return [] unless relation_query?(self.class.query)
+ self.class.query.send(:bound_attributes)
+ end
+
+ # Ensure that all the dependencies are loaded in the base relation
+ def ensure_dependencies!(base)
+ requires.each do |dependent|
+ next if base.auxiliary_statements.key?(dependent)
+
+ instance = AuxiliaryStatement.instantiate(dependent, base)
+ instance.ensure_dependencies!(base)
+ base.auxiliary_statements[dependent] = instance
+ end
+ end
+
private
# Get the class of the join on arel
def arel_join
case @join_type
- when :inner then Arel::Nodes::InnerJoin
- when :left then Arel::Nodes::OuterJoin
- when :right then Arel::Nodes::RightOuterJoin
- when :full then Arel::Nodes::FullOuterJoin
+ when :inner then ::Arel::Nodes::InnerJoin
+ when :left then ::Arel::Nodes::OuterJoin
+ when :right then ::Arel::Nodes::RightOuterJoin
+ when :full then ::Arel::Nodes::FullOuterJoin
else
raise ArgumentError, <<-MSG.strip
The '#{@join_type}' is not implemented as a join type.
MSG
end
@@ -270,22 +239,23 @@
# Mount the query base on it's class
def mount_query
klass = self.class
query = klass.query
- uses = @uses.map(&klass.parent.connection.method(:quote))
+ uses = @uses
# Call a proc to get the query
if query.respond_to?(:call)
query = query.call(*uses)
uses = []
end
# Prepare the query depending on its type
if query.is_a?(String)
- Arel::Nodes::SqlLiteral.new("(#{query})" % uses)
+ uses.map!(&klass.parent.connection.method(:quote))
+ ::Arel::Nodes::SqlLiteral.new("(#{query})" % uses)
elsif relation_query?(query)
- query.select(*select_columns).send(:build_arel)
+ query.select(*select_columns).arel
else
raise ArgumentError, <<-MSG.strip
Only String and ActiveRecord::Base objects are accepted as query objects,
#{query.class.name} given for #{self.class.name}.
MSG