du kannst ein ARec objekt nach seinem arel_table fragen und dem arel methoden 
übergeben

Beste Grüße


Thomas von Deyen
magic labs*

(von unterwegs gesendet)

Am 04.02.2012 um 20:14 schrieb Michael Schuerig <michael.li...@schuerig.de>:

> 
> Ich arbeite zur Zeit daran, eine alte (Rails 2.1) Anwendung auf Rails 
> 3.2 umzustellen. Dabei möchte ich auch möglichst viel handgeschriebenes 
> SQL durch schönere Ausdrucksmittel ersetzen.
> 
> Noch recht harmlose Fälle sehen so aus
> 
>  class Document < ActiveRecord::Base
>    scope :newest,
>      joins(
>        'LEFT OUTER JOIN documents newer
>          ON newer.doc_code = documents.doc_code
>          AND documents.version < newer.version'
>      ).
>      where('newer.doc_code IS NULL').
>      readonly(false)
>  end
> 
> Hier habe ich readonly(false) schon hinzufügen müssen, weil ARec 
> andernfalls die zurückgegebenen Objekte als readonly markiert. Das 
> passiert gerade weil der Join nur als "opaker" String angegeben ist.
> 
> Ein vielleicht naheliegender Ausweg sieht so aus
> 
>  class Document < ActiveRecord::Base
>    has_many :newer_versions,
>      :class_name  => 'Document',
>      :foreign_key => :doc_code,
>      :primary_key => :doc_code,
>      :conditions  => 
>        'documents.version < newer_versions_documents.version'
> 
>    scope :newest,
>      includes(:newer_versions).
>      where(:newer_versions => { :doc_code => nil })
>  end
> 
> Hier generiert ARec ein SELECT-Statement, das auch die (leeren) Spalten 
> von newer_versions_documents zurückliefert. Nicht wirklich schlimm, aber 
> unschön. Vor allem aber funktioniert dieser Trick zwar in diesem Fall, 
> aber etwas Subqueries, die ich auch habe, lassen sich damit nicht 
> ausdrücken.
> 
> Aber war da nicht was? ActiveRecord 3.x basiert doch auf ARel und man 
> kann die irgendwie gemeinsam nutzen. Wenn es mir denn gelingen würde. 
> Ich finde einfach keine Beispiele, die zeigen, wie es gehen könnte.
> 
> Ich kann den gewünschten LEFT OUTER JOIN mit ARel-Mitteln so ausdrücken:
> 
>  docs = Document.arel_table
>  newer = docs.alias
>  loj = docs.join(newer, Arel::Nodes::OuterJoin).
>          on(newer[:doc_code].eq(docs[:doc_code]).
>          and(docs[:version].lt(newer[:version]))).
>          where(newer[:doc_code].eq(nil))
> 
> Aber wie baue ich das in einen Scope ein? Ich brauche etwas, was auch 
> mit anderen Scopes, die für Document definiert sind, verkettet werden 
> kann.
> 
> Weiß jemand, wie es geht?
> 
> Michael
> 
> -- 
> Michael Schuerig
> mailto:mich...@schuerig.de
> http://www.schuerig.de/michael/
> _______________________________________________
> rubyonrails-ug mailing list
> rubyonrails-ug@headflash.com
> http://mailman.headflash.com/listinfo/rubyonrails-ug
_______________________________________________
rubyonrails-ug mailing list
rubyonrails-ug@headflash.com
http://mailman.headflash.com/listinfo/rubyonrails-ug

Antwort per Email an