Q&A. Trailbalzer Testing - Implications of contract method

123 Views Asked by At

The following Q&A is based on the examples given in the Trailblazer book pp. ~50-60 as adapted for my specific requirements. You can simply think of ARInvoice and ar_invoice as Thing and thing to get the general drift if following in the book.

My operation.rb file for this was:

class ARInvoice < GLTransaction   class Create <
  Trailblazer::Operation

    include( Model )
    model( ARInvoice, :create )

    contract() do
      property( :invoice_number )
      property( :currency_code )
      property( :forex_rate )
      property( :gl_account_id )

      validates( :invoice_number, :presence => true )
      validates( :currency_code, :presence => true )
    end

    def process( params )
      @model = ARInvoice.new  # have to use instance variable here
      validate( params[ :ar_invoice ], @model ) do |f|
        f.save
      end
    end
  end
end

I adapted this test from the trailblazer book:

it("INSERTs a valid invoice") do
  test_time = Time.now
  puts(test_time)
  ar_invoice = ARInvoice::Create.(
    :ar_invoice => {
      :invoice_number => 101,
      :gl_account_id => 1,
      :effective_from => test_time.to_s
    }
  ).model

  ar_invoice.persisted?.must_equal(true)
  ar_invoice.invoice_number.must_equal(101)
  ar_invoice.transaction_type.must_equal('IN')
  ar_invoice.effective_from.must_equal(test_time)
  ar_invoice.superseded_after.must_equal(nil)
end

And I got this error:

ar_invoice crud Create#test_0001_INSERTs a valid invoice: \
ActiveRecord::StatementInvalid: SQLite3::ConstraintException: \
gl_transactions.effective_from may not be NULL: \
INSERT INTO "gl_transactions" . . .

But I also see this:

# Running:
2016-02-08 11:24:35 -0500
E

So, test_time value is set. Why is it not getting into the effective_from attribute?

The answer I give below.

1

There are 1 best solutions below

0
On BEST ANSWER

The problem was that I did not grasp the significance of the contract do/end block as used in Trailblazer (TBR). The way I initially read the book was that the contract is concerned with the form. My experience with RoR led me to map the word form with the word view. My mistake. But one that might trip someone else as well.

The correct contract block contains the missing attribute: effective_from

contract() do
  property( :invoice_number )
  property( :currency_code )
  property( :forex_rate )
  property( :gl_account_id )

  property( :effective_from )

  validates( :invoice_number, :presence => true )
  validates( :currency_code, :presence => true )
end

For now, it helps me if I map the word form to params[ :model ]. Because the attributes that are looked for in the params[ :model ] hash when the process method is called are limited to those attributes explicitly listed in the contract do/end block; Which is why Strong Parameters are unneeded when using TBR.

Note that the original test still fails because the currency_code validation is not met. But that was intentional at the time this test was written.