"self" and or
============= This lines mean the same: User.smql :self => {:id => 1} User.smql :id => 1 User.smql 'self.id' => 1 User.smql 'self.self.self.self.id' => 1 self is like a reflection to itself. Very userful if you need the new disjunction: User.smql :self => [{:surname => 'Mueller', :givenname => 'Michael'}, {:givenname => 'Horst', :surname => 'Schlemmer'}], :firm => {:name => 'Hotel an der Elbe'} SmqlToAR::Column ---------------- Rejects every `self`, so it is really like no self, but you use `'self'` as like as a simple reflection. You can ask, if it is self via Column#self? SmqlToAR::QueryBuilder ====================== joins: The old `#join`. Renames because SmqlToAR::And and SmqlToAR::Or which has Array#join, so we cannot delegate `#join` to the QueryBuilder. `#where` -------- Now only one argument! Needed for SmqlToAR::And and SmqlToAR::Or. `#build` will generates LEFT OUTER JOINS now. Needed for disjunctions. The most queries will work like before. Problems: User.smql :articles => {} Before it will return all users with articles, now it will return also users without articles. If you want to have only all users with articles, you ask: User.smql :articles => {:id => true} Will fail if id IS NULL, but this should not happen. ;) `SmqlToAR::And` and `SmqlToAR::Or` ================================== `SmqlToAR::QueryBuilder`-proxies. QueryBuilder let them build where-clauses. And will will produce a conjunction and Or a disjunction of course. They delegates all QueryBuilder-methods to QueryBuilder. Only `#where` will stored local and `#build` will do it partial. They have the same superclass: `SmqlToAR::SubBuilder`. The small changes ================= * `SmqlToAR.reload_library`: Reloads SmqlToAR-lib. Useful while development. * `SmqlToAR::ConditionTypes#conditions`: Return all Conditions. `#try_parse` uses it. * Some classes have a new `#inspect`. * `SmqlToAR::ConditionTypes#Exists` / `NotExists`: `{:id => true}` / `{:id => false}`: This object has setted an id or not? `#id` must exists as column of course! Uses `IS NOT NULL` and `IS NULL`.
This commit is contained in:
parent
93fd3eeda4
commit
2fdc45d1d5
3 changed files with 184 additions and 73 deletions
|
@ -107,7 +107,9 @@ class SmqlToAR
|
|||
|
||||
# Model der Relation `rel` von `model`
|
||||
def self.model_of model, rel
|
||||
model.reflections[ rel.to_sym].andand.klass
|
||||
rel = rel.to_sym
|
||||
r = model.reflections[ rel].andand.klass
|
||||
r.nil? && :self == rel ? model : r
|
||||
end
|
||||
|
||||
# Eine Spalte in einer Tabelle, relativ zu `Column#model`.
|
||||
|
@ -121,7 +123,7 @@ class SmqlToAR
|
|||
def initialize model, *col
|
||||
@model = model
|
||||
@last_model = nil
|
||||
*@path, @col = Array.wrap( col).collect( &it.to_s.split( /[.\/]/)).flatten.collect( &:to_sym)
|
||||
*@path, @col = *Array.wrap( col).collect( &it.to_s.split( /[.\/]/)).flatten.collect( &:to_sym).reject( &it==:self)
|
||||
end
|
||||
|
||||
def last_model
|
||||
|
@ -131,9 +133,12 @@ class SmqlToAR
|
|||
def each
|
||||
model = @model
|
||||
@path.each do |rel|
|
||||
model = SmqlToAR.model_of model, rel
|
||||
return false unless model
|
||||
yield rel, model
|
||||
rel = rel.to_sym
|
||||
unless :self == rel
|
||||
model = SmqlToAR.model_of model, rel
|
||||
return false unless model
|
||||
yield rel, model
|
||||
end
|
||||
end
|
||||
model
|
||||
end
|
||||
|
@ -158,20 +163,21 @@ class SmqlToAR
|
|||
def joins builder = nil, table = nil, &exe
|
||||
pp = []
|
||||
table = Array.wrap table
|
||||
exe ||= builder ? lambda {|j, m| builder.join table+j, m} : Array.method( :[])
|
||||
exe ||= builder ? lambda {|j, m| builder.joins table+j, m} : Array.method( :[])
|
||||
collect do |rel, model|
|
||||
pp.push rel
|
||||
exe.call pp, model
|
||||
end
|
||||
end
|
||||
def length() @path.length+1 end
|
||||
def size() @path.size+1 end
|
||||
def to_a() @path+[@col] end
|
||||
def self?() !@col end
|
||||
def length() @path.length+(self.self? ? 0 : 1) end
|
||||
def size() @path.size+(self.self? ? 0 : 1) end
|
||||
def to_a() @path+(self.self? ? [] : [@col]) end
|
||||
def to_s() to_a.join '.' end
|
||||
def to_sym() to_s.to_sym end
|
||||
def to_json() to_s end
|
||||
def inspect() "#<Column: #{model} #{to_s}>" end
|
||||
def relation() SmqlToAR.model_of last_model, @col end
|
||||
def relation() self.self? ? model : SmqlToAR.model_of( last_model, @col) end
|
||||
def allowed?() ! self.protected? end
|
||||
def child?() @path.empty? and !!relation end
|
||||
end
|
||||
|
@ -225,9 +231,9 @@ class SmqlToAR
|
|||
self
|
||||
end
|
||||
|
||||
def build prefix = nil, base_table = nil
|
||||
def build prefix = nil
|
||||
benchmark 'SMQL build query' do
|
||||
@builder = QueryBuilder.new @model, prefix, base_table
|
||||
@builder = QueryBuilder.new @model, prefix
|
||||
table = @builder.base_table
|
||||
@conditions.each &it.build( builder, table)
|
||||
end
|
||||
|
@ -252,4 +258,12 @@ class SmqlToAR
|
|||
def self.to_ar *params
|
||||
new( *params).to_ar
|
||||
end
|
||||
|
||||
def self.reload_library
|
||||
lib_dir = File.dirname __FILE__
|
||||
fj = lambda {|*a| File.join lib_dir, *a }
|
||||
load fj.call( 'smql_to_ar.rb')
|
||||
load fj.call( 'smql_to_ar', 'condition_types.rb')
|
||||
load fj.call( 'smql_to_ar', 'query_builder.rb')
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue