Home > Blockchain >  Rails joins wrong tables in shards
Rails joins wrong tables in shards

Time:11-01

I'm having an following database structure, with the schema cloned to 2 databases:

users (id, name)
todos (id, title)
todos_users (user_id, todo_id)

I'm having 2 different clients in my software, Big company and Small company. The shards represent the companies' own todos, and don't wanna get separated. All users, including Small company users are stored in the Big company database. This is because we don't have separated logins, and some users can use both Big and Small company todo-lists.

We're having a following problem though, with these models:

# ApplicationRecord connects to the current shard the user is logged to
# GlobalRecord always uses the Big company -database

class User < GlobalRecord
end

class Todo < ApplicationRecord
  has_and_belongs_to_many :users
end

Resulting queries for example DatabaseProxy.on_shard(shard: :small_company) do Todo.first.users end

SELECT "todos".* FROM "todos" ORDER BY "todos"."id" ASC LIMIT $1  [["LIMIT", 1]]
SELECT "users".* FROM "users" INNER JOIN "todos_users" ON "users"."id" = "todos_users"."user_id" WHERE "todos_users"."todo_id" = $1

Here is the problem; it joins the todos_users to users in the primary shard! This is problematic, as the todos don't lay in the Big company database but rather in the Small one. Therefore all the information I insert into the Small company database todos_users gets lost when selecting the todos.

I'm using Rails 6.1, but also upgrading to 7 can be possible.

CodePudding user response:

Solved by upgrading to Rails 7 (disable_joins was introduced in 7) and changing has_and_belongs_to_many to:

# todos_user.rb
class TodosUser < ApplicationRecord
  belongs_to :user
  belongs_to :todo
end
# todo.rb
class Todo
  has_many :todos_users
  has_many :users, through: :todos_users, disable_joins: true
end
  • Related