如何获得具有enum字段类型- Mongoid的模型的规范测试通过

时间:2022-04-27 22:35:01

EDIT: As per @max suggestion, I'm changing my model to use enum instead, however I can't test it for default state:

编辑:根据@max的建议,我将我的模型改为使用enum,但是我不能测试它的默认状态:

it { is_expected.to validate_inclusion_of(:status).to_allow("draft", "published") }

Works fine with the following code in the model:

在模型中可以使用以下代码:

validates :status,        :inclusion => { :in => ["draft", "published"] }

But this part still fails:

但这部分仍然失败:

it { is_expected.to have_field(:status).with_default_value_of("draft") }

Please note that I'm using Mongoid. I have this in my model spec:

请注意我使用的是Mongoid。我在我的模型说明书中有:

OLD question - kept for reference?

老问题——作为参考?

it { is_expected.to have_field(:published).of_type(Boolean).with_default_value_of(false) }

And in my model I have this:

我的模型是这样的

field :published,         type: Mongoid::Boolean,     default: false

Yet is not working. I've tried removing the Mongoid bit but get the same error:

但是不工作。我尝试删除Mongoid位,但得到了相同的错误:

Failure/Error: it { is_expected.to have_field(:published).of_type(Boolean).with_default_value_of(false) } Expected Post to have field named "published" of type Boolean with default value of false, got field "published" of type Mongoid::Boolean

失败/错误:{ is_expected。对于have_field(:publish).of_type(Boolean).with_default_value_of(false)}, Post希望Post的字段名称为“已发布”,类型为Boolean,默认值为false,则获取类型为Mongoid::Boolean的“已发布”字段

Note: I've also tried:

注意:我也尝试:

field :published,         type: Boolean,     default: false

And have added the following method in my model:

并在我的模型中增加了以下方法:

after_initialize :set_published, :if => :new_record?

then

然后

private
def set_published
  self.published ||= false
end

But nothing seems to work. What am I missing?

但似乎什么都不管用。我缺少什么?

2 个解决方案

#1


2  

If I understand correctly, you tried both Mongoid::Boolean and Boolean in your model, but not in the test.

如果我理解正确,您尝试了两个Mongoid::模型中的Boolean和Boolean,但在测试中没有。

Given the test failure message, I think it should be:

鉴于测试失败消息,我认为应该是:

it { is_expected.to have_field(:published).of_type(Mongoid::Boolean).with_default_value_of(false) }

(and field :published, type: Mongoid::Boolean, default: false in your model)

(和字段:已发布,类型:Mongoid: Boolean,默认:在您的模型中为false)

Second problem:

第二个问题:

Are you aware that have_field is to make tests on the views (the generated HTML), not to check that the field exists in the database?

您是否知道have_field用于对视图(生成的HTML)进行测试,而不是检查字段是否存在于数据库中?

We can't help you without the code of your views.

没有您的视图代码,我们无法帮助您。

To check that the default value is draft, I'm not aware of any built-in Rails test method, so you should do it by hand. First create a new instance of your model, save it, and then check that the field published has draft value.

要检查默认值是否为draft,我不知道任何内置的Rails测试方法,所以您应该手动执行。首先创建模型的新实例,保存它,然后检查已发布的字段是否具有draft值。

I'm not familiar with Rspec and the syntax you're using , but it should be something like (assuming you model is named Post):

我不熟悉Rspec和您正在使用的语法,但是应该是这样的(假设您的模型名为Post):

before {
    @post = Post.new
    # some initialization code if needed
    @post.save
}
expect(@post.published).to be("draft")

#2


1  

class Article
  include Mongoid::Document
  field :published, type: Boolean, default: false
end

require 'rails_helper'

RSpec.describe Article, type: :model do
  it { is_expected.to have_field(:published)
                      .of_type(Mongoid::Boolean)
                      .with_default_value_of(false) }
end

Passes perfectly fine on mongoid (4.0.2), mongoid-rspec (2.1.0).

在mongoid(4.0.2)、mongoid-rspec(2.1.0)上传递良好。

But quite frankly using booleans for model state is sub-optimal.

但坦率地说,用布尔值表示模型状态是次优的。

