验证数组 Active Record 中的包含时出错
Error while validating inclussion in array Active Record
我在将以下句子翻译到 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
这里有几个问题:
~
(在原始查询中)适用于正则表达式,LIKE
不适用。
- SQL 中的 table 名字应该是复数,而不是像你这样的单数。
- 您询问的
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
)
}
大多数查询不需要使用字符串:
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
连接条件,当您传递条件散列时同样适用。
不要对多行方法使用作用域 - 它只是一种被过度使用的用于创建 class 方法的语法糖。该文档非常具有误导性 - 它绝对会下蹲,除了 singleton_class.define_method ...
并在你设法破坏某些东西时加注。按照惯例,它用于声明查询数据库的方法。它使您的代码更难阅读并隐藏静态分析的方法。
如果您确实像创建块一样创建多行 lambda use do ... end
instead of braces。
我在将以下句子翻译到 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
这里有几个问题:
~
(在原始查询中)适用于正则表达式,LIKE
不适用。- SQL 中的 table 名字应该是复数,而不是像你这样的单数。
- 您询问的
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
)
}
大多数查询不需要使用字符串:
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
连接条件,当您传递条件散列时同样适用。
不要对多行方法使用作用域 - 它只是一种被过度使用的用于创建 class 方法的语法糖。该文档非常具有误导性 - 它绝对会下蹲,除了 singleton_class.define_method ...
并在你设法破坏某些东西时加注。按照惯例,它用于声明查询数据库的方法。它使您的代码更难阅读并隐藏静态分析的方法。
如果您确实像创建块一样创建多行 lambda use do ... end
instead of braces。