how to force a has_many to use a specific :foreign_key?
I'm having trouble with a model not honoring the :foreign_key policy.
Character model has the following fields: name:string level:int realm:string realm_id:in开发者_如何学编程teger
class Character < ActiveRecord::Base
belongs_to :realm
end
My Realms model looks like this:
class Realm < ActiveRecord::Base
has_many :characters, :foreign_key => "realm_id"
end
However, it seems like it's forcing the character model to use the :realm column as the foreign_key rather than :realm_id. I don't have any clue as to why or how to fix it. Is there any other way to make it ignore the :realm field and go for the :realm_id without having to change the name of the column?
[Edit for clarity]
The character model does have a realm_id:integer field. I have tried not having the foreign_key but the results with both is identical.
ruby-1.9.2-p136 :012 > c = Character.new => #
ruby-1.9.2-p136 :013 > c.realm = "Sargeras"
ActiveRecord::AssociationTypeMismatch: Realm(#2154038240) expected, got String(#2151988680)
Despite even having the foreign_key, it just refuses to let go of the realm column.
[Edit 2]
The realm column will just take over due to the has_many and belongs_to association. There is no way so far to break this, so the solution is to either remove the column (the approach i will take), or rename it to something different.
Did you make sure that your Character table has a realm_id column? Please make sure of that, and then get rid of foreign_key => 'realm_id, it is not necessary at all. Your program should work if you get both these things done.
You should not need the :foreign_key
part here at all, since you're following the standard Rails naming convention, the realm_id column should be inferred from the model name.
EDIT
I see. I don't think you can have a column and an association by the same name in one model. The easiest solution would probably be to rename the "realm" column to "realmname" or something like that.
belongs_to :realm
creates (among other things) methods called realm
and realm=
used as getters and setters. That means the method_missing magic that ActiveRecord uses to expose database columns as attributes is never triggered when you do Character#realm, as that method isn't in fact missing.
If you want to avoid renaming the realm column in your database, you could create attribute accessors for the field manually under another name:
class Character < ActiveRecord::Base
def realm_name
self['realm']
end
def realm_name=(value)
self['realm'] = value
end
end
This way you'll still have the realm column in your database and be able to access the attribute in Ruby, albeit under a different name. This isn't a great idea, though, as you'll be duplicating the realm name as both Character#realm_name
and Character.realm.name
.
I would ditch the realm
column and instead make sure I use Realm
objects when importing from the datasource:
character.realm = Realm.find_by_name('Sargeras')
That way you'd only realm data available where it makes sense; in the Realm
model.
精彩评论