Rails 夹具创建顺序问题
我正在阅读 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
I am reading the book Simply Rails by Sitepoint and given these models:
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
and given this fixtures
stories.yml
one:
name: MyString
link: MyString
two:
name: MyString2
link: MyString2
votes.yml
one:
story: one
two:
story: one
these tests fail:
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
however, if I reverse the order of the stories, for the first assertion and provide the first vote for the first assertion, it passes
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
I copied everything as it is in the book and have not seen an errata about this. My first conclusion was that the fixture is creating the records from bottom to top as it was declared, but that doesn't make any point
any ideas?
EDIT: I am using Rails 2.9 running in an RVM
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您的装置没有像您期望的那样获得 ID 1、2、3 等 - 当您添加装置时,它们会根据(我认为)表名称和装置名称的哈希值获得 ID。对于我们人类来说,它们只是看起来像随机数。
Rails 这样做是为了让您可以轻松地通过名称引用其他装置。例如,灯具
实际上显示在您的数据库中,特别是
请注意从
parent: vladimir
到parent_id: <%= ... %>
的扩展子模型 - 这就是 Rails 处理装置之间关系的方式。这个故事的寓意是:不要指望你的装置按任何特定的顺序排列,也不要指望
:order =>; :id
在测试中为您提供有意义的结果。使用results.member? objX
重复而不是results == [obj1, obj2, ...]
。如果您需要固定 ID,请自行将其硬编码。希望这有帮助!
PS:列宁和斯大林实际上没有关系。
Your fixtures aren't getting IDs 1, 2, 3, etc. like you'd expect - when you add fixtures, they get IDs based (I think) on a hash of the table name and the fixture name. To us humans, they just look like random numbers.
Rails does this so you can refer to other fixtures by name easily. For example, the fixtures
actually show up in your database like
Note in particular the expansion from
parent: vladimir
toparent_id: <%= ... %>
in the child model - this is how Rails handles relations between fixtures.Moral of the story: Don't count on your fixtures being in any particular order, and don't count on
:order => :id
giving you meaningful results in tests. Useresults.member? objX
repeatedly instead ofresults == [obj1, obj2, ...]
. And if you need fixed IDs, hard-code them in yourself.Hope this helps!
PS: Lenin and Stalin weren't actually related.
Xavier Holt 已经给出了主要答案,但还想提一下,可以强制 Rails 按特定顺序读取固定装置。
默认情况下,rails 会分配自己的 ID,但您可以利用 YAML
omap
规范来指定有序映射。由于您强制执行顺序,因此您还必须自己手动指定 ID,如上所示。
我也不确定这部分,但我认为一旦您承诺覆盖默认的 Rails 生成的 ID 并使用您自己的 ID,您就必须对所有下游引用执行相同的操作。
在上面的示例中,假设每个国家/地区可以有多个领导者,您需要执行类似的操作
您需要手动指定引用先前模型(国家/地区)的 id
Xavier Holt already gave the main answer, but wanted to also mention that it is possible to force rails to read in fixtures in a certain order.
By default rails assigns its own IDs, but you can leverage the YAML
omap
specification to specify an ordered mappingSince you are forcing the order, you have to also specify the ID yourself manually, as shown above.
Also I'm not sure about this part, but I think once you commit to overriding the default rails generated ID and use your own, you have to do the same for all downstream references.
In the above example, suppose each country can have multiple leaders, you would have do something like
You need to manually specify the id that refers to the previous Model (Countries)