Mat*_*ieu 5 postgresql rspec ruby-on-rails ruby-on-rails-4 factory-bot
在我的ruby on Rails应用程序上,当创建模型Deal时,我使用after_create在DealPrize表上创建奖品。
Deal和DealPrize有一个属于/有很多关系:一个Deal有很多Deal奖品,一个Dealprize属于Deal。
它的工作方式是这样的:在我的管理面板(使用activeadmin)上,在Deal中,我有一个“奖品编号”列,并且我使用了after_create,因此,每次管理员创建新交易时,应用程序都会使用此award_number列,并在DealPrize表中创建此数量的奖品(根据需要插入尽可能多的行)。
我使用rspec和FactoryGirl的测试失败。可能是由于rspec / factory girl在prepare_statements中的表现不佳。我不确定。
这是我的代码
型号/deal.rb
has_many :deal_prizes, dependent: :delete_all
after_create :create_dealprizes
# Constants
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
Run Code Online (Sandbox Code Playgroud)
这是我的测试:我想确定在创建交易时,如果交易的awards_number为340,则在Dealprizes表上应按原样添加340行。
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
Run Code Online (Sandbox Code Playgroud)
我使用工厂进行交易:
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
Run Code Online (Sandbox Code Playgroud)
这是DealPrizes的工厂:
FactoryGirl.define do
factory :deal_prize do
end
end
Run Code Online (Sandbox Code Playgroud)
这是我得到的错误:
PG::UnableToSend:
server closed the connection unexpectedly
This probably means the server terminated abnormally
before or while processing the request.
Run Code Online (Sandbox Code Playgroud)
如果需要,这是我如何处理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
Run Code Online (Sandbox Code Playgroud)
每次运行方法时,您都需要从池中获取一个新连接(并确保完成后将其返回到池中)。看看with_connection。
像这样的东西应该有效。
class Deal < ActiveRecord::Base
has_many :deal_prizes, dependent: :delete_all
after_create :create_dealprizes
# Constants
TIME_SET = Time.zone.now
def create_dealprizes
self.class.connection_pool.with_connection do |connection|
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
connection.execute("START TRANSACTION")
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
connection.execute("COMMIT")
end
end
end
Run Code Online (Sandbox Code Playgroud)
这应该可行,但在我看来(就其价值而言)它不是很 Ruby 风格。听起来您很关心性能,所以我会使用单个 INSERT 语句添加数据。您可以手动构建它,但是activerecord-import gem 使它变得非常容易。
使用该 gem 可能看起来像:
class Deal < ActiveRecord::Base
has_many :deal_prizes, dependent: :delete_all
after_create :create_dealprizes
def create_dealprizes
prizes = prizes_number.times.map do
deal_prizes.build(created_by: admin_user, prize_id: 5)
end
DealPrize.import(prizes)
end
end
Run Code Online (Sandbox Code Playgroud)
下面是一个使用 ActiveRecord 导入的示例应用程序。
| 归档时间: |
|
| 查看次数: |
1176 次 |
| 最近记录: |