If you consider a blog post or article it could be:

如果你考虑一篇博文或一篇文章,可以是:

 1. draft
 2. published
 3. deleted
 4. ... 

Adding N number of switches in the model is icky - an awesome solution is to use Enums.

在模型中增加N个开关是令人讨厌的——一个很棒的解决方案是使用枚举。

First write the spec:

首先写规范:

RSpec.describe Article, type: :model do

  specify 'the default status of an article should be :draft' do
    expect(subject.status).to eq :draft
  end

  # or with rspec-its
  # its(:status) { should eq :draft }
end

Then add gem "mongoid-enum" to your Gemfile.

然后在您的Gemfile中添加gem“mongoid-enum”。

Finally add the enum field:

最后添加enum字段:

class Article
  include Mongoid::Document
  include Mongoid::Enum
  enum :status, [:draft, :published]
end

Enums add all this awesomeness:

无数的母亲增添了这一切:

Article.published # Scope to get all published articles
article.published? # Interrogation methods for each state.
article.published! # sets the status

#1


2  

If I understand correctly, you tried both Mongoid::Boolean and Boolean in your model, but not in the test.

如果我理解正确,您尝试了两个Mongoid::模型中的Boolean和Boolean,但在测试中没有。

Given the test failure message, I think it should be:

鉴于测试失败消息,我认为应该是:

it { is_expected.to have_field(:published).of_type(Mongoid::Boolean).with_default_value_of(false) }

(and field :published, type: Mongoid::Boolean, default: false in your model)

(和字段:已发布,类型:Mongoid: Boolean,默认:在您的模型中为false)

Second problem:

第二个问题:

Are you aware that have_field is to make tests on the views (the generated HTML), not to check that the field exists in the database?

您是否知道have_field用于对视图(生成的HTML)进行测试,而不是检查字段是否存在于数据库中?

We can't help you without the code of your views.

没有您的视图代码,我们无法帮助您。

To check that the default value is draft, I'm not aware of any built-in Rails test method, so you should do it by hand. First create a new instance of your model, save it, and then check that the field published has draft value.

要检查默认值是否为draft,我不知道任何内置的Rails测试方法,所以您应该手动执行。首先创建模型的新实例,保存它,然后检查已发布的字段是否具有draft值。

I'm not familiar with Rspec and the syntax you're using , but it should be something like (assuming you model is named Post):

我不熟悉Rspec和您正在使用的语法,但是应该是这样的(假设您的模型名为Post):

before {
    @post = Post.new
    # some initialization code if needed
    @post.save
}
expect(@post.published).to be("draft")

#2


1  

class Article
  include Mongoid::Document
  field :published, type: Boolean, default: false
end

require 'rails_helper'

RSpec.describe Article, type: :model do
  it { is_expected.to have_field(:published)
                      .of_type(Mongoid::Boolean)
                      .with_default_value_of(false) }
end

Passes perfectly fine on mongoid (4.0.2), mongoid-rspec (2.1.0).

在mongoid(4.0.2)、mongoid-rspec(2.1.0)上传递良好。

But quite frankly using booleans for model state is sub-optimal.

但坦率地说,用布尔值表示模型状态是次优的。

If you consider a blog post or article it could be:

如果你考虑一篇博文或一篇文章,可以是:

 1. draft
 2. published
 3. deleted
 4. ... 

Adding N number of switches in the model is icky - an awesome solution is to use Enums.

在模型中增加N个开关是令人讨厌的——一个很棒的解决方案是使用枚举。

First write the spec:

首先写规范:

RSpec.describe Article, type: :model do

  specify 'the default status of an article should be :draft' do
    expect(subject.status).to eq :draft
  end

  # or with rspec-its
  # its(:status) { should eq :draft }
end

Then add gem "mongoid-enum" to your Gemfile.

然后在您的Gemfile中添加gem“mongoid-enum”。

Finally add the enum field:

最后添加enum字段:

class Article
  include Mongoid::Document
  include Mongoid::Enum
  enum :status, [:draft, :published]
end

Enums add all this awesomeness:

无数的母亲增添了这一切:

Article.published # Scope to get all published articles
article.published? # Interrogation methods for each state.
article.published! # sets the status