开发者

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