Pergunta

Olá a todos, eu tenho algo de um requisito interessante para o meu projeto. Eu preciso de um relacionamento has_one onde é tanto uma classe ou de outra, mas sem herança. Eu poderia ir longe com herança se ele é o único caminho, mas os dois registros associados têm dados completamente diferentes e não estão relacionados a todos.

O que eu preciso descobrir é algo como o seguinte.

# 1. Foo never belongs to anything.
# 2. Foo MUST have one assigned sub-record for validity.
# 3. Foo can only have either Bar or Baz assigned.
# 4. Bar and Baz have only ONE common property, and aren't
#    related in either data or implementation.

class Foo < ActiveRecord::Base
  # Attributes: id, name, value
  has_one :assignment, :foreign_key => 'assigned_to', :readonly => true
          # Could really use an :object_type for has_one here...
end

class Bar < ActiveRecord::Base
  # Attributes: name,...
end

class Baz < ActiveRecord::Base
  # Attributes: name,...
end

Onde Foo tem uma atribuição, de tipo quer Bar ou Baz; eles só compartilham uma coluna comum, então talvez eu possa fazer um objeto pai com isso. No entanto, se eu torná-los herdar de um objeto comum (quando os dados que eles contêm realmente é laranjas e maçãs) deve I fazer uma tabela para o registro? Talvez eu possa fugir com ele se o registro é um registro abstrato, mas as crianças não são?

Eu suponho que agora você pode ver a minha dificuldade. Eu sou um pouco novo para RoR, mas amá-la até agora. Eu tenho certeza que há uma maneira de contornar isso, mas eu vou ser amaldiçoado se eu não consigo descobrir o que é.

Foi útil?

Solução

You're trying to model something that doesn't fit the relational database paradigm. All references in SQL have one origin and one target.

FWIW, Polymorphic Associations is also an anti-pattern because it breaks this rule. It should be a clue that it's a broken design when the documentation says you must forgo a referential integrity constraint to make it work!

You need Foo to have two has_one relationships: one to Bar and one to Baz. Then implement some class logic to try to ensure only one reference is populated in any instance of Foo. That is, of the references to Bar and Baz, one must have a value and the other must be nil, but this is something for your code to check for and enforce.

Outras dicas

Perhaps one way to do this, is to create to has-one associations in Foo, for Bar and Baz. Then create a method called assignment and assignment= which can be the sole way to access Bar and Baz. You can check which of the two has_ones is not nil in the get method and return that one. In the assignment method, you can-check what is the type of the variable passed in and set the correct has-one relationship to that object and set the other to nil. That ought to cover all your bases without being too complicated.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top