googleapis / googleapis/ruby-spanner-activerecord
BufferedMutation breaks after_xxx hooks.
- Dominant language
- Ruby
- Stars
- 105
- Forks
- 37
- Avg merge
- 10h 2m
- Merged PRs (30d)
- 5
Description
## Problem
activerecord-spanner-adapter breaks ActiveRecord's after_xxx hooks.
Perhaps this is a problem caused by BufferedMutation.
Like codes shows in bellow, I am unable to retrieve the record in the `after_save` block immediately after insertion.
I doubt that this similar problem is also happening in `after_update` and `after_create`.
## Solution(?)
I do not have a idea to monkey-patch for this problem.
My only solution was to remove `require "activerecord_spanner_adapter/base"` from lib.
https://github.com/googleapis/ruby-spanner-activerecord/blob/07f5b6cbfc701848e3aebf4cb195d267d9e52fb8/lib/active_record/connection_adapters/spanner_adapter.rb#L23
## Reproduce
sample code:
```ruby
require "bundler/inline"
gemfile do
source "https://rubygems.org"
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
gem 'activerecord', '6.1.6'
gem 'activerecord-spanner-adapter'
# gem 'activerecord-spanner-adapter',
# git: 'https://github.com/googleapis/ruby-spanner-activerecord',
# ref: '2d30298fd0dedb447ce9ff089df43c65131dc9fe' # composite-pk branch
end
require "active_record"
require "activerecord-spanner-adapter"
require "google/cloud/spanner"
spanner = Google::Cloud::Spanner.new project: "test-project", emulator_host: "localhost:9010"
job = spanner.create_instance "test-instance",
name: "Test Instance",
config: "emulator-config",
nodes: 1
job.wait_until_done!
instance = spanner.instance "test-instance"
job = instance.create_database "testdb", statements: []
job.wait_until_done!
ActiveRecord::Base.establish_connection(project: "test-project", adapter: "spanner", instance: "test-instance", database: "testdb", emulator_host: "localhost:9010")
ActiveRecord::Schema.define do
create_table :singers, force: true, id: false do |t|
t.integer :singer_id, null: false, primary_key: true
t.column :first_name, :string, limit: 200
t.string :last_name
end
end
class Singer < ActiveRecord::Base
after_save do
Singer.print_name
end
def self.print_name
puts "first name => #{Singer.first&.first_name}"
end
end
Singer.create(first_name: "John", last_name: "Doe")
Singer.print_name
singer = Singer.first
singer.first_name = "Jane"
singer.save!
```
output:
```
-- create_table(:singers, {:force=>true, :id=>false})
-> 0.0135s
first name => <=== can't see created record in after_save
first name => John
first name => Jane
```
This is expected output by using MySQL or remove `require "activerecord_spanner_adapter/base"` from lib.
```
-- create_table(:singers, {:force=>true, :id=>false})
-> 0.0172s
first name => John
first name => John
first name => Jane
```
Contributor guide
Assessment
This issue has not been assessed yet.