In my ruby on Rails application, when creating a Deal model, I use after_create to create prizes in the DealPrize table.
The deal and DealPrize belong to the / has _many relationship: the deal has many Deal prizes, and Dealprize belongs to the deal.
It works as follows: in my admin panel (using activeadmin) inside the transaction, I have a prize number in the column, and I use after_create, so every time the administrator creates a new deal, the application accepts this column “column” and create this prize volume (inserting as many rows as necessary) inside the DealPrize table.
My tests using rspec and FactoryGirl fail. This may be due to the fact that the girl does not play well with prep_statements. I'm not sure.
Here is my code
models /deal.rb
has_many :deal_prizes, dependent: :delete_all
after_create :create_dealprizes
TIME_SET = Time.zone.now
CONNECTION = ActiveRecord::Base.connection.raw_connection
def create_dealprizes
begin
CONNECTION.describe_prepared('create_deal_prizes')
rescue PG::InvalidSqlStatementName
CONNECTION.prepare('create_deal_prizes', 'INSERT INTO deal_prizes (deal_id,created_at,updated_at,admin_user_id,prize_id) values ($1, $2, $3, $4, $5)')
end
Deal.transaction do
self.prizes_number.times do |i|
CONNECTION.exec_prepared('create_deal_prizes', [
{ value: self.id},
{ value: TIME_SET },
{ value: TIME_SET },
{ value: self.admin_user_id },
{ value: 5 }
])
end
end
end
Here is my test: I would like to be sure when the transaction will be created, if there are 340 prizes_number in the transaction, then 340 tables will be added to the Dealprizes table, as it should be.
require 'spec_helper'
describe DealPrize do
describe "the right number of rows are created inside DealPrize table when a Deal is created" do
before do
@initial_prize_count = DealPrize.count
@deal_prize = FactoryGirl.create(:deal_prize)
@deal = FactoryGirl.create(:deal_prizes => [@deal_prize], :prizes_number => 277)
end
it "does create right nb of rows" do
expect(DealPrize.count).to eq( @initial_prize_count + 277 )
end
end
end
I use factory for transactions:
FactoryGirl.define do
factory :deal do
country "France"
title "Neque porro quisquam est qui dolorem"
description "lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum"
factory :deal_skips_validate do
to_create {|instance| instance.save(validate: false) }
end
end
end
and here is the factory for DealPrizes:
FactoryGirl.define do
factory :deal_prize do
end
end
Here is the error I get:
PG::UnableToSend:
server closed the connection unexpectedly
This probably means the server terminated abnormally
before or while processing the request.
If necessary, this is how I view the transaction in my spec_helper.rb
config.use_transactional_fixtures = false
config.before(:suite) do
DatabaseCleaner.clean_with(:truncation, :except => %w(roles))
end
config.before(:each) do
DatabaseCleaner.strategy = :transaction
end
config.before(:each, js: true) do
DatabaseCleaner.strategy = :truncation
end
config.before(:each) do
DatabaseCleaner.start
end
config.after(:each) do
DatabaseCleaner.clean
end