【问题标题】:Setting join table attributes when adding objects to a has_many through relationship通过关系将对象添加到 has_many 时设置连接表属性
【发布时间】:2012-11-22 08:43:53
【问题描述】:

在我的 Ruby on Rails 3.2.3 应用程序中,我有两个模型通过 has_many through 关系通过第三个模型连接:

class Organization < ActiveRecord::Base
  attr_accessible :description, :name
  has_many :roles, dependent: :destroy
  has_many :members, through: :roles, source: :user
end

class Role < ActiveRecord::Base
  attr_accessible :title
  belongs_to :organization
  belongs_to :user
end

class User < ActiveRecord::Base
  attr_accessible :email, :fullname
  has_many :roles, dependent: :destroy
  has_many :organizations, through: :roles
end

我想将UserOrganization 相关联。但是,需要指定Role 上的title 属性。为了强制执行此操作,我在 MySQL 中将 title 字段设置为 NOT NULL

以下是 Rails 控制台上发生的情况:

>> o = Organization.first
>> u = User.first
>> o.members << u
   (0.1ms)  BEGIN
  SQL (0.4ms)  INSERT INTO `roles` (`created_at`, `organization_id`, `title`, `updated_at`, `user_id`) VALUES ('2012-11-22 08:37:23', 1, NULL, '2012-11-22 08:37:23', 1)
Mysql2::Error: Column 'title' cannot be null: INSERT INTO `roles` (`created_at`, `organization_id`, `title`, `updated_at`, `user_id`) VALUES ('2012-11-22 08:37:23', 1, NULL, '2012-11-22 08:37:23', 1)
   (0.1ms)  ROLLBACK
ActiveRecord::StatementInvalid: Mysql2::Error: Column 'title' cannot be null: INSERT INTO `roles` (`created_at`, `organization_id`, `title`, `updated_at`, `user_id`) VALUES ('2012-11-22 08:37:23', 1, NULL, '2012-11-22 08:37:23', 1)
    from /path/...

我知道我可以直接创建一个Role 实例。但是,在使用 &lt;&lt; 运算符时,在连接表上指定属性的更优雅的方法是什么?

【问题讨论】:

  • 你为什么不在模型中使用验证存在而不是在数据库中放置 not null?
  • 我在Role 中有validates_presence_of :title。它在模型级别和数据库级别都强制执行。但是,Rails 仍然会吐出 MySQL 错误,而不是一些验证错误。
  • 你能从数据库中删除验证,看看会发生什么吗?
  • 另外,如果不同的角色或固定的数量,你可能有很多吗?例如,管理员、帐户、员工?
  • 在这种情况下,title 可以是任何东西(“副总裁”、“财务主管”等)。我坚信数据库效率,包括将字段定义为NOT NULL 并具有外键,因此我不想从数据库中删除声明。

标签: ruby-on-rails ruby-on-rails-3 activerecord


【解决方案1】:

我认为您正在尝试使用不属于其中的信息来更新角色表。在您的情况下,角色名称应包含在组织或用户中,而不是您的联接表中。无论是包含在父模型中,还是更好,都可以创建另一个连接表,以便将角色与用户联系起来。

class role_users < ActiveRecord::Base
  attr_accessible :user_id, role_id
  belongs_to :user
  belongs_to :role
end

class Roles < ActiveRecord::Base
  attr_accessible :title, :foo, :bar
  has_many :role_users
  has_many :users, :through => :role_users
end    

class Users < ActiveRecord::Base
  attr_accessible :other, :foo, :bar
  has_many :role_users
  has_many :roles, :through => :role_users
end

然后像我们一样自行设置这些角色,并添加一个复选框或下拉列表,以便用户可以选择。或者让用户自己输入信息。

【讨论】:

  • Rails ActiveRecord Associations guide 中的示例显示了一个“连接表”,其中包含两个外键之外的其他字段。我在设计架构时从那里获得了灵感。
  • 用铁轨给猫剥皮的方法有很多。这只是我对您提出的问题的建议。
猜你喜欢
  • 1970-01-01
  • 2015-08-22
  • 2014-07-25
  • 2016-08-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多