Eu tenho uma classe Item com os seguintes atributos:
itemId,name,weight,volume,price,required_skills,required_items
.
Como os dois últimos atributos terão vários valores, eu os removi e criei novos esquemas como:
itemID,required_skill
( itemID
é chave estrangeira, itemID and required_skill
é chave primária).
Agora, estou confuso sobre como criar / usar esta nova tabela. Aqui estão as opções que me vieram à mente:
1) O relacionamento entre Items e Required_skills é um para muitos, portanto, posso criar uma classe RequiredSkill, que pertence ao Item, que por sua vez possui n RequiredSkills. Então eu posso fazer Item.get(1).requiredskills
. Isso me parece mais lógico e fornece métodos e consultas como:
sugar.components.create :raw_material => water.name
sugar.components.create :raw_material => sugarcane.name
sugar.components
sugar.components.count
2) Como as required_skills podem ser consideradas constantes (já que elas se assemelham a regras), eu posso colocá-las em um banco de dados hash ou gdbm ou em outra tabela sql e consulta a partir daí, que eu não prefiro.
Minha pergunta é: existe algo como uma tabela sem modela no datamapper, em que o datamapper é responsável pela criação e integridade da tabela e me permite consultá-lo da maneira do datamapper, mas não requer uma classe, como eu posso fazê-lo no sql ?
Resolvi meu problema usando a primeira maneira: criei uma nova classe para cada processo de normalização (que aparece como associação um para muitos acima). No entanto, eu sou novo na programação orientada a objetos e não sei se a criação de uma nova classe para cada normalização é a maneira usual de fazê-lo no datamapper, ou melhor, em um hack? Isso, e se existe uma maneira melhor de fazer isso, é o que eu gostaria de saber.
@JustinC
Relendo as associações do datamapper.org várias vezes, agora vejo que o datamapper certamente exige classes separadas para junções. Então você respondeu minha pergunta. No entanto, como Robert Harvey colocou a recompensa, sinto a responsabilidade de esperar um pouco mais por uma resposta sobre uma maneira dinâmica.
Seu código reclamou Cannot find the child_model Container for Item in containers
. Eu consegui fazê-lo funcionar com o segundo exemplo de associação auto-referencial como abaixo (colocando aqui como referência a outras pessoas):
class Item
class Link
include DataMapper::Resource
storage_names[:default] = "requirement_links"
belongs_to :require, "Item", :key => true
belongs_to :required, "Item", :key => true
end
include DataMapper::Resource
property :id, Serial
property :name, String, :required => true
has n, :links_to_required_items, "Item::Link", :child_key => [:require_id]
has n, :links_to_requiring_items, "Item::Link", :child_key => [:required_id]
has n, :required_items, self,
:through => :links_to_required_items,
:via => :required
has n, :requiring_items, self,
:through => :links_to_requiring_items,
:via => :require
def require(others)
required_items.concat(Array(others))
save
self
end
def unrequire(others)
links_to_required_items.all(:required => Array(others)).destroy!
reload
self
end
end
Então eu posso fazer:
jelly = Item.get :name => "Jelly"
sugar = Item.get :name => "Sugar"
jelly.require sugar
para exigir itens e:
jelly.required_items.each { |i|; puts i.name }
para listar requisitos, que são realmente ótimos.
Depois de ler sua resposta, vejo que ainda estou para normalizar ainda mais meu esquema de banco de dados. Para ser sincero, não vejo o ponto de definir a relação entre matérias-primas e produtos como auto-referencial. Quero dizer, se esse fosse um programa pequeno, certamente usaria um hash {:jelly => ":sugar => 3, :water => 5"}
para refletir os itens e valores necessários, de acordo com o princípio YAGNI. Fazer isso como na primeira opção já me fornece consultas e métodos tão simples quanto os fornecidos pela associação auto-referencial. (No entanto, devo admitir que ele se parece mais com um procedimento armazenado do que com uma chamada de método para um objeto.)
Então, você poderia explicar os benefícios do uso de uma associação auto-referencial, difícil de entender / implementar para mim, em comparação com minha abordagem mais simples? Eu sou novo no OOP e me pergunto se estou meio que submodelo.