views:

130

answers:

3

I have a few models:

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

I have the Course model set up as such:

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

The issue I am running into: In the course I check to see if the course_stat exists and if it doesn't to create it. But in the model it is saying that it exists because there is a player_course_stat associated with this instance.

When I dive into the ruby script/console and check to see the course_stat relationship it is nil.

> 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. Is there a problem with the way I have the relationships for the Course model set?
  2. Why is course_stat nil in the console but not in the application as it is running?

Update:

Looking into this a bit further I looked through the logs to get the SQL statements that are generated for the console and the 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

I want a query like the console creates to be used. Is there a way for me to do this with out having to write the sql out in full?

A: 

Given your relationships:

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

when you have a PlayerCourseStat, you have a Course stat because you've modeled an IS-A relationship... a PlayerCourseStat IS-A CourseStat. Did you mean to do:

class PlayerCourseStat < StatsParent
Jeff Paquette
The only real difference between a PlayerCourseStat and a CourseStat is that a PlayerCourseStat is associated with a user and a CourseStat is not. Since they are both updated the same way it make sense to me to have the PlayerCourseStat inherit from the CourseStat to prevent duplicated code of the update method.
lillq
+1  A: 

I think you should simply add a condition to your has_one

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

It seems redundant, but I find the inconsistency between console and the app to be very confusing...

MattMcKnight
Thanks. This seems to be the most simple solution even though it seems redundant.
lillq
+1  A: 

If you want to keep this simple (which is always a nice idea), eliminate the inheritance and put the shared logic in a module

module Stats
  def ...
end

class CourseStat < ActiveRecord::Base
  include Stats
end

class PlayerCourseStat < ActiveRecord::Base
  include Stats
end
Mike