我有两个模型:User
和Location
,如下所示:
class User < ActiveRecord::Base
attr_accessible :location, :password, :user_name, :password_confirmation
validates :location, :user_name, :presence => true
validates :password, :presence => true, :confirmation => true
has_one :location, :foreign_key => 'location'
end
class Location < ActiveRecord::Base
attr_accessible :loc_id, :loc_name
belongs_to :user, :foreign_key => 'loc_id'
end
您可以看到我对模型使用自定义foreign_key。我使用表单构建器来构建用户注册表单,但是当我提交数据时,会发生错误:
Location(#2170327880) expected, got String
我使用simple_form
来构建表单,相关代码是:
= f.input :location, :collection => Location.all.collect {|c| [c.loc_name, c.loc_id]}
如何解决此问题?或者我必须使用location_id
这样的默认foreign_key进行关联吗?
感谢。
更新
当我将location
模型中的User
字段重命名为loc_id
并删除此:foreign_key
时:
class User < ActiveRecord::Base
attr_accessible :loc_id, :password, :user_name, :password_confirmation
validates :loc_id, :user_name, :presence => true
validates :password, :presence => true, :confirmation => true
has_one :location, :foreign_key => 'location'
end
class Location < ActiveRecord::Base
attr_accessible :loc_id, :loc_name
belongs_to :user
end
工作正常。但我仍然想知道如何关联User
和Location
模型。
P.S。我使用Location
模型存储国家/地区代码和国家/地区名称,该名称永远不会按User
更新。
答案 0 :(得分:1)
看起来你在滥用外键。在用户模型中,您应该只有has_one :location
,并且位置模型应该具有user_id属性。在位置模型中,您只需要编写belongs_to :user
。外键始终是另一个(外部)表的索引。
答案 1 :(得分:1)
听起来你真的想拥有
class User < ActiveRecord::Base
belongs_to :location
end
class Location < ActiveRecord::Base
has_many :users
end
这意味着用户拥有location_id
列。如果您以相反的方式执行操作(位置上的user_id列),则给定位置只能与一个用户相关联。 rails方式是位置表中id列的用户'点'location_id
。如果您希望它指向不同的列,请使用:primary_key
选项(如果您希望将用户列调用为location_id之外的其他内容,则为:foreign_key
选项)
就表单而言,你不能f.select :location
- 表单不知道如何传输这样复杂的对象。在这些情况下,您需要设置表单以控制location_id属性,即
= f.input :location_id, :collection => Location.all.collect {|c| [c.loc_name, c.id]}
如果您沿着路线找到位置ID列,请参阅位置上的loc_id列,那么您需要将其更改为
= f.input :location_id, :collection => Location.all.collect {|c| [c.loc_name, c.loc_id]}
就个人而言,如果你刚开始使用rails,我会坚持使用默认值
答案 2 :(得分:0)
class User < ActiveRecord::Base
# stuff
has_one :location
end
class Location < ActiveRecord::Base
# more stuff
belongs_to :user
end
答案 3 :(得分:0)
如果您最终要做的是选择具有相同位置的所有用户,您可能希望以稍微不同的方式设置模型。现在,因为每个用户在位置表中都有自己的位置记录,所以最终会有重复的位置,您必须找到所有这些位置以获取唯一位置并从中提取user_id。
而是这样做
class User < ActiveRecord::Base
has_one :placement
has_one :location, through: :placement
end
class Placement < ActiveRecord::Base
belongs_to :user
belongs_to :location
end
class Location < ActiveRecord::Base
has_many :placements
has_many :users, through: :placements
end
。至于迁移,Placement应该有:user_id和:location_id。您可以删除当前位置中的:user_id。此代码所说的是我们有很多用户,而且我们有许多独特的位置,我们通过创建展示位置将用户放在不同的位置,这表示位于以下位置的用户:user_id位于:location_id。另外,不要忘记添加一行
add_index :placements, [:user_id, :location_id], unique: true
这样您就无法将用户置于多个位置。
编辑:忘记添加:您只需获取位置记录并调用location.users即可获取某个位置的所有用户