如何处理依赖对象(不确定如何表达)

how to treat dependent objects (not sure how to phrase this)

我正在学习 TDD 和 rails。我正在为一个 "logic" 问题伤害自己。先介绍一个情况。

我们有 3 个模型:ProjectMissionAttachment。我是这样创建的

rails g model Mission
rails g model Project
rails g model Attachment title:string attachable:references{polymorphic}
rake db:migrate

什么产生了这个schema.rb

ActiveRecord::Schema.define(version: 20180307200338) do
  create_table "attachments", force: :cascade do |t|
    t.string "attachable_type"
    t.integer "attachable_id"
    t.string "title"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.index ["attachable_type", "attachable_id"], name: "index_attachments_on_attachable_type_and_attachable_id"
  end
  create_table "missions", force: :cascade do |t|
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end
  create_table "projects", force: :cascade do |t|
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end
end

对于模型,我们有:

# app/models/mission.rb
class Mission < ApplicationRecord
  has_many :attachments, :as => :attachable
end

# app/models/project.rb
class Project < ApplicationRecord
  has_many :attachments, :as => :attachable
end

# app/models/attachment.rb
class Attachment < ApplicationRecord
  belongs_to :attachable, polymorphic: true
end

现在我们有了上下文,我想介绍一下我的"logic"问题。对我来说,创建一个 Attachment 是完全符合逻辑的:

Mission.find(1).attachments.create(file: 'my-file.jpg')
Project.find(1).attachments.create(file: 'my-file.jpg')

但很难想象自己会创建这样的附件:

Attachment.create(attachable: Mission.find(1))
Attachment.create(attachable: Project.find(1))

在开始TDD之前,我从来没有想过这个。我总是使用第一种方法,仅此而已。但现在我正在为我的附件模型编写测试,我最终做了如下事情:

require 'test_helper'

class AttachmentTest < ActiveSupport::TestCase

  test "should be valid" do
    resource = build(:attachment)
    assert resource.valid?
  end

  # FIXME is 'attachable' the final name?
  test "should require attachable" do
    resource = build(:attachment, attachable: nil)
    assert resource.invalid?
  end

  test "should require file" do
    resource = build(:attachment, file: nil)
    assert resource.invalid?
  end
end

不知何故,我正在测试永远不会发生的场景 build(:attachment)

所以我的问题是:我应该放弃思考 "I have to do it in order to prove Project.attachments.build() is gonna work" 吗?

我也在 ProjectMission 中进行测试,例如:

这变得令人困惑。

在测试方面,这个关系应该怎么测试?

抱歉这么久了(也许)有点混乱 post。

编辑

问题bonus有没有办法简单的说"we can not create from Attachment and have to go through a relation"

在我看来,您正在尝试测试 rails:

中内置的功能
  • 应该有很多附件 = 测试has_many :attachments
  • 应该允许创建附件 = 测试accepts_nested_attributes_for :attachments
  • 应保存附件 = has_many
  • 的测试autosave
  • 应该检索附件 = 再次测试has_many :attachments

还有,你自己说的:

Somehow, I'm testing scenarios that will never happened build(:attachment).

那么何必呢?


您想测试您的对象以确保它们响应 规格。例如,如果你想确保 Attachment 必须有 attachable,那么你可以写:

test 'must have attachable' do
  attachment = Attachment.new.tap(&:valid?)
  assert_includes(attachment.errors.details[:attachable], { error: :blank })
end

这是,我认为,确保您对属性进行存在验证的最佳选择。