Rails:对于模型 A has_many B Belongs_to C 返回 A,其中 B 属于 C 并且 B 是最近为给定 A 创建的?

发布于 2024-08-21 14:20:26 字数 467 浏览 6 评论 0原文

我有三个模型 A、B 和 C,其中 A has_many BB 属于 C,并且 B 有一个created_on 时间戳。 C has_many A through B。

我想返回all A,其中A有一个属于C的B,并且B是该A最近创建的B。

我可以使用方法循环来做到这一点。这可以仅使用named_scopes来完成吗?还是其他一些优雅/有效的方式?

根据对现实世界 (TM) 的请求,示例 A、B 和 C 可以想象为宠物 (A)、宠物名称 (B) 和名称 (C)。宠物名称是在特定时间赋予宠物的,任何给定的名称都可以赋予许多宠物。任何宠物都可以有多个名称(:通过关系)。对于给定的名称,我想要所有个宠物,其中该名称是该宠物最近创建的 PetName。该调用可能类似于 @name.pets.most_recently_named_as

I have three models A, B, and C, where A has_many B; B belongs to C, and B has a created_on timestamp. C has_many A through B.

I want to return all A where A has a B that belongs to C and where B is the most recently created B for that A.

I can do this with a method loop. Can this be done solely with named_scopes?, or is some other elegant/efficient manner?

As per request for real world (TM) examples A, B and C can be imagined as, for instance, Pets (A), PetsName (B), and Names (C). PetsNames are given to Pets at a specific time, and any given Name can be given to many Pets. Any Pet can have many Names (a :through relationship). For a given Name I want all of the Pets in which that Name is the most recently created PetName for that Pet. The call may look something like @name.pets.most_recently_named_as

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

葵雨 2024-08-28 14:20:26

Rails 的方法是在 pets 上指定一个命名范围。

像这样的事情:

class Pets
  has_many :pet_names
  has_many :names, :through => :pet_names

  named_scope :with_current_name, lambda {|name| 
    { :joins => "JOIN (pet_names pna, names) " +
        "ON (pna.pet_id = pets.id AND pna.name_id = names.id) " +
        "LEFT JOIN pet_names pnb " +
        "ON (pnb.pet_id = pets.id AND pna.created_at < pnb.created_at)", 
      :conditions => ["pnb.id IS NULL AND names.id = ? ", name]
    }
  }
end

Pets.with_current_name(@name)
@name.pets.with_current_name(@name)

为了保持事物以名称为中心,您始终可以在 C/Name 上定义一个调用命名范围的方法。

你总是可以这样做

class Name < ActiveRecord::Base
  has_many :pet_names
  has_many :pets, :through => :pet_names

  def currently_named_pets
    Pets.with_current_name(self)
  end
end

@name.currently_named_pets

这是一个相当复杂的连接。这表明您可能应该重新考虑存储这些信息的方式。为什么名称位于单独的表中如此重要?

您最好这样做:将

nameold_name 列添加到 Pet 后:

class Pet < ActiveRecord::Base
  serialize :old_name, Array
  def after_initialization 
    @old_name ||= []
  end

  def name= new_name
    self.old_name << new_name
    self.name = new_name
  end

  named_scope :with_name, lambda {|name|
     { :conditions => {:name => name}}
  }
end

The Rails way to do this is a named scope on pets.

Something like this:

class Pets
  has_many :pet_names
  has_many :names, :through => :pet_names

  named_scope :with_current_name, lambda {|name| 
    { :joins => "JOIN (pet_names pna, names) " +
        "ON (pna.pet_id = pets.id AND pna.name_id = names.id) " +
        "LEFT JOIN pet_names pnb " +
        "ON (pnb.pet_id = pets.id AND pna.created_at < pnb.created_at)", 
      :conditions => ["pnb.id IS NULL AND names.id = ? ", name]
    }
  }
end

Pets.with_current_name(@name)
@name.pets.with_current_name(@name)

To keep things name centric you could always define a method on C/Name that invokes the named scope.

You could always do

class Name < ActiveRecord::Base
  has_many :pet_names
  has_many :pets, :through => :pet_names

  def currently_named_pets
    Pets.with_current_name(self)
  end
end

And

@name.currently_named_pets

It's a pretty complicated join. Which is an indicator that you should probably should rethink the way you store this information. Why is it so important that Names be in a separate table?

You might be better off doing something like this:

After adding name and old_name columns to Pet:

class Pet < ActiveRecord::Base
  serialize :old_name, Array
  def after_initialization 
    @old_name ||= []
  end

  def name= new_name
    self.old_name << new_name
    self.name = new_name
  end

  named_scope :with_name, lambda {|name|
     { :conditions => {:name => name}}
  }
end
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文