【问题标题】:Multiple entries in a :has_many through association:has_many 中的多个条目通过关联
【发布时间】:2012-07-08 23:57:17
【问题描述】:

我需要一些关于我正在使用 rails 3 进行的 Rails 开发的帮助。 这个应用程序是在几个月前刚推出时就给我的,从那以后我就非常喜欢 Ruby。

我有一组可以通过团队表分配资源的项目。

团队记录具有开始日期和结束日期(即资源从项目中分配和取消分配的时间)。

如果用户已从项目中分配和取消分配,并且在以后将其分配回项目中, 我不想重写结束日期,而是想在 Teams 表中创建一个新条目,以便能够跟踪资源分配给某个项目的日期。

所以我的问题是,是否可以通过关联在 :has_many 中有多个条目?

这是我的联想:

class Resource < ActiveRecord::Base
  has_many :teams
  has_many :projects, :through => :teams 
end

class Project < ActiveRecord::Base
  has_many :teams
  has_many :resources, :through => :teams
end

class Team < ActiveRecord::Base
  belongs_to :project
  belongs_to :resource
end

我在Project.rb中也有如下函数:

after_save  :update_team_and_job

private
  def update_team_and_job

    # self.member_ids is the selected resource ids for a project

    if self.member_ids.blank?
      self.teams.each do |team|
        unless team.deassociated
          team.deassociated = Week.current.id + 1
          team.save
        end
      end
    else
      self.teams.each do |team|

        #assigning/re-assigning a resource

        if self.member_ids.include?(team.resource_id.to_s)
          if team.deassociated != nil
            team.deassociated = nil
            team.save
          end
        else

          #de-assigning a resource

          if team.deassociated == nil
            team.deassociated = Week.current.id + 1
            team.save
          end
        end
      end

      y = self.member_ids - self.resource_ids
      self.resource_ids = self.resource_ids.concat(y)

      self.member_ids = nil
    end
  end
end

【问题讨论】:

  • 当然,你可以创建新的,这个有很多,我不明白你的问题。
  • 他的“问题”有点难以从他的帖子中梳理出来,但比大多数客户需求收集任务要少,祝你的职业生涯好运。
  • 好吧,选错了词,我的意思是如果一个资源已经被关联和解除关联,我如何创建一个新的关联而不是仅仅覆盖已经存在的关联?

标签: ruby-on-rails model-associations


【解决方案1】:

当然,您可以有多个关联。 has_many 采用 :uniq 选项,您可以将其设置为 false,并且正如文档所述,它对于 :through rel'ns 特别有用。

您的代码正在查找现有团队并设置取消关联,而不是添加新团队(我认为最好将其命名为 TeamMembership)

我认为你只想做这样的事情:

  1. 为活跃的会员添加一个 assoc(但在这个使用 uniq: => true:

    has_many :teams
    has_many :resources, :through => :teams, :uniq => false
    has_many :active_resources, 
             :through => :teams, 
             :class_name => 'Resource', 
             :conditions => {:deassociated => nil},
             :uniq => true
    
  2. 添加时,如果它不存在,则添加到 active_resources,并“取消关联”任何已删除的团队:

    member_ids.each do |id|
      resource = Resource.find(id) #you'll probably want to optimize with an include or pre-fetch
      active_resources << resource # let :uniq => true handle uniquing for us
    end
    
    teams.each do |team|
      team.deassociate! unless member_ids.include?(team.resource.id) # encapsulate whatever the deassociate logic is into a method
    end
    

代码少得多,而且更惯用。此外,代码现在更明确地反映了业务建模

警告:我没有为此编写测试应用程序,代码可能缺少一两个细节

【讨论】:

  • 感谢您的回复。每当将资源添加到项目中时,我想创建一个新团队而不是查找现有团队并设置取消关联,那么我会从 after_save 回调中删除此代码吗?我也尝试了您的建议,但我一直收到错误消息 - “无法找到关联:模型项目中的团队”。
  • 您仍然希望您的团队关联您已经定义,并在其上设置 :uniq false。没有理由不在给定的外键或连接表上(并且通常会导致更好的建模)具有多个定义的关联,并根据条件进行区分。我将编辑我的答案以重复团队成员。
  • 这一行:active_resources false (这将是一个 Rails 错误);如果是这种情况,请尝试执行 active_resources.create(:resource => resource)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多