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

Antwort per Email an