2010-04-22 2 views
5

Probleme mit AR 2.3.5, zB:Wie man den Typ des ActiveRecord-Attributs erzwingt, das zurückgegeben wird: Wählen Sie die Phrase in der Join-Tabelle aus?

users = User.all(:select => "u.id, c.user_id", :from => "users u, connections c", 
     :conditions => ...) 

Returns, zB:

=> [#<User id: 1000>] 
>> users.first.attributes 
=> {"id"=>1000, "user_id"=>"1000"} 

Beachten Sie, dass AR die id des Modells kehrt als numerische gesucht, aber die user_id des verbundenen Modell ausgewählt als String, obwohl beide int(11) im Datenbankschema sind.

Wie könnte ich diesen Abfragetyp besser erstellen, um Spalten von Tabellen auszuwählen, die mehrere Modelle unterstützen, und ihren natürlichen Typ anstatt String abzurufen? Scheint so, als ob AR irgendwo dazwischen stochert. Wie könnte ich die zurückgegebenen Typen zur AR-Ladezeit zwingen und nicht auf jeden Post-hoc-Zugriff .to_i (usw.) anheften?

+1

Können Sie erklären, was „Verbindungen“ ist, und wie wird es den Benutzern zu tun? – kikito

Antwort

1

Warum verwenden Sie: aus => "Benutzer" in einem User.method? Im Folgenden wird tun eine innere Verknüpfung (das ist, was Sie sowieso tun)

users = User.all(:include => :connections, :select => "users.id, connections.user_id", :conditions => {...}) 

Diese sehr schwere Abfrage für die Datenbank sein wird. Schnellere Abfrage wäre jedoch mit dem äußeren Join.

Dadurch kehren auch die Schlüssel als INT nicht STRING

Eine wesentlich schnellere Alternative war

Connection.all(:include => :user, :conditions => {...}).collect {|e| [e.user_id, e.id] } 

Diese Sie mit den ids ein Array von Arrays gibt. Wenn Sie nur die Spalten "id, user_id" auswählen, muss es nicht unbedingt ein AR-Objekt sein. Ein Array kann schneller sein.

Ich hoffe, ich vermisse hier keinen Punkt. Schlage mich vor, wenn ich es bin.

+0

Der from: wurde eingefügt, um die Namen der Tabellenspalten zu aliasieren. Es werden Unterbedingungen dynamisch gemischt. Ich werde Ihre Herangehensweise prüfen und einige Tests damit machen - danke. – tribalvibes

2

Es wird leider nicht sehr einfach passieren. Alle Daten aus der DB-Verbindung werden als Strings zu Rails gesendet. Die Konvertierung von Typen erfolgt in jeder der dynamischen Attributmethoden, die rails zur Laufzeit erstellt. Es weiß, welche Attribute in welche Spalte konvertiert werden sollen, durch die Spalten-Metadaten der Tabelle, die beim Start der App abgerufen werden. Jedes Modell hat nur Spaltenmetadaten für seine eigenen Spalten, deshalb haben die eigenen Spalten den richtigen Typ. Es gibt keine einfache Möglichkeit, die richtigen Typen automatisch zu konvertieren.

Sie können auf der anderen Seite eine einfache Konvertierungsmethode erstellen, die einen Hashwert verwendet und die Attribute automatisch konvertiert.

Etwas wie folgt aus:

users = User.all(:select => "cl, comments.c2", ...) 
users = convert_columns(users, 'c2' => :integer, 'other_column' => :date) 

def convert_columns(records, columns = {}) 
    records.each do |rec| 
    columns.each do |col, type| 
     rec[col] = case type 
     when :int then rec[col].to_i 
     when :date then ........ 
     .... 
     end 
    end 
    end 
end 
0

Wenn Sie schnelle Lösung wollen - versuchen Rückruf zu verwenden after_find und Preset-Typen korrekt Attribute dort:

class User < ActiveRecord::Base 

    after_find :preset_types 


    private 
    def preset_types user 
    user.user_id = user.user_id.to_i 
    end 

end