Ruby on rails 如何确定关联中的第一个子元素?

Ruby on rails 如何确定关联中的第一个子元素?,ruby-on-rails,ruby,Ruby On Rails,Ruby,我有3张发票属于同一批货。创建的第一张发票始终是装运的主发票 Invoice id shipment_id 21 55 # This is the main invoice 88 55 93 55 如果我执行以下查询 s = Shipment.find(55) s.invoices[0] # 21 s.invoices[1] # 88 s.invoices[2] # 93 我猜子元素的顺序是由它们的id决定的。我说得对吗?或者还有其他的吗 我这样问是因为我需要确定子元素的顺

我有3张发票属于同一批货。创建的第一张发票始终是装运的主发票

Invoice 
id   shipment_id
21   55 # This is the main invoice
88   55
93   55
如果我执行以下查询

s = Shipment.find(55)
s.invoices[0] # 21
s.invoices[1] # 88
s.invoices[2] # 93
我猜子元素的顺序是由它们的id决定的。我说得对吗?或者还有其他的吗

我这样问是因为我需要确定子元素的顺序,以确保我的方法之一始终有效

def am_i_the_main_invoice?
  if self.shipment.invoices[0].id == self.id
    true
  else
    false
  end
end

除非明确设置顺序,否则顺序是随机的。虽然您的数据库现在可能会以相同的顺序返回元素,但如果您更改了任何内容(甚至是看起来不相关的内容),它可以是任何其他顺序。所以再次强调:不要信任从关系数据库检索的元素的顺序,除非您在查询中显式地设置了顺序


在您的
shipping
类中,您可能已经设置了一个
具有多个
关系,您可以添加类似
:order=>“id ASC”
的内容,以始终按id强制执行订单。

除非您明确设置,否则订单是随机的。虽然您的数据库现在可能会以相同的顺序返回元素,但如果您更改了任何内容(甚至是看起来不相关的内容),它可以是任何其他顺序。所以再次强调:不要信任从关系数据库检索的元素的顺序,除非您在查询中显式地设置了顺序


在您的
shipping
类中,您可能已经设置了一个
有许多关系,您可以添加类似
:order=>“id ASC”
的内容,以始终按id强制执行订单。

您可以向
invoices
表中添加一个标志,而不是依赖于已排序的查询:

# in migration
add_column :invoices, :is_primary, :boolean, {null: false, default: false}

# if your rdbms supports partial indexes, you can enforce it
execute 'create unique index uniq_single_primary on invoices (shipment_id) where is_primary = true'

# then query is easy ..
def am_i_the_main_invoice?
  self.is_primary?
end

您可以在
invoices
表中添加一个标志,而不是依赖于有序查询:

# in migration
add_column :invoices, :is_primary, :boolean, {null: false, default: false}

# if your rdbms supports partial indexes, you can enforce it
execute 'create unique index uniq_single_primary on invoices (shipment_id) where is_primary = true'

# then query is easy ..
def am_i_the_main_invoice?
  self.is_primary?
end

返回的顺序通常取决于您使用的SQL数据库。通常它是基于主键的,但正如前面所说的,不要相信它,因为它可以更改

您可以通过两种方式解决此问题:

  • 在您的发票模型中添加一个范围,您可以在查看您的收款之前调用该范围,例如
    范围:按装运、订单(“id ASC”)
  • 添加默认范围,以便始终按该顺序检索,例如
    default\u范围顺序(“id ASC”)

  • 希望这有帮助

    返回的顺序通常取决于您使用的SQL数据库。通常它是基于主键的,但正如前面所说的,不要相信它,因为它可以更改

    您可以通过两种方式解决此问题:

  • 在您的发票模型中添加一个范围,您可以在查看您的收款之前调用该范围,例如
    范围:按装运、订单(“id ASC”)
  • 添加默认范围,以便始终按该顺序检索,例如
    default\u范围顺序(“id ASC”)

  • 希望这有帮助

    为了可读性,我会添加一个关联扩展

    class Shipment < ActiveRecord::Base
      has_many :invoices do
        def main
          @main_invoice ||=  first(:order => "id ASC")
        end
    
        def main?(id)
          main.try(:id) == id
        end
      end
    end
    

    这样,您就清楚地公开了
    main
    invoice的概念

    为了可读性,我会添加一个关联扩展

    class Shipment < ActiveRecord::Base
      has_many :invoices do
        def main
          @main_invoice ||=  first(:order => "id ASC")
        end
    
        def main?(id)
          main.try(:id) == id
        end
      end
    end
    

    这样,您就清楚地公开了
    main
    invoice的概念

    我不得不修改查询,因为我不断地得到错误,所以这就是
    main\u invoice
    方法中的内容:
    self.invoices(:order=>'id ASC')。首先
    。我喜欢这种方法,因为它不需要更改数据库。错误是什么?另外,我认为
    发票(:order=>'id ASC')
    不会修改排序顺序。关联方法采用
    boolean
    参数来重新加载关联数组。我会先使用self.order(“id ASC”)。我使用了我给出的代码,以前它对我很有效。我不得不修改查询,因为我不断出错,所以这就是
    main\u invoice
    方法中的内容:
    self.invoices(:order=>'id ASC')。首先
    。我喜欢这种方法,因为它不需要更改数据库。错误是什么?另外,我认为
    发票(:order=>'id ASC')
    不会修改排序顺序。关联方法采用
    boolean
    参数来重新加载关联数组。我会先使用self.order(“id ASC”)。我使用过我给出的代码,它以前也为我工作过。只有在某些数据库(例如MySQL)中,当不指定顺序时,您通常会获得按primar键排序的数据。然而,即使是MySQL有时也会返回无序数据(例如在压缩之后)。其他数据库(如Postgres)更频繁地返回有序数据。一般来说(根据各种SQL标准),如果没有指定顺序,它可能是随机的。@HolgerJust我个人总是设置一个顺序,除非我不在乎,因为你是对的,甚至MySQL也会使它们无序。从我所看到的情况来看,SQLite似乎也把它们按顺序带了出来。但宁可安全也不要后悔,对吧;)只有在某些数据库(例如MySQL)中,在不指定顺序的情况下,您通常会获得按primar键排序的数据。然而,即使是MySQL有时也会返回无序数据(例如在压缩之后)。其他数据库(如Postgres)更频繁地返回有序数据。一般来说(根据各种SQL标准),如果没有指定顺序,它可能是随机的。@HolgerJust我个人总是设置一个顺序,除非我不在乎,因为你是对的,甚至MySQL也会使它们无序。从我所看到的情况来看,SQLite似乎也把它们按顺序带了出来。但宁可安全也不要后悔,对吧;)