I am currently developing a Dungeons & Dragons 4th Edition Character Sheet application in Ruby on Rails 3.2.1. I am currently at a stage where I realize that I need to associate character races (dwarves, elves, …) with ability bonuses. (Example: a dwarf gets +2 bonuses to the Constitution and Wisdom abilities as a racial trait.)
I currently have the following set up:
class Character < ActiveRecord::Base {
has_many :attributions
has_many :abilities, through: :attributions
}
class Attribution < ActiveRecord::Base {
belongs_to :character
belongs_to :ability
# The "attributions" table also has the column "score,"
# which is the character's ability score
}
class Ability < ActiveRecord::Base {
has_many :attributions
has_many :characters, through: :attributions
}
As you can see, the characters each have their own set of abilities. I figure I may do the same thing for character races, but I am unsure of any best practices in this area. I could probably use the same join model, creating something like this (Character
would stay the same, except for an overridden abilities
method, perhaps):
class CharacterRace < ActiveRecord::Base {
# I am not sure if this will actually work, but I hope
# you understand what I am trying to do with this
has_many :racial_ability_traits, class_name: "Attribution"
has_many :abilities, through: :racial_ability_traits
}
class Attribution < ActiveRecord::Base {
# The following two are just like before
belongs_to :character
belongs_to :ability
# This field would be new
belongs_to :character_class
}
class Ability < ActiveRecord::Base {
# These are the same as above
has_many :attributions
has_many :characters, through: :attributions
# These would be new, and I am not sure if it will work, but
# I hope you understand what I amm trying to do with this
has_many :racial_traits, class_name: "Attribution"
has_many :character_races, through: :racial_ability_traits
}
However, even if this would work, I somehow feel like having the same join model for different joins (even if the purpose is pretty much the same) is kind of an ugly approach. I could, of course, create a different kind of join like this:
class CharacterRace < ActiveRecord::Base {
has_many :abilities, through: :attributions
# These are for the racial bonus
has_many :racial_ability_bonuses
has_many :abilities, through: :racial_ability_bonuses
}
class RacialAbilityBonus < ActiveRecord::Base {
belongs_to :character_race
belongs_to :ability
}
class Ability < ActiveRecord::Base {
has_many :attributions
has_many :abilities, through: :attributions
# These are for the racial bonus
has_many :racial_ability_bonuses
has_many :character_races, through: :racial_ability_bonuses
}
This would probably work, but there is a problem. Not only the races can have such traits/bonuses. A magical item might also give an ability bonus. Therefore, an Item
model should also be given a has_many :abilities, through: :item_ability_bonus
association. Continuing down the road explained above, this would cause a lot of join models.
I am therefore asking you guys if you know any good approach for handling this problem. Any suggestion about making my existing code better is welcome as well.
I am very thankful for all of your serious answers. :-)
I think you just need polymorphic associations.