You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Preload schema and seeds, we have 2 tables and has_many association
ActiveRecord::Schema.define do
create_table :teams, force: true do |t|
end
create_table :users, force: true do |t|
t.string :name
t.integer :team_id
end
end
class Team < ActiveRecord::Base
has_many :users
end
class User < ActiveRecord::Base
belongs_to :team
end
team = Team.create!
User.create!(name: 'A', team: team)
User.create!(name: 'B', team: team)
User.create!(name: 'C', team: team)
The issue is
team = Team.lazy_preload(:users).find(team.id)
team.users.build(name: 'D')
p 'just call team users somewhere', team.users
team.save!
p '===' * 5
team = Team.lazy_preload(:users).find(team.id)
team.users.build(name: 'D')
p 'without call team users works fine'
team.save!
p '===' * 5
team = Team.lazy_preload(:users).find(team.id)
team.users.load.build(name: 'D')
p 'with force load also works fine'
team.save!
In the first example, user D will not be created because if we call association after build we replace object to new one from database, is this expected behavior? I didn't find this in the description, many thanks!
logs
D, [2024-06-06T00:44:43.238636 #51420] DEBUG -- : TRANSACTION (0.5ms) BEGIN
D, [2024-06-06T00:44:43.239524 #51420] DEBUG -- : Team Create (1.4ms) INSERT INTO "teams" DEFAULT VALUES RETURNING "id"
D, [2024-06-06T00:44:43.240386 #51420] DEBUG -- : TRANSACTION (0.7ms) COMMIT
D, [2024-06-06T00:44:43.246105 #51420] DEBUG -- : TRANSACTION (0.6ms) BEGIN
D, [2024-06-06T00:44:43.247101 #51420] DEBUG -- : User Create (1.6ms) INSERT INTO "users" ("name", "team_id") VALUES ($1, $2) RETURNING "id" [["name", "A"], ["team_id", 1]]
D, [2024-06-06T00:44:43.247902 #51420] DEBUG -- : TRANSACTION (0.7ms) COMMIT
D, [2024-06-06T00:44:43.248577 #51420] DEBUG -- : TRANSACTION (0.4ms) BEGIN
D, [2024-06-06T00:44:43.249080 #51420] DEBUG -- : User Create (0.9ms) INSERT INTO "users" ("name", "team_id") VALUES ($1, $2) RETURNING "id" [["name", "B"], ["team_id", 1]]
D, [2024-06-06T00:44:43.250079 #51420] DEBUG -- : TRANSACTION (0.9ms) COMMIT
D, [2024-06-06T00:44:43.250910 #51420] DEBUG -- : TRANSACTION (0.6ms) BEGIN
D, [2024-06-06T00:44:43.251557 #51420] DEBUG -- : User Create (1.3ms) INSERT INTO "users" ("name", "team_id") VALUES ($1, $2) RETURNING "id" [["name", "C"], ["team_id", 1]]
D, [2024-06-06T00:44:43.252366 #51420] DEBUG -- : TRANSACTION (0.7ms) COMMIT
"========================"
D, [2024-06-06T00:44:43.257612 #51420] DEBUG -- : Team Load (0.6ms) SELECT "teams".* FROM "teams" WHERE "teams"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
"just call team users somewhere"
D, [2024-06-06T00:44:43.265162 #51420] DEBUG -- : User Load (0.5ms) SELECT "users".* FROM "users" WHERE "users"."team_id" = $1 [["team_id", 1]]
#<ActiveRecord::Associations::CollectionProxy [#<User id: 1, name: "A", team_id: 1>, #<User id: 2, name: "B", team_id: 1>, #<User id: 3, name: "C", team_id: 1>]>
"========================"
D, [2024-06-06T00:51:33.203851 #52175] DEBUG -- : Team Load (1.0ms) SELECT "teams".* FROM "teams" WHERE "teams"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
"without call team users works fine"
D, [2024-06-06T00:51:33.205138 #52175] DEBUG -- : TRANSACTION (0.7ms) BEGIN
D, [2024-06-06T00:51:33.205848 #52175] DEBUG -- : User Create (1.4ms) INSERT INTO "users" ("name", "team_id") VALUES ($1, $2) RETURNING "id" [["name", "D"], ["team_id", 1]]
D, [2024-06-06T00:51:33.207215 #52175] DEBUG -- : TRANSACTION (1.2ms) COMMIT
"========================"
D, [2024-06-06T00:44:43.269206 #51420] DEBUG -- : Team Load (0.5ms) SELECT "teams".* FROM "teams" WHERE "teams"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
D, [2024-06-06T00:44:43.270050 #51420] DEBUG -- : User Load (0.4ms) SELECT "users".* FROM "users" WHERE "users"."team_id" = $1 [["team_id", 1]]
"with force load also works fine"
D, [2024-06-06T00:44:43.271183 #51420] DEBUG -- : TRANSACTION (0.4ms) BEGIN
D, [2024-06-06T00:44:43.271787 #51420] DEBUG -- : User Create (1.0ms) INSERT INTO "users" ("name", "team_id") VALUES ($1, $2) RETURNING "id" [["name", "D"], ["team_id", 1]]
D, [2024-06-06T00:44:43.272553 #51420] DEBUG -- : TRANSACTION (0.7ms) COMMIT
how it works with includes, ofc because we preload users before build
team = Team.includes(:users).find(team.id)
team.users.build(name: 'D')
p 'just call team users somewhere', team.users
team.save!
D, [2024-06-06T00:48:27.639756 #51807] DEBUG -- : Team Load (0.5ms) SELECT "teams".* FROM "teams" WHERE "teams"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
D, [2024-06-06T00:48:27.645837 #51807] DEBUG -- : User Load (0.5ms) SELECT "users".* FROM "users" WHERE "users"."team_id" = $1 [["team_id", 1]]
"just call team users somewhere"
#<ActiveRecord::Associations::CollectionProxy [#<User id: 1, name: "A", team_id: 1>, #<User id: 2, name: "B", team_id: 1>, #<User id: 3, name: "C", team_id: 1>, #<User id: nil, name: "D", team_id: 1>]>
D, [2024-06-06T00:48:27.649317 #51807] DEBUG -- : TRANSACTION (1.0ms) BEGIN
D, [2024-06-06T00:48:27.650261 #51807] DEBUG -- : User Create (2.0ms) INSERT INTO "users" ("name", "team_id") VALUES ($1, $2) RETURNING "id" [["name", "D"], ["team_id", 1]]
D, [2024-06-06T00:48:27.651341 #51807] DEBUG -- : TRANSACTION (0.9ms) COMMIT
The text was updated successfully, but these errors were encountered:
I guess no one noticed that before, because usually reading and writing are separated, and when we write the data we probably don't need lazy loading at all. I guess it could be good to put it to gotchas section.
Please help me understand this is expected behavior or a bug? And if it’s expected, is it possible to somehow make it more predictable?
Gems
Preload schema and seeds, we have 2 tables and
has_many
associationThe issue is
In the first example, user
D
will not be created because if we call association afterbuild
we replace object to new one from database, is this expected behavior? I didn't find this in the description, many thanks!logs
how it works with
includes
, ofc because we preload users before buildThe text was updated successfully, but these errors were encountered: