【问题标题】:Rails "has_one" relation. Assign Project to Customer(Timestamp)Rails“has_one”关系。将项目分配给客户(时间戳)
【发布时间】:2016-04-28 09:43:33
【问题描述】:

我正在构建一个时间跟踪器。您可以创建一个带有开始时间、结束时间、客户和来自该客户的项目的时间戳。这样您就可以看到您为某个项目或客户花费了多少时间。

“has_many”表之间的关系完美无缺,但“has_one”关系存在问题。

我的桌子:

timestamps              customers             projects
----------              ------------          -----------
id:integer              id:integer            id:integer
desc:string             customer_name:string  project_name:string
customer_id:interger    project_id:integer

我的模型:

时间戳.rb

class Timestamp < ActiveRecord::Base
    has_one :customer
    has_one :project, through: :customer
end

客户.rb

class Customer < ActiveRecord::Base
   belongs_to :timestamp
   has_many :projects, dependent: :destroy
end

项目.rb

class Project < ActiveRecord::Base
    belongs_to :customer  
end

我的目标:

  1. 为关联的客户和项目创建一个时间戳:Timestamp.create({desc: "Something", customer_id: "1", project_id: "6"})
  2. 从时间戳获取项目:Timestamp.find(1).customer.project

我的问题:

如果我将 timestamp_id 包含到项目表中,我可以完成这项工作,但是使用这种方法,Rails 在我创建新时间戳时会使用特定的 timestamp_id 复制每个项目。但我想为时间戳分配一个 project_id。

仅供参考:我正在使用带有 MYSQL 数据库的 rails 4.2.6。

【问题讨论】:

  • 你的 timestamp.rb 中不应该是has_many :projects, through: :customer 吗?因为一位客户拥有许多项目。如果你故意使用 has_one,那么它只会从列表中获取第一个项目
  • 你是对的。但这并不能解决问题。不过谢谢!
  • 您的应用程序中的Timestamp 是什么,它的用途是什么?它与 Active Record 时间戳有何不同?我之所以问,是因为这闻起来像 XY 问题,而且你被困在将功能失调的解决方案转换为功能代码的过程中。也许有更好的方法。
  • @sebastian 你想实现多对多关系,比如项目有很多客户,客户有很多项目吗?如果不是,则使用简单的关系而不通过约定。
  • @Substantial 我正在构建一个时间跟踪器。您可以创建一个带有开始时间、结束时间、客户和来自该客户的项目的时间戳。这样您就可以看到您为一个项目或客户花费了多少时间。

标签: mysql ruby-on-rails ruby-on-rails-4 table-relationships


【解决方案1】:

因为您不希望每个时间戳都有重复的项目和重复的客户,所以您只需要为时间戳设置外键。通过这种方式,您会希望拥有具有以下列的表格:

Timestamps
  customer_id:integer:index
  project_id:integer:index

Customers

Projects
  customer_id:integer:index

您必须编写并运行迁移以删除列,并添加列以便它看起来在上方。

然后,修改关联:

class Timestamp < ActiveRecord::Base
  belongs_to :customer # change to belongs_to
  has_many :projects, through: :customer # you might not need this anymore because of the line below
  belongs_to :project # add this line
end

class Customer < ActiveRecord::Base
   has_one :timestamp # change to has_one
   has_many :projects, dependent: :destroy
end

class Project < ActiveRecord::Base
  belongs_to :customer
  has_one :timestamp # add this line
end

然后,您现在可以使用以下内容

Timestamp.find(1).customer
Timestamp.find(1).project
Timestamp.find(1).projects # these projects are customer.projects and are not directly associated to the line above, so I don't think you would need to call this

【讨论】:

    【解决方案2】:

    好的,谢谢大家! @Jay-Ar Polisario 您的回答并不完美,但它让我想到了我的“has_one / has_many”关系,因此在重新考虑这些问题数小时后它起作用了。谢谢。

    所有从 Google 来到这里寻找类似问题答案的人:

    开始在白板或纸上绘制表格和列。让关系可视化!这有助于我找出正确的关系。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-12
      • 1970-01-01
      • 1970-01-01
      • 2016-07-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多