5

Ich habe ein lokales Benutzermodell, das ActiveRecord verwendet. Der Benutzer hat ein E-Mail-Feld. Ich habe auch ein ActiveResource-Modell namens tasks, das ein created_by-Feld hat, in dem die E-Mail-Adresse der einreichenden Benutzer gespeichert wird. Ich möchte die beiden verbinden, aber ich kämpfe mit der richtigen Syntax oder auch, ob es möglich ist.Wie definiere ich eine Beziehung zwischen ActiveRecord und ActiveResource mit Fremdschlüsseln?

Der Hauptzweig von ActiveResource scheint nicht einmal Fremdschlüssel zu unterstützen. Ich fand eine alternative branch aber konnte immer noch nichts arbeiten.

class User < ActiveRecord::Base 
    has_many :tasks 
end 

class Task < ActiveResource::Base 
    belongs_to :user 
    schema do 
    string 'created_by' #email 
    # other fields 
    end 
end 

Antwort

1

Sie können nicht, aber Sie können es vortäuschen, indem Sie selbst Accessormethoden implementieren.

class User < ActiveRecord::Base 
    #has_many :tasks 
    def tasks 
    Task.find(:all, params: {created_by: email}) 
    end 
end 

class Task < ActiveResource::Base 
    #belongs_to :user 
    def user 
    User.where(email: created_by).first 
    end 

    schema do 
    string 'created_by' #email 
    # other fields 
    end 
end 

Auf diese Weise können Sie Code schreiben als ob Ihre Objekte zugeordnet waren (das heißt User.first.tasks.length). Sie sind jedoch nicht wirklich verbunden. Das heißt, der Aufruf von User.first.tasks wird die Datenbank treffen und dann eine weitere HTTP-Anforderung zum Abrufen der Aufgaben stellen. Je nachdem, wie Ihr Code strukturiert ist, können unerwartete Leistungsprobleme auftreten.

Sie können aber auch nicht eine einzige Abfrage ausführen einen Benutzer und alle damit verbundenen Aufgaben zu bekommen (da es zwei getrennte Datenspeicher ist), und Sie können ausgefallene Sachen wie User.joins(:tasks).where({tasks: field_1: true}) nicht tun.

4

soll Ihr Code in Ordnung, dass Sie ein user_id Attribut auf den Task als Fremdschlüssel zu handeln gegeben arbeiten, oder Sie den Fremdschlüssel in der Vereinigung auf User Modell angeben können, wie folgt: Jetzt

class User < ActiveRecord::Base 
    has_many :tasks, foreign_key: "uid" 
end 

Das Problem ist, können Sie belongs_to auf ActiveResource nicht verwenden, so dass Sie die user aus einer Instanz der Task Klasse abrufen können, können Sie einfach entfernen und die andere Seite der Beziehung wird jedoch weiterhin funktionieren, wenn Sie müssen rufen Sie die user dann müssten Sie entweder Ihre eigenen implementieren Suchmethode wie folgt:

class Task < ActiveResource::Base 
    schema do 
    string 'created_by' #email 
    # other fields 
    end 

    def user 
    @user ||= User.find self.user_id # use the attribute name that represents the foreign key 
    end 

    def user=(user) 
    @user = user 
    self.update_attribute(:user_id, user.id) 
    end 
end 

Dies wird die gleiche grundsätzlich verhalten, wie Sie auf einem ActiveRecord-Modell erwartet, aber dies ermüdend sein kann, wenn Sie mehrere Zuordnungen haben, so dass Sie das ActiveResource Modul stattdessen erweitern können belongs_to wie folgt hinzufügen :

module BelongsToActiveResource 

    def self.included(base) 
     base.extend(ClassMethods) 
    end 

    module ClassMethods 

    def belongs_to(name, options = {}) 
     class_eval %(
     def #{name} 
      @#{name} ||= name.to_s.classify.find(name.id) 
     end 

     def #{name}=(obj) 
      @#{name} ||= obj 
      self.update_attribute((name.to_s + "_id").to_sym, @#{name}.id 
     end 
    ) 
    end 

    end 

end 

ActiveResource::Base.class_eval { include BelongsToActiveResource } 

Dies ermöglicht es Ihnen, auf jedem ActiveResource Modell zu verwenden belongs_to.

PS: die obige Lösung von https://stackoverflow.com/a/8844932/3770684

+0

inspiriert habe ich versucht, dies mit dem Affen-Patch vorgeschlagen, dass Sie, aber wenn ich laufe ‚User.last.tasks‘ ich ‚NoMethodError: nicht definierte Methode' relation_delegate_class‘für Aufgabe: Klasse ' – Simmo

+0

Welche Versionen von Ruby und Rails verwenden Sie? – cousine

+0

Rails 4.1.0 und Ruby 2.1.1 – Simmo