5

我正在使用acts_as_taggable_on插件为我的Framework模型提供标记。我有 Rails 生成的功能测试,以及它使用的固定装置,我想扩展它们以添加一些标签,以便我可以测试按标签等搜索。

我是否必须为taggingstag表创建固定装置并将它们加载到我的功能测试的顶部?如果是这样,我该怎么做?我还没有完全理解这里描述的关系的语法。是否可以在测试搜索行为之前获取一个Framework实例并将标签添加到其中?或者如果我这样做,Rails 之神会击倒我吗?

4

6 回答 6

8

我面临着同样的问题。在我做了一些试验和错误之后,我想出了以下方法,通读关于夹具、关联和@barnaclebarnes 对这个问题的回答的文档。

我用rails 4.2.0作为可标记的 3.5.0做到了这一点。

备注: 我之前的回答成功了,但有点古怪。在@David 向我指出一种更清洁的方式之后,我完全重写了它——完全省略了我的反复试验并坚持解决方案。

一种促进更多轨道车载设施的方法

@barnaclebarnes 解决方案将提供更多的自动化,但也意味着更多的 id 打字和簿记。所以我一直在寻找更简洁的方法。

多态关系

acts_as_taggable_on使用一个名为taggable的多态关系来实现标签与不​​同模型之间的关系。有关多态关系的详细信息,请参阅有关关联的 rails 指南。

高级夹具

ActiveRecord::FixtureSet的ruby​​doc描述了 ActiveRecord 的工作原理以及它对灯具关系的作用(章节Label references for associations):

Active Record 反映fixture 的模型类,查找所有belongs_to 关联,并允许您为关联[...] 指定目标标签,而不是为FK [...] 指定目标ID。

在页面的下方,还有一些关于多态属于_to 的详细信息。

这将允许像这样的标记夹具定义:

tagging:
  taggable: foo (Klass)
  context: tags
  tag: bar

命名空间的夹具和模型

ActiveRecord::TestFixtures提供了一种方法来显式设置夹具的模型类,以防无法推断。换句话说:您可以使用目录来命名固定装置并将它们与其命名空间模型相匹配。要为acts_as_taggable_on 的标签和标记加载测试数据,我们可以将它们的fixtures 放在子文件夹中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 文件进行 erb 处理,则可以对可标记模型及其实例进行相当低的维护定义。

于 2015-03-22T02:12:06.777 回答
5

如果你想使用 TestUnit 然后设置一些标签(在夹具文件 tags.yml 中):

tag_one:
  name: tag one
tag_two:
  name: tag two

然后设置标签(在夹具文件 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 以放入右列。

于 2012-08-17T10:30:53.557 回答
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')
于 2010-11-20T10:33:03.267 回答
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')

不会抛出错误,但它不会悄悄地创建标签。

希望这可以帮助!

于 2011-08-08T04:02:45.573 回答
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标记时poetry,我写:

create(:post, :poetry)

而且效果很好。

于 2013-08-15T15:03:40.730 回答
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")
于 2014-12-10T14:12:16.037 回答