ruby-on-rails - 有没有办法为 Activerecord 中的单个查询创建临时列?
问题描述
假设我们有一个带有以下迁移的 ChessPiece 类。
create_table :chess_pieces do |t|
t.string :type
t.integer :row
t.integer :column
t.integer :game_id, index: true
end
如果一个主教想要从 (0,0) 移动到 (7,7),那么我需要检查两个位置之间的每个空间是否有其他可能阻碍我的主教的棋子。IE 如果 (5,5) 上有一个 Pawn。
我可以在数据库中查询每个可能有这样一个阻塞块的位置:
pieces = []
8.times do |i|
pieces << ChessPiece.where(game_id: @game_id, row: i, column: i)
end
但我想减少查询。或者,我可以获取一个游戏的所有棋子并在 Ruby 中迭代它们,但这似乎也效率低下。我想做的是告诉数据库将row
和column
列组合成“行列”的形式并调用它position
。这样我就可以运行如下查询:
ChessPiece.where(game_id: @game_id, position: ["1-1", "2-2", "3-3"])
如何动态创建这个新列,以便可以运行类似上述查询的内容?(假设我不能只编辑数据库模式。)
解决方案
您可以使用.select
创建任何您想要的选择语句:
@chess_pieces = ChessPiece.select(
"chess_pieces.*",
"CONCAT(chess_pieces.row, '-', chess_pieces.column) AS position"
)
当您使用别名时,结果中的列将作为模型的属性提供:
@chess_pieces.first.position
您还可以在某些(PG、MySQL)但不是所有 dbs 上的 WHERE、ORDER 和 GROUP 子句中使用列别名:
ChessPiece.select(
"chess_pieces.*",
"CONCAT(chess_pieces.row, '-', chess_pieces.column) AS position"
).where('position = ?', '1-1')
.group('position')
.order('position ASC')
对于那些不支持它的人,您需要在现场进行连接、聚合或任何您正在执行的操作。
ChessPiece.order("CONCAT(chess_pieces.row, '-', chess_pieces.column)")
推荐阅读
- typescript - 区分 TypeScript 对象类型和类类型的方法
- python - 仅更新值的动态字典创建
- spring-webflow - 在流中访问多个请求参数
- python - 可以同时显示四种不同类型数据的可视化
- javafx - 对 VBox 可见部分的 JavaFX 侦听器
- tslint - 如何强制 nrwl nx 尊重标签更新?
- reactjs - React:全局状态属性的异步更改
- ios - 如何“预选” UIActivityViewController 图标?
- events - Cakephp 3.x Table Beforefind,无法停止事件
- javascript - 如何将值插入嵌套数组