多态 :has_many, :through 作为 Rails 3.1 插件中的模块

发布于 2024-12-15 16:26:50 字数 3319 浏览 2 评论 0原文

我到处寻找指向此的指针,但找不到。基本上,我想做其他人在以 :has_many、:through 方式创建多态关系时想做的事情……但我想在模块中完成。我一直陷入困境,认为我一定忽略了一些简单的事情。

也就是说:

module ActsPermissive
  module PermissiveUser
    def self.included(base)
      base.extend ClassMethods
    end
    module ClassMethods
      def acts_permissive
        has_many  :ownables
        has_many  :owned_circles, :through => :ownables
      end
    end
  end

  class PermissiveCircle < ActiveRecord::Base
    belongs_to    :ownable, :polymorphic => true
  end
end

对于如下所示的迁移:

create_table :permissive_circles do |t|
  t.string :ownable_type
  t.integer :ownable_id
  t.timestamps
end

当然,其想法是无论加载acts_permissive 都将能够拥有它拥有的圈子列表。

对于简单的测试,我

it "should have a list of circles" do
  user = Factory :user
  user.owned_circles.should be_an_instance_of Array
end

失败了:

Failure/Error: @user.circles.should be_an_instance_of Array
     NameError: uninitialized constant User::Ownable

我尝试过:使用 :class_name => has_many :ownables 行上的 'ActsPermissive::PermissiveCircle' 失败并显示:

Failure/Error: @user.circles.should be_an_instance_of Array
     ActiveRecord::HasManyThroughSourceAssociationNotFoundError:
      Could not find the source association(s) :owned_circle or 
      :owned_circles in model ActsPermissive::PermissiveCircle. 
      Try 'has_many :owned_circles, :through => :ownables, 
      :source => <name>'. Is it one of :ownable?

遵循建议并设置 :source =>; :ownable 失败,

Failure/Error: @user.circles.should be_an_instance_of Array
     ActiveRecord::HasManyThroughAssociationPolymorphicSourceError:
       Cannot have a has_many :through association 'User#owned_circles' 
       on the polymorphic object 'Ownable#ownable'

这似乎表明使用非多态通过进行操作是必要的。因此,我添加了一个类似于此处设置的circle_owner类

module ActsPermissive
  class CircleOwner < ActiveRecord::Base
    belongs_to :permissive_circle
    belongs_to :ownable, :polymorphic => true
  end

  module PermissiveUser
    def self.included(base)
      base.extend ClassMethods
    end
    module ClassMethods
      def acts_permissive
        has_many  :circle_owners, :as => :ownable
        has_many  :circles, :through => :circle_owners, 
                  :source => :ownable, 
                  :class_name => 'ActsPermissive::PermissiveCircle'
      end
    end

  class PermissiveCircle < ActiveRecord::Base
    has_many :circle_owners
  end
end

:迁移:

create_table :permissive_circles do |t|
  t.string :name
  t.string :guid

  t.timestamps
end

create_table :circle_owner do |t|
  t.string  :ownable_type
  t.string  :ownable_id
  t.integer :permissive_circle_id
end

仍然失败:

Failure/Error: @user.circles.should be_an_instance_of Array
     NameError:
       uninitialized constant User::CircleOwner

这让我们回到了开始。

  1. 如何在模块上执行看似相当常见的多态 :has_many, :through 操作?
  2. 或者,是否有一种好方法可以允许对象被某个对象中的任意对象收集?与模块类似的方式?

I've search everywhere for a pointer to this, but can't find one. Basically, I want to do what everyone else wants to do when they create a polymorphic relationship in a :has_many, :through way… but I want to do it in a module. I keep getting stuck and think I must be overlooking something simple.

To wit:

module ActsPermissive
  module PermissiveUser
    def self.included(base)
      base.extend ClassMethods
    end
    module ClassMethods
      def acts_permissive
        has_many  :ownables
        has_many  :owned_circles, :through => :ownables
      end
    end
  end

  class PermissiveCircle < ActiveRecord::Base
    belongs_to    :ownable, :polymorphic => true
  end
end

With a migration that looks like this:

create_table :permissive_circles do |t|
  t.string :ownable_type
  t.integer :ownable_id
  t.timestamps
end

The idea, of course, is that whatever loads acts_permissive will be able to have a list of circles that it owns.

For simple tests, I have

it "should have a list of circles" do
  user = Factory :user
  user.owned_circles.should be_an_instance_of Array
end

which fails with:

Failure/Error: @user.circles.should be_an_instance_of Array
     NameError: uninitialized constant User::Ownable

I've tried: using :class_name => 'ActsPermissive::PermissiveCircle' on the has_many :ownables line, which fails with:

Failure/Error: @user.circles.should be_an_instance_of Array
     ActiveRecord::HasManyThroughSourceAssociationNotFoundError:
      Could not find the source association(s) :owned_circle or 
      :owned_circles in model ActsPermissive::PermissiveCircle. 
      Try 'has_many :owned_circles, :through => :ownables, 
      :source => <name>'. Is it one of :ownable?

while following the suggestion and setting :source => :ownable fails with

Failure/Error: @user.circles.should be_an_instance_of Array
     ActiveRecord::HasManyThroughAssociationPolymorphicSourceError:
       Cannot have a has_many :through association 'User#owned_circles' 
       on the polymorphic object 'Ownable#ownable'

Which seems to suggest that doing things with a non-polymorphic-through is necessary. So I added a circle_owner class similar to the setup here:

module ActsPermissive
  class CircleOwner < ActiveRecord::Base
    belongs_to :permissive_circle
    belongs_to :ownable, :polymorphic => true
  end

  module PermissiveUser
    def self.included(base)
      base.extend ClassMethods
    end
    module ClassMethods
      def acts_permissive
        has_many  :circle_owners, :as => :ownable
        has_many  :circles, :through => :circle_owners, 
                  :source => :ownable, 
                  :class_name => 'ActsPermissive::PermissiveCircle'
      end
    end

  class PermissiveCircle < ActiveRecord::Base
    has_many :circle_owners
  end
end

With a migration:

create_table :permissive_circles do |t|
  t.string :name
  t.string :guid

  t.timestamps
end

create_table :circle_owner do |t|
  t.string  :ownable_type
  t.string  :ownable_id
  t.integer :permissive_circle_id
end

which still fails with:

Failure/Error: @user.circles.should be_an_instance_of Array
     NameError:
       uninitialized constant User::CircleOwner

Which brings us back to the beginning.

  1. How can I do what seems to be a rather common polymorphic :has_many, :through on a module?
  2. Alternatively, is there a good way to allow an object to be collected by arbitrary objects in a similar way that will work with a module?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

谁人与我共长歌 2024-12-22 16:26:51

事实证明,将 :class_name 添加到两个 :has_many 定义中实际上是有效的(有人对此发表了评论,但他们删除了评论)。它在我的非简化程序中不起作用,因为我的程序中的其他内容导致了级联错误,该错误似乎是 :has_many 定义的本地错误。

短篇故事:对于一些实际上不是问题的事情来说却带来了很多麻烦。布莱赫

It turns out that adding :class_name to both :has_many definitions will actually work (someone commented on that, but they deleted their comment). It didn't work in my non-simplified program because of something else in my program that was causing a cascading error that SEEMED to be local to the :has_many definition.

Short story: It was a lot of trouble for something that wasn't actually a problem. Blech

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文