我正在使用acts_as_taggable_on插件为我的Framework
模型提供标记。我已经获得了Rails生成的功能测试,以及它使用的灯具,我想扩展它们以添加一些标签,以便我可以通过标签等来测试搜索。
我是否必须为taggings
和tag
表创建灯具并在功能测试的顶部加载它们?如果是这样,我该怎么做?我没有理解here描述的关系的语法。另一种方法是在测试搜索行为之前获取Framework
实例并将标记添加到其中吗?或者,如果我这样做,Rails的神会让我失望吗?
答案 0 :(得分:7)
我遇到了同样的问题。在我做了一些试错之后,我想出了关于灯具,关联和@barnaclebarnes回答这个问题的文档,我想出了以下方法。
我使用 rails 4.2.0 和 act-as-taggable-on 3.5.0 进行此操作。
<强>注:强> 我以前的答案做了伎俩,但有点古怪。在@David指出我更清洁的方式后,我完全重写了它 - 完全省略了我的试验和错误并坚持解决方案。
@barnaclebarnes解决方案会提供更多的自动化,但也意味着更多的打字和记账。所以我一直在寻找一种更简洁的方式。
acts_as_taggable_on 使用名为 taggable 的多态关系来实现标记与不同模型之间的关系。有关polymorphic relations的详细信息,请参阅关联关联指南。
ActiveRecord::FixtureSet的rubydoc描述了ActiveRecord的工作方式以及它对灯具关系的作用(章节关联的标签引用):
Active Record反映在fixture的模型类上,查找所有belongs_to关联,并允许您为关联[...]指定目标标签,而不是FK [...]的目标ID。
在页面上更下方,还有一些关于多态的belongs_to的详细信息。
这将允许这样的标记夹具定义:
tagging:
taggable: foo (Klass)
context: tags
tag: bar
ActiveRecord::TestFixtures提供了一种方法,可以在无法推断的情况下显式设置fixture的模型类。
换句话说:您可以使用目录来命名夹具,并将它们与命名空间模型匹配。
要加载act_as_taggable_on标记和标记的测试数据,我们可以将其固定符放在子文件夹fixtures/acts_as_taggable_on/
中(备注:fixtures/ActsAsTaggableOn/
也可以)
# models/item.rb
class Item < ActiveRecord::Base
acts_as_taggable_on
end
# fixtures/items.yml
item_1: {}
item_2: {}
# fixtures/acts_as_taggable_on/tags.yml
tag_1:
name: tag_1
tag_2:
name: tag_2
# fixtures/acts_as_taggable_on/taggings.yml
tagging_1
taggable: item_1 (Item)
context: tags
tag: tag_1
如果您对yaml文件进行了调整,则可以对可标记模型及其实例进行相当低的维护定义。
答案 1 :(得分:5)
如果你想使用TestUnit,那么设置一些标签(在夹具文件tags.yml中):
tag_one:
name: tag one
tag_two:
name: tag two
然后设置标记(在fixture文件taggings.yml中):
tagging_one:
tag_id: <%= ActiveRecord::Fixtures.identify(:tag_one) %>
taggable_id: <%= ActiveRecord::Fixtures.identify(:framework_one) %>
taggable_type: Framework
context: tags
基本上ActiveRecord::Fixtures.identify(:tag_one)
获取标记的ID以放入右列。
答案 2 :(得分:2)
通常最好在需要时随时创建这些类型的东西。夹具很快就变得非常难以管理,当你将来看测试时,你需要查看三到四个夹具文件来解开发生的事情。
我建议你花一点时间看看factory_girl的宝石,它将为你节省大量的时间。你会做这样的事情:
# test/factories.rb
Factory.define :framework do |f|
# Add any properties to make a valid Framework instance here, i.e. if you have
# validates_presence_of :name on the Framework model ...
f.name 'Test Name'
end
然后在功能测试或单元测试中,您可以轻松创建具有单个测试所需特定属性的对象:
# Create and save in the DB with default values
@framework = Factory.create(:framework)
# Build an object with a different name and don't save it in the DB
@framework = Factory.build(:framework, :name => 'Other name'
# Create with tags
@framework = Factory.build(:framework, :tags_list => 'foo, bar')
答案 3 :(得分:1)
使用:tags_list对我不起作用:
> undefined method `tags_list=' for #<Project:0xb610b24>
在您的实际工厂中做了什么工作,您需要像这样添加它:
Factory.define(:project) do |f|
f.tags_list ("factory")
end
我还发现这需要在父级工厂中,由于某些原因它不适用于儿童。我也发现了调用
@framework = Factory.build(:framework, :tag_list => 'foo, bar')
不会抛出错误,但它悄悄地不会创建标记。
希望这有帮助!
答案 4 :(得分:0)
这是我向用户模型添加标签(使用acts-as-taggable-on
)的方法(使用factory_girl):
FactoryGirl.define do
factory :post do
...
trait :poetry do
after(:create) { |post| post.update_attributes(tag_list: 'poetry') }
end
end
end
这样,当我想创建一个普通的Post
对象时,我写道:
create(:post)
但是当我想创建一个标有Post
的{{1}}时,我写道:
poetry
它运作良好。
答案 5 :(得分:0)
这是我在测试中添加标签的最简单方法。如果您的模型设置如下:
class User < ActiveRecord::Base
acts_as_taggable # Alias for acts_as_taggable_on :tags
acts_as_taggable_on :skills, :interests
end
你正在使用FactoryGirl,你可以像这样创建它们:
user1 = create(:user, tag_list: "SomeTag",
skill_list: "SomeSkillTag",
interest_list: "SomeInterestTag")