Vous avez plusieurs options quant à la façon de modéliser cela dans les rails, mais la première chose que je suggère est que pour sauver vous-même le temps et les problèmes plus tard, vous devriez aborder votre question sous un angle différent.
Afin de tirer le meilleur parti de Rails, vous ne devriez pas commencer par une conception de base de données. Vous devez commencer par un modèle de données, puis examiner la manière de mapper ce modèle de données à une structure de base de données, et non l'inverse. Ceci est une différence subtile, mais implique un état d'esprit différent où vous voyez votre base de données comme une considération secondaire à votre modèle, et non l'inverse. Cela rendra le problème plus facile à comprendre à long terme.
Deux constructions ActiveRecord peuvent être utilisées dans ce scénario: héritage de table unique et héritage polymorphique.
unique Héritage de Table
magasins unique Héritage de Table (STI) Les modèles avec des fonctionnalités bien partagées au sein de la même table de base de données sous-jacente. Dans votre exemple, les questions et réponses, et dans une moindre mesure les commentaires sont tous des objets similaires. Ils ont du contenu, un auteur, des champs datetime pour created_at et mis à jour à etc. La seule différence entre une question et une réponse est que les questions "appartiennent à" une réponse. Les commentaires sont légèrement plus compliqués car vous pouvez commenter à la fois les questions et réponses, et peut-être aussi sur les commentaires, bien que votre schéma de base de données ne reflète pas que c'est possible.
Avec STI vos questions et réponses ne sont pas stockées dans une table séparée mais dans une seule table et marqués avec les noms de classe. Les classes de questions et réponses réelles héritent alors de la classe de base, dans votre cas "Post". Il existe de nombreuses ressources òû il discuter des IST mais this one peuvent aider
polymorphes héritage
C'est la deuxième méthode de modélisation des comportements similaires dans les rails. Cela utilise une seule table, dans vos messages de cas pour stocker les données qui sont communes entre les deux classes. Cette table contient des colonnes qui référencent le nom de classe et l'instance d'ID de l'objet de base. Les données spécifiques à l'objet seraient alors stockées dans une table distincte par modèle.
mise en œuvre (en utilisant STI)
Pour modéliser vos données en utilisant STI alors vous créer un modèle de base des postes comme ce
class CreatePosts < ActiveRecord::Migration
def self.up
create_table :posts do |t|
t.string :type
t.string :author
t.text :content
t.integer :parent_id
t.timestamps
end
end
def self.down
drop_table :posts
end
end
Vos modèles alors ressembler à ceci
class Post < ActiveRecord::Base
end
class Question < Post
has_many :answers, :foreign_key => :parent_id
has_many :comments, :foreign_key => :parent_id
end
class Answer < Post
belongs_to :question, :foreign_key => :parent_id
has_many :comments, :foreign_key => :parent_id
end
class Comment < Post
belongs_to :question, :foreign_key => :parent_id
belongs_to :answer, :foreign_key => :parent_id
end
Et quelques exemples de code
q1 = Question.new(:author => 'Steve', :content => 'What is 2 + 2')
q1c1 = q1.comments.build(:author => 'Malcolm',
:content => "Good question, i'd been wondering that myself")
q1a1 = q1.answers.build(:author => 'John', :content => '2+2 = 5')
q1a2 = q1.answers.build(:author => 'Phil', :content => '2+2 is a sum')
q1a1c1 = q1a1.comments.build(:author => 'Chris',
:content => 'Sorry John it should be 4')
q1a2c1 = q1a2.comments.build(:author => 'Steve',
:content => 'Hi Phil thanks for stating the obvious!')
q1.save
qu = Question.find(:first)
puts "#{qu.author} asked #{qu.content}"
qu.comments.each {|qc| puts "\t#{qc.author} commented #{qc.content}"}
qu.answers.each do |ans|
puts "\t#{ans.author} answered with #{ans.content}"
ans.comments.each do |comm|
puts "\t\t#{comm.author} commented #{comm.content}"
end
end
Ce code produit les résultats suivants
Steve asked What is 2 + 2
Malcolm commented Good question, i'd been wondering that myself
John answered with 2+2 = 5
Chris commented Sorry John it should be 4
Phil answered with 2+2 is a sum
Steve commented Hi Phil thanks for stating the obvious!
En regardant dans la base de données, il y a une table de messages unique avec la structure suivante
CREATE TABLE "posts" (
"id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
"type" varchar(255),
"author" varchar(255),
"content" text,
"parent_id" integer,
"created_at" datetime,
"updated_at" datetime
);
Et le contenu des données après l'exemple est la suivante: -
1|Question|Steve|What is 2 + 2||2009-06-13 09:52:20|2009-06-13 09:52:20
2|Answer|John|2+2 = 5|1|2009-06-13 09:52:20|2009-06-13 09:52:20
3|Comment|Chris|Sorry John it should be 4|2|2009-06-13 09:52:20|2009-06-13 09:52:20
4|Answer|Phil|2+2 is a sum|1|2009-06-13 09:52:20|2009-06-13 09:52:20
5|Comment|Steve|Hi Phil thanks for stating the obvious!|4|2009-06-13 09:52:20|2009-06-13 09:52:20
6|Comment|Malcolm|Good question, i'd been wondering that myself|1|2009-06-13 09:52:20|2009-06-13 09:52:20
Vous trouverez peut-être plus facile de diviser les commentaires modèle dans QuestionComments et AnswerComments. Cela rendrait SQL directement plus facile.
C'est génial. Merci d'avoir pris le temps d'écrire une réponse aussi complète. Bien que j'aime votre suggestion d'utiliser STI sur une approche polymorphe, un inconvénient de STI par rapport à Class Table héritage tout2.com/title/... est que vous vous retrouvez avec des colonnes inutilisées dans les classes qui dérivent de Post. Par exemple, une question peut avoir des balises associées et cela pourrait être une colonne dans le tableau des questions, mais sous STI, il devrait s'agir d'une colonne dans le tableau Posts, puis Answers et Comments se retrouvent également avec une colonne Tags. –
... mais puisque Rails ne propose que des associations STI et polymorphes, STI semble être le meilleur choix même si vous vous retrouvez avec des colonnes supplémentaires inutilisées dans cette approche. Globalement, vous avez raison, cependant - J'ai besoin d'aborder le problème de la perspective Rails plutôt que d'une perspective de base de données. Je vais avoir besoin de m'habituer, j'en ai peur. –
Salut Charlie, je vais commenter, mais je viens de boire depuis plusieurs heures alors ce n'est pas le moment. Je vais écrire quelques commentaires et/ou une solution polymorphique demain –