使用acts_as_taggable_on为模型创建夹具数据

时间:2010-11-01 17:05:31

标签: ruby-on-rails testing fixtures acts-as-taggable-on

我正在使用acts_as_taggable_on插件为我的Framework模型提供标记。我已经获得了Rails生成的功能测试,以及它使用的灯具,我想扩展它们以添加一些标签,以便我可以通过标签等来测试搜索。

我是否必须为taggingstag表创建灯具并在功能测试的顶部加载它们?如果是这样,我该怎么做?我没有理解here描述的关系的语法。另一种方法是在测试搜索行为之前获取Framework实例并将标记添加到其中吗?或者,如果我这样做,Rails的神会让我失望吗?

6 个答案:

答案 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")