【问题标题】:Rails 4 model rspec for if conditional如果有条件的Rails 4模型rspec
【发布时间】:2014-12-09 14:32:07
【问题描述】:

我是 Rails 新手,我正在尝试查看我的对象以查看值是否为真,以验证对象中的所有其他项目。如果此人是用户,我当然可以验证应用程序/模型中的名称和电子邮件。为此编写规范的最佳方法是什么?

class Members < ActiveRecord::Base
    validates_presence_of :email, if: :is_user?
    validates_presence_of :first_name, if: :is_user?
    validates_presence_of :last_name, if: :is_user?

    def is_user?
        :is_user
    end
end

【问题讨论】:

  • is_user 是数据库中的一个字段。

标签: ruby rspec ruby-on-rails-4.1


【解决方案1】:

在 members 表中是否有名为“is_user”的字段?似乎该方法应该返回一个布尔值(真或假),而现在它返回一个将始终被评估为真的符号,例如,如果你这样做

if :is_user
  puts "will always happen" # this will be printed
end

如果数据库中有该字段,则无需创建该方法,因为 rails 会为模型数据库上的所有布尔字段生成带有问号的方法。

现在,要测试您是否可以使用 shoulda_matchers 之类的 gem,或者您可以编写自己的测试,例如

describe "validations" do
  context "member is a user" do
    subject { Member.new(is_user: true) }

    it "validates presence of email" do
      subject.valid?
      expect(subject.errors["email"]).to include("can't be blank")
    end
  end

  context "member is not an user" do
    subject { Member.new(is_user: false) }

    it "doesn't require fields to have info" do
      subject.valid?
      expect(subject.errors["email"]).to_not include("can't be blank")
      expect(subject.errors["first_name"]).to_not include("can't be blank")
      expect(subject.errors["last_name"]).to_not include("can't be blank")
    end
  end
end

【讨论】:

  • 是的,它是一个布尔值。所以我需要为应用模型文件做一些不同的事情吗?还是我目前可以接受的?
  • 如果它是您在数据库中is_user 字段上的布尔值,则删除该方法,否则它将始终为真,并且将始终执行这些验证。如果这是您想要的,那么您可以删除验证声明中的方法和 if: ... 部分
  • 它如何知道您是否没有明确说明该值必须为真才能使其他字段具有值?
  • 嘿,所以validates_presence_of :email, if: :is_user? 说,“仅在成员是用户时验证电子邮件是否通过”,但是,您为 is_user? 定义的方法返回一个符号,而不是数据库中的字段,但是一个始终被评估为 true 的 ruby​​ 对象。然后,该验证将每次运行,并且与数据库上字段 is_user 的值无关,因为它依赖于您定义的 is_user? 方法的结果,该方法始终是相同的值,计算结果为真的符号。
  • 当我说“评估为真”时,我的意思是当在 if 条件下使用 if :any_symbol 时,它将始终进入执行之后的任何内容。与nilfalse 不同,它们在 if 语句中使用时永远不会执行条件代码。
【解决方案2】:

你应该使用 shouda 匹配器,它会排序和漂亮:
示例取自这里Shoulda/RSpec matchers - conditional validation

context "if user" do
  before { subject.stub(:is_user?) { true } }
  it { should validate_presence_of(:name) }
  it { should validate_presence_of(:email) }
end

context "if not user" do
  before { subject.stub(:is_user?) { false } }
  it { should_not validate_presence_of(:name) }
  it { should validate_presence_of(:email) }
end

【讨论】:

    猜你喜欢
    • 2013-12-26
    • 1970-01-01
    • 1970-01-01
    • 2014-10-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多