Я хочу иметь возможность запрашивать игры пользователя, где его user_id находится в движении игр white_user_ids или black_user_ids. Я также хочу иметь возможность запрашивать пользователей игры, где ходы white_user_ids или black_user_ids соответствуют пользователям.
РЕДАКТИРОВАТЬ:
Прежде чем я начну объяснять свой вопрос более подробно, я придумал обходной путь:
class User < ActiveRecord::Base
def games
Game.where( [ "moves -> 'black_user_ids' @> '?' OR moves -> 'white_user_ids' @> '?'", self.id, self.id ] )
end
end
class Game < ActiveRecord::Base
serialize :moves, HashSerializer
store_accessor :moves, :white_user_ids, :black_user_ids
def users
User.find((self.white_user_ids + self.black_user_ids).uniq)
end
end
Есть ли что-то неправильное в создании пользовательских методов с именами, которые я хочу, вместо того, чтобы писать has_many ...
? Если это хак и плохой, то, пожалуйста, продолжайте читать и не стесняйтесь отвечать.
Первоначальный вопрос:
Вот самая основная версия схемы для этого вопроса:
User
id
Game
id
moves - jsonb
white_user_ids - integer array
black_user_ids - integer array
Я создал индекс выражения для обоих user_id:
execute <<-SQL
CREATE INDEX moves_white_user_ids_on_games ON games USING GIN ((moves->'white_user_ids'));
CREATE INDEX moves_black_user_ids_on_games ON games USING GIN ((moves->'black_user_ids'));
SQL
Я не знаю, как настроить отношения между пользователями и играми. Очевидно, существует какое-то отношение has_many или, может быть, даже отношение has_and_belongs_to_many. Но я сохраняю все данные, которые мне понадобятся для создания ассоциации, в таблице игр, перемещает столбец jsonb.
Примеры:
<User id: 1>
<User id: 5>
<User id: 6>
<User id: 11>
<User id: 17>
<User id: 20>
<User id: 23>
<User id: 35>
<User id: 76>
<User id: 89>
<User id: 93>
<Game id: 1, moves: {"black_user_ids"=>[88],
"white_user_ids"=>[23]}>
<Game id: 2, moves: {"black_user_ids"=>[6, 1, 11, 76, 17, 23],
"white_user_ids"=>[93, 89, 1, 35, 20, 5, 6]}>
<Game id: 3, moves: {"black_user_ids"=>[76, 68, 20, 96, 19, 3],
"white_user_ids"=>[82, 48, 29, 37, 20, 74]}>
<Game id: 4, moves: {"black_user_ids"=>[82],
"white_user_ids"=>[74, 16]}>
<Game id: 5, moves: {"black_user_ids"=>[22, 41, 25, 78, 50],
"white_user_ids"=>[24, 10, 99, 26, 1, 4]}>
Пользовательские ассоциации/области:
User.find(1).games
вернет игры [2, 5], любую уникальную игру, в которой либо black_user_ids, либо white_user_ids имеют свой user_id.
User.find(1).black_games
вернет игру [2], любую игру, в которой black_user_ids имеет свой user_id.
User.find(1).white_games
вернет игры [2, 5], любую игру, в которой white_user_ids имеет свой user_id.
Ассоциации/области игры:
Game.find(2).users
вернет пользователей [1, 5, 6, 11, 17, 20, 23, 35, 76, 89, 93], любого уникального пользователя в его black_user_ids или white_user_ids.
Game.find(3).black_users
вернет пользователей [3, 19, 20, 68, 76, 96], любого пользователя в его black_user_ids.
Game.find(4).white_users
вернет пользователей [16, 74], любого пользователя в его white_user_ids.