【问题标题】:Associating a new object with an existing object with has_many through通过 has_many 将新对象与现有对象相关联
【发布时间】:2013-04-18 01:40:35
【问题描述】:

我有两个类用户和项目。一个用户可以拥有多个项目,一个项目可以由多个用户拥有。但是,一个项目必须至少有一个用户,而一个用户不一定必须有一个项目。

这是我目前拥有的:

class Project < ActiveRecord::Base
    attr_accessible :prj_id, :name
    has_many :ownerships, foreign_key: "project_id", dependent: :destroy
    has_many :users, through: :ownerships
end

class User < ActiveRecord::Base
    attr_accessible :first_name, :last_name, :email, :password, :password_confirmation

    has_many :ownerships, foreign_key: "user_id", dependent: :destroy
    has_many :projects, through: :ownerships
    validates :first_name, presence: true, length: { maximum: 25 }
    validates :last_name, presence: true, length: { maximum: 25 }
    VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
    validates :email, presence: true, format: { with: VALID_EMAIL_REGEX },
        uniqueness: { case_sensitive: false }
    validates :password, presence: true, length: { minimum: 6 }
    validates :password_confirmation, presence: true
end

class Ownership < ActiveRecord::Base
    attr_accessible :project_id

    belongs_to :user, class_name: "User"
    belongs_to :project, class_name: "Project"

    validates :user_id, presence: true
    validates :project_id, presence: true
end

因此,在我们创建项目之前,用户必须先存在。我目前遇到的问题是当我尝试创建一个新项目并将用户附加到新项目时,它不允许我保存,因为用户已经存在于 User 表中。更具体地说,在 Rails 控制台中:

>> prj = Project.new(prj_id: 'hello', name: 'hello')
>> usr = User.find_by_id(1)
>> prj.users<<usr
>> prj.save

prj.save 行未能给出此消息:

(0.1ms)  SAVEPOINT active_record_1
User Exists (0.1ms)  SELECT 1 AS one FROM "users" WHERE (LOWER("users"."email") = LOWER('example@example.com') AND "users"."id" != 1) LIMIT 1
(0.1ms)  ROLLBACK TO SAVEPOINT active_record_1
=> false

有没有办法将新项目与现有用户关联,在项目表和所有权表中创建一个新条目,同时检查用户是否存在于用户表中(而不是尝试创建新用户)?谢谢!

【问题讨论】:

  • 在致电prj.save 后尝试检查您的prj.errorsusr.errors。是否有任何错误信息?另外,您的Ownership 表/模型是什么样的?
  • 错误只是用户无效,因为它试图保存到用户表(并且唯一性验证失败)。所有权只是一个表,其中 user_id 和 project_id 分别作为 User 表和 Project 表的外键。我想要的是创建一个新项目和引用现有用户和新项目的新所有权元组。我想保存新项目和新所有权元组,但不保存用户,因为它们已经存在。
  • 您的所有权等级在哪里?它有任何验证吗?
  • 听起来您的电子邮件地址为“example@example.com”的用户不止一个
  • 我已经用 Ownership 类更新了帖子。

标签: ruby-on-rails ruby-on-rails-3 ruby-on-rails-3.1 ruby-on-rails-3.2


【解决方案1】:

您的项目的所有权记录无效,因为它要求存在project_id,对于新项目,nil。您需要先创建项目或更改 Ownership 模型中的验证。

您可以通过检查所涉及模型的错误对象来看到这一点:

> prj.errors.full_messages
=> ["Ownerships is invalid"]
> prj.ownerships.first.errors.full_messages
=> ["Project can't be blank"]

【讨论】:

  • 我实际上正在寻找一种原子方式来完成它,这样如果一个失败,另一个也失败了。如果系统以某种方式无法创建所有权元组,我不喜欢其他悬空项目。
  • 我个人不会验证您的所有权user_idproject_id。这些是阻止创建所有权的唯一限制,并且它们并没有真正为您带来太多收益,因为 Rails 正在通过关联为您处理创建。验证对于用户可以进行更正的情况很有用......他们似乎没有直接在您的情况下编辑所有权。
【解决方案2】:

尝试将ownership 类的验证更改为

validates :user, presence: true
validates :project, presence: true

不确定验证实际关联 (project) 与 id (project_id) 的区别是否会有所不同,但值得一试。也就是说,如果您是从项目方面创建关联(并且项目必须始终有一个用户,而不是其他方式),那么根据您的业务规则,您只有真正需要用户方无论如何都要验证。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-15
    • 1970-01-01
    • 1970-01-01
    • 2014-04-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多