小编Kin*_*ong的帖子

Rails习惯用来避免has_many中的重复:through

我的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 …

activerecord idioms ruby-on-rails associations

36
推荐指数
2
解决办法
1万
查看次数

为什么这个Perl产生"不是CODE参考?"

我需要在运行时从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)

perl symbol-tables subroutine typeglob

5
推荐指数
1
解决办法
5811
查看次数