Rails灯具创建顺序问题

时间:2011-02-09 21:26:39

标签: ruby-on-rails ruby unit-testing rake

我正在阅读Sitepoint的Simply Rails一书并给出了这些模型:

story.rb

class Story < ActiveRecord::Base
    validates_presence_of :name, :link
    has_many :votes do
        def latest
            find :all, :order => 'id DESC', :limit => 3
        end
    end

    def to_param
        "#{id}-#{name.gsub(/\W/, '-').downcase}"
    end
end

vote.rb

class Vote < ActiveRecord::Base
    belongs_to :story
end

并给出了这个装置

stories.yml

one:
  name: MyString
  link: MyString

two:
  name: MyString2
  link: MyString2

votes.yml

one:
  story: one

two:
  story: one

这些测试失败了:

story_test.rb

def test_should_have_a_votes_association
    assert_equal [votes(:one),votes(:two)], stories(:one).votes
  end

def test_should_return_highest_vote_id_first
    assert_equal votes(:two), stories(:one).votes.latest.first
  end

然而,如果我颠倒了故事的顺序,对于第一个断言并为第一个断言提供第一个投票,它会通过

story_test.rb

def test_should_have_a_votes_association
    assert_equal [votes(:two),votes(:one)], stories(:one).votes
  end

  def test_should_return_highest_vote_id_first
    assert_equal votes(:one), stories(:one).votes.latest.first
  end

我复制了书中的所有内容,并没有看到关于此的勘误。我的第一个结论是,夹具在声明时从下到上创建记录,但这没有任何意义

任何想法?

编辑:我正在使用在RVM中运行的Rails 2.9

2 个答案:

答案 0 :(得分:8)

您的灯具没有像您期望的那样获得ID 1,2,3等等 - 当您添加灯具时,它们会根据表名和灯具名称的散列获得ID(我认为)。对我们人类而言,它们看起来就像随机数字。

Rails执行此操作,因此您可以轻松地通过名称引用其他灯具。例如,灯具

#parents.yml
vladimir:
  name: Vladimir Ilyich Lenin

#children.yml
joseph:
  name: Joseph Vissarionovich Stalin
  parent: vladimir

实际上显示在您的数据库中,如

#parents.yml
vladimir:
  id: <%= fixture_hash('parents', 'vladimir') %>
  name: Vladimir Ilyich Lenin

#children.yml
joseph:
  id: <%= fixture_hash('children', 'joseph') %>
  name: Joseph Vissarionovich Stalin
  parent_id: <%= fixture_hash('parents', 'vladimir') %>

特别注意子模型中从parent: vladimirparent_id: <%= ... %>的扩展 - 这就是Rails处理灯具之间关系的方式。

故事的道德:不要指望你的灯具有任何特定的顺序,并且不要指望:order => :id在测试中给你有意义的结果。反复使用results.member? objX代替results == [obj1, obj2, ...]。如果您需要固定ID,请自行硬编码。

希望这有帮助!

PS:列宁和斯大林实际上没有关联。

答案 1 :(得分:1)

Xavier Holt已经给出了主要答案,但是也想提一下,可以强制轨道以一定的顺序读入灯具。

默认情况下,rails会分配自己的ID,但您可以利用YAML omap规范来指定有序映射

# countries.yml
--- !omap
- netherlands:
    id:         1
    title:      Kingdom of Netherlands
- canada:
    id:         2
    title:      Canada

由于您强制订单,您还必须自己手动指定ID,如上所示。

此外,我不确定这一部分,但我认为一旦你承诺覆盖默认的rails生成的ID并使用你自己的ID,你必须为所有下游引用做同样的事情。

在上面的示例中,假设每个国家/地区可以有多个领导者,您可以执行类似

的操作
# leaders.yml
netherlands-leader:
  country_id: 1   #you have to specify this now!
  name: Willem-Alexander

您需要手动指定引用之前模型(国家/地区)的ID