我在将以下句子翻译到Rails范围时遇到了一些问题:
SELECT COUNT(*) FROM permission_activities pa
JOIN activities a ON pa.activity_id = a.id
WHERE a.method = :method AND :url ~ a.url_regex AND pa.permission_id IN(:permission_ids)
我带了一些类似的东西:
class PermissionActivity < ApplicationRecord
belongs_to :permission
belongs_to :activity
scope :allowed_access, lambda { |permissions, url, method|
includes(:activity).where(
'activity.method = :method AND :url LIKE activity.url_regex
AND permission_activity.permission_id IN :permissions',
method: method, url: url, permissions: permissions
)
}
end
但我得到了这个错误:
ActiveRecord::StatementInvalid (PG::SyntaxError: ERROR: syntax error at or near "1")
LINE 2: AND permission_activity.permission_id IN 1,2,3) LIMIT ...
为什么permissions
没有显示为数组?我是不是错过了一些显而易见的东西?还是我的方法从概念上就注定了?
有用信息:
class Permission < ApplicationRecord
has_many :permission_activities, dependent: :destroy
has_many :activities, through: :permission_activities
end
class Activity < ApplicationRecord
has_many :permission_activities, dependent: :destroy
has_many :permissions, through: :permission_activities
end
class PermissionActivity < ApplicationRecord
belongs_to :permission
belongs_to :activity
end
大部分查询不需要使用字符串:
class PermissionActivity < ApplicationRecord
belongs_to :permission
belongs_to :activity
def self.allowed_access(permissions, url, method)
includes(:activity)
.where("? ~ activities.url_regex", url)
.where(
activities: {
method: method
},
permission_activities: {
permission_id: permissions
}
})
end
end
当您将调用链接到where
时,它将把条件与AND
连接起来,当您传递条件哈希时也是如此。
不要为多行方法使用scope——这只是创建类方法时被过度使用的语法糖。该文档是极其错误的——除了singleton_class.define_method ...
之外,它绝对是蹲着的,如果你设法砸到了什么东西,它就会上升。按照惯例,它用于声明查询数据库的方法。它会使代码更难阅读,并对静态分析隐藏该方法。
如果您确实创建了多行lambda,请使用do ... end
,而不是像块那样使用大括号。
这里有几个问题:
~
(在原始查询中(可以使用正则表达式,而LIKE
则不能- SQL中的表名应该是复数,而不是像您那样的单数
- 您正在询问的
IN
问题
修复第一个很容易:用~
替换LIKE
。固定第二个也很容易:使用复数。修复第三个也是非常直接的:IN
想要一个列表,所以在命名的占位符周围添加一些括号。
应用这些给你:
scope :allowed_access, lambda { |permissions, url, method|
includes(:activity).where(
'activities.method = :method AND :url ~ activities.url_regex
AND permission_activities.permission_id IN (:permissions)',
method: method, url: url, permissions: permissions
)
}