Rails ActiveRecorde has_many foreign_key 使用

使用的是rails2.0.2版本,。现有表结构如下:
create table mc$dr_role(
id number primary key,
role varchar2(30),
enabled varchar2(10)
)
create table mc$dr_user_roles(
id number primary key,
user_id number ,
role_id number
)
create table users(
id number primary key,
name varchar2(30) ,
passwd varchar2(30)
)

在model中写法是:
class Role < ActiveRecord::Base
set_table_name "mc$dr_role"
has_many :user_roles, :class_name =>"DrUserRole", :foreign_key=>"id",
:dependent=> :delete_all
has_many :users, :through => :user_roles
end
class User < ActiveRecord::Base
has_many :user_roles, :class_name =>"DrUserRole", :foreign_key=>"id",
:dependent=> :destroy
has_many :roles, :through => :user_roles
end
class DrUserRole < ActiveRecord::Base
set_table_name "mc$dr_user_roles"
belongs_to :user, :class_name =>"User", :foreign_key=>"user_id"
belongs_to :role, :class_name =>"Role", :foreign_key=>"role_id"
end


在执行@user.roles << role 报错Cannot associate new records through 'User#user_roles' on '#'. Both records must have an id in order to create the has_many :through record associating them.
我很奇怪关联中“#”是哪里出来的?没弄明白。foreign_key这个配置选项我都已经尝试过好几次变化了,都没成功。。。不知道原因在那里?还是对于这样自定义的表进行关联式有问题的?

正常来说
按照你所需要的建多对多关联表 是这样弄的
ruby generate model role role:string enable:string
ruby generate model user name:string pass:string
ruby generate model UserRole user_id:integer role_id:integer
rake db:migrate

就生成对应的表和字段了
然后是model
class Role < ActiveRecord::Base
has_many :user_roles,:dependent=> :destroy
has_many :users, :through => :user_roles
end

class User < ActiveRecord::Base
has_many :user_roles,:dependent=> :destroy
has_many :roles, :through => :user_roles
end
class DrUserRole < ActiveRecord::Base
belongs_to :user
belongs_to :role
end


over

你的错误应该是指定了错误的外键 导致的..


对于belongs_to :foreign_key是默认的,除非你的,主键不是id,如果你只是修改了table没有改field名的话,考虑去掉:foreign_key。
参考官方API

[quote]:foreign_key
Specify the foreign key used for the association. By default this is guessed to be the name of the association with an "_id" suffix. So a class that defines a belongs_to :person association will use "person_id" as the default :foreign_key. Similarly, belongs_to :favorite_person, :class_name => "Person" will use a foreign key of "favorite_person_id".[/quote]

那么,楼主的问题在哪呢?

楼主最主要不一样的地方是,打破了一个默认规则,就是不希望,物理表名和Model名一致。

实际,对于这样的需要只需要set_table就够了,也就是model写成这样



class Role < ActiveRecord::Base
set_table_name "mc$dr_role"
has_many :dr_user_roles,
:dependent=> :delete_all
has_many :users, :through => :dr_user_roles
end
class User < ActiveRecord::Base
has_many :dr_user_roles,
:dependent=> :destroy
has_many :roles, :through => :dr_user_roles
end
class DrUserRole < ActiveRecord::Base
set_table_name "mc$dr_user_roles"
belongs_to :user
belongs_to :role
end



那么,最开始说了,什么时候用指定:foreign_key
接着看看,什么时候用:class_name,这个应该是,只有定义的关系和类名不一致的时候。例如:假设楼主,很坚持使用user_roles,就可以按下面写
Ruby代码



class Role < ActiveRecord::Base
set_table_name "mc$dr_role"
has_many :user_roles,
:class_name =>"DrUserRole",
:dependent=> :delete_all
has_many :users, :through => :user_roles
end
class User < ActiveRecord::Base
has_many :user_roles,
:class_name =>"DrUserRole",
:dependent=> :destroy
has_many :roles, :through => :user_roles
end
class DrUserRole < ActiveRecord::Base
set_table_name "mc$dr_user_roles"
belongs_to :user
belongs_to :role
end



换句话说,这里没有问题,没有不一致的问题。
只是,不应该指定一个,不太合逻辑的foreign_key。也就是说belongs_to的class_name和forein_key可以不去掉,顶多就是重复写了一遍。has_many的foreign_key也可以去掉,因为和默认的外键是一样的,毕竟你的id还是主键。

那么,如果楼主说了,我就偏要写呢,

嗯,也可以,那就像楼上说的,那得把foreign_key写对。
has_many的默认foreign_key是什么呢,那就要看看逻辑啦
你有很多子表,那么外键就是你的主键了,所以应该是,主表名加主id。
或者,也可以参考,官方API



:foreign_key
# Specify the foreign key used for the association. By default this is guessed to be the name of this class in lower-case and "_id" suffixed. So a Person class that makes a has_many association will use "person_id" as the default :foreign_key.



也就是说,楼主的Model写成下面的,也没问题。


class Role < ActiveRecord::Base
set_table_name "mc$dr_role"
has_many :user_roles, :class_name =>"DrUserRole", :foreign_key=>"role_id",
:dependent=> :delete_all
has_many :users, :through => :user_roles
end
class User < ActiveRecord::Base
has_many :user_roles, :class_name =>"DrUserRole", :foreign_key=>"user_id",
:dependent=> :destroy
has_many :roles, :through => :user_roles
end
class DrUserRole < ActiveRecord::Base
set_table_name "mc$dr_user_roles"
belongs_to :user, :class_name =>"User", :foreign_key=>"user_id"
belongs_to :role, :class_name =>"Role", :foreign_key=>"role_id"
end



最后,说说,为什么:foreign_key写成id的问题,@user.roles能找到,但添加会有问题呢?

因为,:foreign_key写成id,@user.roles就变成
DrUserRole.find_by_id(@user.id)
而不是,正确的
DrUserRole.find_by_user_id(@user.id)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值