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.
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.