我的网站有User
和Group
个模型,一切都很好。用户和组模型是我们拥有的两种类型的帐户,它们目前用于联系信息,身份验证和授权。
现在,我正在构建网站的订阅部分,以便我们开始为订阅我们的高级服务的用户(和团体/组织)收费。我选择将这个新代码放在Rails引擎中,因为我希望只将引擎部署到可以通过我们的VPN访问的主机上的环境,如下所示:
mount Billing::Engine, :at => '/billing' if Rails.env.admin?
我有三个与我合作管理订阅的模型:
module Billing
class PricingPlan < ActiveRecord::Base
has_many :subscriptions
end
end
module Billing
class Subscription < ActiveRecord::Base
belongs_to :pricing_plan
belongs_to :subscriber, :polymorphic => true
# Used for eager loading
belongs_to :users, :foreign_key => 'subscriber_id', :class_name => '::User'
belongs_to :groups, :foreign_key => 'subscriber_id', :class_name => '::Group'
has_many :payments
end
end
module Billing
class Payments < ActiveRecord::Base
belongs_to :subscription
end
end
Billing::Subscription.subscriber
部分是目前令我烦恼的部分。正如您所看到的,我目前正在跨越引擎边界以获取生活在我的应用程序中的::User
和::Group
模型,但这感觉很糟糕。
我考虑过创建Billing::User
和Billing::Group
AR模型,以便引擎和应用程序可以完全隔离,但是在两个模型之间复制信息似乎有点奇怪现在,在同一个数据库中(例如first_name,last_name,email等)......加上我必须在它们之间复制信息,这是一个灾难的秘诀,我确定。
我还想过使用某种包装模型来抽象出实际的实现,如下所示:
module Billing
class User < ::User
end
end
但是如果我没记错的话,我遇到了关于rspec模拟和存根后的多态行为和/或问题的问题,所以我放弃了这种方法。
我很感激任何指导。我已经多次前往谷歌寻找答案,但到目前为止,我所看到的一切似乎都没有直接适用。
更新
根据Carl Zulauf的建议,我提出了以下建议:
# File: app/models/concerns/billing/subscribable.rb
require 'active_support/concern'
module Billing
module Subscribable
extend ActiveSupport::Concern
included do
has_one :subscription, {
:class_name => '::Billing::Subscription',
:foreign_key => 'subscriber_id',
:as => :subscriber
}
base = self
Billing::Subscription.class_eval do
belongs_to base.name.tableize.to_sym, {
:foreign_key => 'subscriber_id',
:class_name => base.to_s
}
end
end
end
end
然后我就这样调用:
class User < ActiveRecord::Base
include Billing::Subscribable
can_subscribe
end
这样做......只要我在之前加载User
我就会调用Billing::Subscription.eager_load :users
......这看起来真的很冒险。对我有什么建议吗?
更新#2
我最终创建了一个初始化程序来处理这个问题。这是有效的,但如果有更好的选择,我会全力以赴。
# File: config/initializers/setup_billing.rb
User.class_eval do
include Billing::Subscribable
end
Group.class_eval do
include Billing::Subscribable
end
答案 0 :(得分:0)
一种方法是在引擎中添加一个模块,将一个类宏添加到User
和Group
。
class User < ActiveRecord::Base
include Billing::ModelHelper
has_subscription # new macro
end
然后 has_subscription
:
User
)has_many
/ has_one
/ belongs_to
关联添加到User
Billing::Subscription
(belongs_to :user, ...
)