Frage

class User < ActiveRecord::Base
  has_one :location, :dependent => :destroy, :as => :locatable
  has_one :ideal_location, :dependent => :destroy, :as => :locatable
  has_one :birthplace, :dependent => :destroy, :as => :locatable
end

class Location < ActiveRecord::Base
  belongs_to :locatable, :polymorphic => true
end

class IdealLocation < ActiveRecord::Base
end

class Birthplace < ActiveRecord::Base
end

Ich kann nicht wirklich einen Grund sehen Subklassen in dieser Situation zu haben. Das Verhalten der Lage Objekte sind identisch, der einzige Punkt von ihnen ist die Assoziationen leicht zu machen. Ich würde auch die Daten als int speichern bevorzugen und nicht eine Zeichenfolge als es dem Datenbank-Indizes kann kleiner sein.

Ich sehe so etwas wie die folgenden, aber ich kann den Gedanken nicht abgeschlossen:

class User < ActiveRecord::Base
  LOCATION_TYPES = { :location => 1, :ideal_location => 2, :birthplace => 3 }

  has_one :location, :conditions => ["type = ?", LOCATION_TYPES[:location]], :dependent => :destroy, :as => :locatable
  has_one :ideal_location, :conditions => ["type = ?", LOCATION_TYPES[:ideal_location]], :dependent => :destroy, :as => :locatable
  has_one :birthplace, :conditions => ["type = ?", LOCATION_TYPES[:birthplace]], :dependent => :destroy, :as => :locatable
end

class Location < ActiveRecord::Base
  belongs_to :locatable, :polymorphic => true
end

Mit diesem Code der folgenden fehlschlägt, im Grunde macht es nutzlos:

user = User.first
location = user.build_location
location.city = "Cincinnati"
location.state = "Ohio"
location.save!

location.type # => nil

Dies ist offensichtlich, da es keine Möglichkeit gibt, die zu übersetzen. Bedingungen Optionen auf der has_one Erklärung in den Typen-1-gleich

Ich konnte die ID in der Ansicht überall diese Felder erscheinen einbetten, aber dies scheint falsch zu:

<%= f.hidden_field :type, LOCATION_TYPES[:location] %>

Gibt es eine Möglichkeit die zusätzliche Unterklassen zu vermeiden oder die LOCATION_TYPES nähert Arbeit machen?

In unserem speziellen Fall ist die Anwendung sehr Lage bewusst und Objekte viele verschiedene Arten von Standorten haben. Bin ich nur seltsam zu sein, alle jene Unterklassen nicht wollen?

Irgendwelche Vorschläge Sie geschätzt haben, sagen Sie mir, ich bin verrückt, wenn Sie wollen, aber würden Sie wollen 10+ verschiedene Standortmodelle im Umlauf app / Modelle sehen?

War es hilfreich?

Lösung

Soweit ich es sehen kann, ist ein Ort ein Ort ein Ort ist. Die verschiedenen „Unterklassen“ Sie sich beziehen (IdealLocation, Geburtsort) scheinen nur um die Beziehung zu einem bestimmten Standort des Benutzers zu beschreiben. Hör auf mich, wenn ich das Teil falsch haben.

Das Wissen, dass kann ich zwei Lösungen für diese sehen.

Das ist zuerst zu behandeln Stellen als Wert-Objekte statt Einheiten. (Weitere Informationen zu den Bedingungen: Wert vs Entity-Objekten (Domain Driven Design) ). In dem obigen Beispiel, scheinen Sie den Speicherort „Cincinnati, OH“ zu Einstellung, anstatt ein „Cincinnati, OH“ Objekt aus der Datenbank zu finden. In diesem Fall, wenn viele verschiedene Benutzer in Cincinnati gab, dann würden Sie nur so viele identische „Cincinnati, OH“ Standorte in Ihrer Datenbank haben, wenn man es nur Cincinnati, OH. Für mich, das ist ein klares Zeichen dafür, dass Sie mit einem Wert Objekt arbeiten, keine Einheit.

Wie würde diese Lösung aussehen? Wahrscheinlich eine einfache Lage Objekt wie folgt verwendet:

class Location
  attr_accessor :city, :state

  def initialize(options={})
    @city = options[:city]
    @state = options[:state]
  end
end

class User < ActiveRecord::Base
  serialize :location
  serialize :ideal_location
  serialize :birthplace
end

@user.ideal_location = Location.new(:city => "Cincinnati", :state => "OH")
@user.birthplace = Location.new(:city => "Detroit", :state => "MI")
@user.save!

@user.ideal_location.state # => "OH"

Die andere Lösung, die ich sehen kann, ist Ihr bestehende Lage Active Modell zu verwenden, sondern einfach zu verwenden, um die Beziehung mit Benutzern die Beziehung „Typen“ zu definieren, etwa so:

class User < ActiveRecord::Base
  belongs_to :location, :dependent => :destroy
  belongs_to :ideal_location, :class_name => "Location", :dependent => :destroy
  belongs_to :birthplace, :class_name => "Location", :dependent => :destroy
end

class Location < ActiveRecord::Base
end

Alles, was Sie brauchen würden, zu tun, um diese Arbeit zu machen ist, umfasst location_id, ideal_location_id und birthplace_id Attribute in Ihrem User-Modell.

Andere Tipps

Warum nicht named_scopes verwenden?

So etwas wie:

class User
  has_many :locations
end

class Location
  named_scope :ideal, :conditions => "type = 'ideal'"
  named_scope :birthplace, :conditions => "type = 'birthplace" # or whatever
end

Dann im Code:

user.locations.ideal => # list of ideal locations
user.locations.birthplace => # list of birthplace locations

Sie würden immer noch zu behandeln haben die Art bei der Erstellung Einstellung, denke ich.

Versuchen BEFORE_SAVE Haken Hinzufügen

class Location
  def before_save
    self.type = 1
  end
end

und ebenso für die anderen Arten von Standort

Sie können das Verhalten von Location kapseln Objekte Module verwendet werden, und einige Makro verwenden, um die Beziehung zu erstellen:

has_one <location_class>,: conditions => [ "type =?" LOCATION_TYPES [: location]],: dependent =>: destroy,: as =>: locatable

Sie können in Ihrem Modul etwas wie folgt verwenden:

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

  module ClassMethods
    def some_class_method(param)
    end

    def some_other_class_method(param)
    end

    module InstanceMethods
      def some_instance_method
      end
    end
  end
end

Rails Guides: Add- ein wirkt-as-Methode-zu-aktiv-record

Vielleicht etwas Wichtiges hier fehlt mir, aber ich dachte, dass Sie Ihre Beziehungen wie diese nennen könnte:

class User < ActiveRecord::Base

  has_one :location, :dependent => :destroy
  #ideal_location_id
  has_one :ideal_location, :class_name => "Location", :dependent => :destroy
  #birthplace_id
  has_one :birthplace, :class_name => "Location", :dependent => :destroy

end

class Location < ActiveRecord::Base
  belongs_to :user # user_id
end
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top