2009-11-23 8 views
1

J'ai quelques modèles:Modèle question de relation avec Ruby on Rails

class StatsParent < ActiveRecord::Base 
class CourseStat < StatsParent 
class PlayerCourseStat < CourseStat 

j'ai le modèle Course mis en place en tant que tel:

class Course < ActiveRecord::Base 
    has_one :course_stat 
    has_many :player_course_stats 

    def update_stats(plyr_rnd) 
    puts self.course_stat # this puts #<PlayerCourseStat:0x000001015c54e0> 
    if self.course_stat 
     self.course_stat.add_player_round(plyr_rnd) 
    else 
     self.course_stat = CourseStat.new(plyr_rnd) 
    end 
    end 
#...rest of the class 

La question que je me présente dans: Au cours Je vérifie pour voir si le course_stat existe et s'il ne le crée pas. Mais dans le modèle, il est dit qu'il existe parce qu'il y a un player_course_stat associé à cette instance.

Lorsque je plonge dans le ruby script/console et vérifie pour voir la relation course_stat c'est nul.

> ruby script/console 
Loading development environment (Rails 2.3.3) 
>> course = Course.find(1) 
=> #<Course id: ...> 
>> course.course_stat 
=> nil 
>> course.player_course_stats 
=> [#<PlayerCourseStat id: 1, ...>] 
  1. Y at-il un problème avec la façon dont je les ai relations pour l'ensemble du modèle de cours?
  2. Pourquoi course_stat est nul dans la console mais pas dans l'application car elle est en cours d'exécution?

Mise à jour:

En regardant dans un peu plus loin, je regardé à travers les journaux pour obtenir les instructions SQL qui sont générés pour la console et l'application.

# from console: course.course_stat 
CourseStat Load (0.2ms) SELECT * FROM "stats_parents" WHERE 
("stats_parents".course_id = 1) AND (("stats_parents"."type" = 'CourseStat')) 
LIMIT 1 

# from app: course.course_stat 
CourseStat Load (0.3ms) SELECT * FROM "stats_parents" WHERE 
("stats_parents".course_id = 3) AND (("stats_parents"."type" = 'CourseStat' OR 
             "stats_parents"."type" = 'PlayerCourseStat')) 
LIMIT 1 

Je veux une requête comme la console créée pour être utilisée. Y a-t-il un moyen pour moi de faire cela sans écrire le sql en entier?

+1

Est-ce que vous faites un héritage de table unique? Si oui, êtes-vous sûr que vous définissez la colonne 'type' correctement pour le modèle StatsParent? – khelll

+0

STI est la valeur par défaut et s'il existe un champ type: string dans la migration, il doit être rempli automatiquement par Rails. –

+0

J'ai ajouté une mise à jour pour afficher les requêtes qui sont exécutées. J'espère que cela aide à la clarification. – lillq

Répondre

1

Je pense que vous devez simplement ajouter une condition à votre has_one

has_one :course_stat, :conditions => "type = 'CourseStat'" 

Il semble redondant, mais je trouve l'incohérence entre la console et l'application pour être très déroutant. ..

+0

Merci. Cela semble être la solution la plus simple même si elle semble redondante. – lillq

0

Compte tenu de vos relations:

class StatsParent < ActiveRecord::Base 
class CourseStat < StatsParent 
class PlayerCourseStat < CourseStat 

lorsque vous avez un PlayerCourseStat, vous avez une stat de cours parce que vous avez un IS-modélisé une relation ... un PlayerCourseStat IS-A CourseStat. Vouliez-vous dire faire:

class PlayerCourseStat < StatsParent 
+0

La seule vraie différence entre un PlayerCourseStat et un CourseStat est qu'un PlayerCourseStat est associé à un utilisateur et qu'un CourseStat ne l'est pas.Comme ils sont tous les deux mis à jour de la même manière, il est logique que le PlayerCourseStat hérite du CourseStat pour empêcher le code dupliqué de la méthode de mise à jour. – lillq

1

Si vous voulez garder ce simple (ce qui est toujours une bonne idée), d'éliminer l'héritage et de mettre la logique partagée dans un module

module Stats 
    def ... 
end 

class CourseStat < ActiveRecord::Base 
    include Stats 
end 

class PlayerCourseStat < ActiveRecord::Base 
    include Stats 
end