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

发布于 2024-09-30 11:41:20 字数 466 浏览 8 评论 0原文

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

我是否必须为 taggingstag 表并将它们加载到我的功能测试的顶部?如果是这样,我该怎么做?我还没有理解此处描述的关系语法。另一种选择是在测试搜索行为之前获取一个 Framework 实例并向其添加标签吗?或者如果我这样做的话,Rails 诸神会击倒我吗?

I'm using the acts_as_taggable_on plugin to provide tagging for my Framework model. I've got the functional tests that Rails generates, as well as the fixtures it uses and I would like to expand them to add some tags so that I can test searching by tag, etc.

Do I have to create fixtures for the taggings and tag tables and load them at the top of my functional tests? If so, how do I do that? I haven't gotten my head around the syntax for relations described here. Would an alternative be to grab a Framework instance and add the tags to it before testing the searching behavior? Or will the Rails gods strike me down if I do that?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

清风不识月 2024-10-07 11:41:20

我面临着同样的问题。在进行了一些反复试验、阅读有关装置、关联的文档和@barnaclebarnes 对这个问题的回答之后,我想出了以下方法。

我使用rails 4.2.0acts-as-taggable-on 3.5.0来完成此操作。

备注:
我之前的回答确实有效,但有点古怪。在 @David 向我指出了一种更干净的方法之后,我完全重写了它 - 完全省略了我的尝试和错误并坚持解决方案。

一种促进 Rails @barnaclebarnes 解决方案的更多机载设施的方法

将提供更多的自动化功能,但也意味着在 ids 上进行更多的打字和簿记。所以我一直在寻找更简洁的方法。

多态关系

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

高级夹具

ActiveRecord::FixtureSet 的 ruby​​doc 描述了ActiveRecord 及其对固定装置关系的作用(章节关联的标签参考):

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

在页面的更下方,还有一些有关多态belongs_to 的详细信息。

这将允许像这样的标记固定装置定义:

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

命名空间固定装置和模型

ActiveRecord::TestFixtures 提供了一种方法来显式设置夹具的模型类,以防无法推断。
换句话说:您可以使用目录来命名设备并将它们与其命名空间模型相匹配。
要加载acts_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

如果您 erb 了 yaml 文件,则可以对可标记模型及其实例进行相当低的维护定义。

I was faced with the same problem. I came up with following approach after I did some trial-and-error, read through documentation about fixtures, associations and @barnaclebarnes answer to this question.

I did this with rails 4.2.0 and acts-as-taggable-on 3.5.0.

Remark:
My previous answer did the trick, but was a bit wacky. I completly rewrote it after @David pointed me to a cleaner way - completly ommited my Trial and Error and stuck to the solution.

An approach facilitating more of the on-board facilities of rails

@barnaclebarnes solution would provide a little more automatism, but also means much more typing and bookkeeping on ids. So I kept looking for a more concise way.

Polymorphic relations

acts_as_taggable_on uses a polymorphic relation named taggable to implement the relation between tags and different models. See the rails guide on associations for details on polymorphic relations.

Advanced Fixtures

The rubydoc of ActiveRecord::FixtureSet describes the workings of ActiveRecord and what it does with relations of fixtures (chapter Label references for associations):

Active Record reflects on the fixture's model class, finds all the belongs_to associations, and allows you to specify a target label for the association [...] rather than a target id for the FK [...].

A bit further down on the page, there are also some details on polymorphic belongs_to.

This would allow for a tagging fixture definition like this:

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

Namespaced Fixtures and Models

ActiveRecord::TestFixtures provides a method to explicitly set the model class for a fixture in case it can not be inferred.
In other words: you can use directories to namespace fixtures and match them with their namespaced models.
To load test data for tags and taggings of acts_as_taggable_on we can put their fixtures in the subfolder fixtures/acts_as_taggable_on/ (Remark: fixtures/ActsAsTaggableOn/ would also work)

Put It All Together

# 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

If you erb up the yaml files this allows for a pretty low maintanance definition of taggable models and their instances.

行至春深 2024-10-07 11:41:20

如果您想使用 TestUnit,则设置一些标签(在夹具文件 taggings.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。

If you want to use TestUnit then set up some tags (in fixture file tags.yml):

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

And then set up the taggings (in fixture file taggings.yml):

tagging_one:
  tag_id: <%= ActiveRecord::Fixtures.identify(:tag_one) %>
  taggable_id: <%= ActiveRecord::Fixtures.identify(:framework_one) %>
  taggable_type: Framework
  context: tags

Basically the ActiveRecord::Fixtures.identify(:tag_one) gets the ID for the tag to put into the right column.

南街女流氓 2024-10-07 11:41:20

通常最好在需要时即时创建这些东西。夹具很快就会变得非常难以管理,当您将来查看测试时,您将需要查看三到四个夹具文件来了解正在发生的情况。

我建议花一点时间看看 Factory_girl gem,它将在将来为您节省大量时间。您可以这样做:

# 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')

It's generally best to create these kinds of things on the fly as you need them. Fixtures can quickly become pretty unmanageable, and when you look at the test in the future you will need to look at three or four fixture files to unpick what is happening.

I'd recommend taking a little time out to look at the factory_girl gem, it will save you loads of time in the future. You'd do something like this:

# 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

Then in your functional or unit tests you can easily create objects with the specific properties you need for an individual test:

# 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')
眼角的笑意。 2024-10-07 11:41:20

使用 :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')

不会引发错误,但它不会悄悄创建标签。

希望这有帮助!

using :tags_list did not work for me:

> undefined method `tags_list=' for #<Project:0xb610b24>

What did work was in your actual factory, you need to add it like such:

Factory.define(:project) do |f|
  f.tags_list ("factory")
end

I have also found that this needs to be in the parent-level factory, for some reason it does not work from children. I have also found that calling

@framework = Factory.build(:framework, :tag_list => 'foo, bar')

Doesn't throw an error, but it quietly does NOT create a tag.

Hope this helps!

空心↖ 2024-10-07 11:41:20

这就是我将标签(使用 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 时, 我会这样写: code>poetry,我写道:

create(:post, :poetry)

而且效果很好。

This is how I add tags (using acts-as-taggable-on) to my user model (using factory_girl):

FactoryGirl.define do 
  factory :post do 
    ...
    trait :poetry do
      after(:create) { |post| post.update_attributes(tag_list: 'poetry') }
    end
  end
end

This way when I want to create just a regular Post object, I write:

create(:post)

but when I want to create a Post tagged with poetry, I write:

create(:post, :poetry)

And it works pretty well.

握住我的手 2024-10-07 11:41:20

这是我发现在测试中添加标签的最简单方法。如果您有一个像这样设置的模型:

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

This is the easiest way I have found to add tags in your tests. If you have a model set up like this:

class User < ActiveRecord::Base
  acts_as_taggable # Alias for acts_as_taggable_on :tags
  acts_as_taggable_on :skills, :interests
end

And you are using FactoryGirl, you can create them like this:

user1 = create(:user, tag_list: "SomeTag",
                      skill_list: "SomeSkillTag",
                      interest_list: "SomeInterestTag")
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文