我正在阅读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
答案 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: vladimir
到parent_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