【发布时间】:2015-08-04 19:58:51
【问题描述】:
User 和Organization 通过Relationship 具有many-to-many 关联。 Relationship 模型包括几个关于关系的布尔变量,例如 moderator (true/false) 和 member (true/false)。另外,我添加了一个名为 default 的布尔值,用于设置默认组织。
我需要验证如果(且仅当)用户是一个或多个组织 (member == true) 的成员,这些组织中的一个(并且恰好是 1 个)具有拥有default == true。
所以基本上这意味着如果用户是多个组织的成员,则这些组织中的一个必须是默认组织,如果用户是多个组织的成员,则必须存在这样的默认组织。
如何编写此验证?我当前的验证在播种时会产生以下错误:
PG::SyntaxError: ERROR: syntax error at or near "default"
LINE 1: ...ERE (user_id = 1) AND (member = 't' and default = ...
^
: SELECT COUNT(*) FROM "relationships" WHERE (user_id = 1) AND (member = 't' and default = 't')
我在Relationship 模型中的实现:
validate :default
private
def default
@relationships = Relationship.where('user_id = ?', self.user_id)
@members = @relationships.where('member = ?', true)
@defaults = @members.where('default = ?', true)
# If more than 1 organization has been set as default for user
if @defaults.count > 1
@defaults.drop(0).each do |invalid|
invalid.update_columns(default: false)
end
end
# If user is member but has no default organization yet
if !@defaults.any? && @members.any?
@members.first.update_columns(default: true)
end
end
更新从外观上看,我知道我不应该以这种方式建模,而应该使用@DavidAldridge 在他的回答中建议的has_onebelongs_to 关系。但我不明白如何为这种关系建模(请参阅我在答案下方的评论)。非常感谢任何建议。
【问题讨论】:
-
这并不是验证的真正用途。您可以考虑改用回调
-
你的模型是什么样的?你到底定义了什么关系?
-
我已将
validate :default更改为before_save :default以将其转换为回调,但它在播种时产生了相同的错误。我会将模型关系添加到帖子中。 -
对于您遇到的错误,那是因为
default是 Postgres 关键字。见stackoverflow.com/questions/31809764/… -
好的,谢谢!将其更改为回调并更改名称解决了它。您将其添加为答案,然后我会接受吗?我有时确实会听到有关回调的坏消息(例如,参见 samuelmullen.com/2013/05/the-problem-with-rails-callbacks)。我的用例有更好的选择吗?另外,我找不到信息是否使用
before_save创建新记录时也会触发回调?还是我需要添加bothbefore_save :newname和before_create :default?因为在Relationship中所做的每个更改都应该触发验证。
标签: ruby-on-rails ruby validation ruby-on-rails-4 associations