我的Rails应用程序中的用户和角色之间存在标准的多对多关系:
class User < ActiveRecord::Base
has_many :user_roles
has_many :roles, :through => :user_roles
end
Run Code Online (Sandbox Code Playgroud)
我想确保只为用户分配一次角色.任何插入重复项的尝试都应该忽略该请求,而不是抛出错误或导致验证失败.我真正想要表示的是"集合",其中插入已存在于集合中的元素无效.{1,2,3} U {1} = {1,2,3},而非{1,1,2,3}.
我意识到我可以这样做:
user.roles << role unless user.roles.include?(role)
Run Code Online (Sandbox Code Playgroud)
或者通过创建一个包装器方法(例如add_to_roles(role)),但我希望通过关联使其自动化的一些惯用方法,以便我可以写:
user.roles << role # automatically checks roles.include?
Run Code Online (Sandbox Code Playgroud)
它只是为我做的工作.这样,我不必记得检查重复或使用自定义方法.我缺少框架中的某些东西吗?我首先想到:has_many的uniq选项可以做到,但它基本上只是"选择不同的".
有没有办法以声明方式做到这一点?如果没有,可能使用关联扩展名?
以下是默认行为失败的示例:
>> u = User.create
User Create (0.6ms) INSERT INTO "users" ("name") VALUES(NULL)
=> #<User id: 3, name: nil>
>> u.roles << Role.first
Role Load (0.5ms) SELECT * FROM "roles" LIMIT 1
UserRole Create (0.5ms) INSERT INTO "user_roles" ("role_id", "user_id") VALUES(1, 3)
Role Load … 我需要在运行时从Perl符号表中删除一个方法.我尝试使用undef &Square::area,这会删除函数,但会留下一些痕迹.具体来说,当$square->area()被调用时,Perl抱怨它是"不是CODE引用"而不是"Undefined subroutine&Square :: area called"这是我所期望的.
你可能会问,"为什么这很重要?你删除了这个功能,你为什么要打电话呢?" 答案是,我不是在呼唤它,Perl是.广场由矩形继承,我想继承链传递$square->area通过到&Rectangle::area,但而不是跳过广场,在那里该方法不存在,再通过下降到矩形的面积()方法调用与死"不是CODE参考."
奇怪的是,这似乎只发生在&Square :: area由typeglob赋值(例如*area = sub {...})定义时.如果使用标准sub area {}方法定义函数,则代码按预期工作.
同样有趣的是,取消定义整个glob可以按预期工作.只是不要取消定义子程序本身.
这是一个简短的例子,说明了症状,并与正确的行为形成对比:
#!/usr/bin/env perl
use strict;
use warnings;
# This generates "Not a CODE reference". Why?
sub howdy; *howdy = sub { "Howdy!\n" };
undef &howdy;
eval { howdy };
print $@;
# Undefined subroutine &main::hi called (as expected)
sub hi { "Hi!\n" }
undef &hi;
eval { hi };
print $@; …Run Code Online (Sandbox Code Playgroud)