【问题标题】:Ruby on rails modelling relationshipsRuby on Rails 建模关系
【发布时间】:2017-03-23 09:04:27
【问题描述】:

我正在创建一个基本的订阅应用程序,并且想知道对以下关系建模的最简洁的方法是什么。我似乎对has_and_belongs_to_many 关系以及何时使用它们感到困惑。

我正在尝试大致创建下面的结构,有几点需要注意。 subscriptionorder 都只能有一个plan,但subscriptionsorders 可以有很多products

计划也以与产品相同的方式创建。即可以创建 6 个计划,然后可以将其添加到任意数量的订阅中(类似于产品)。

关系设计

目前我有以下:

# User Model
has_one :subscription
has_one :plan, through: :subscription

# Subscription Model
belongs_to :user
belongs_to :plan # Not sure this is correct as a subscription should only be allowed to have 1 plan which belongs to the subscription. 

# Plan Model
has_many :subscriptions # Again this doesn't feel quite right as I think the plan should belong to the subscription.

# Product Model
has_and_belongs_to_many :orders
has_and_belongs_to_many :subscriptions

# Order Model
belongs_to :user
has_and_belongs_to_many :products

任何人都可以就最佳建模方法提供任何建议,我们将不胜感激。

【问题讨论】:

  • 当您编写表定义时,通常很清楚您需要什么关系。例如,如果您将user_id 添加到subscriptions,那么subscription belongs_to user
  • 如果您无法将 foreign_id 添加到任何一个表中,则它是 has_and_belongs_to_many

标签: ruby-on-rails ruby activerecord model relationships


【解决方案1】:

在我看来 has_many :通过关联更合适。

http://guides.rubyonrails.org/association_basics.html#the-has-many-through-association

# User model
has_one :subscription
has_one :plan, through: :subscription

# Subscription model
belongs_to :user
belongs_to :plan
has_many :orders

# Plan (Subscription Plan) model
has_many :subscriptions
has_many :users, through: :subscriptions

# Order model
belongs_to :subscription

您能详细说明OrderProduct 型号吗?你想让他们代表什么?如果Order 用于表示订阅中的每个事务,则它应该属于Subscription

【讨论】:

  • 感谢您的回复。如您所述,订单应通过订阅代表每笔交易。还值得一提的是,每个客户只能有 1 个订阅 :)。再次感谢您的建议
  • @TomPinchen 好的,我相应地更新了我的答案。希望这会有所帮助:)
【解决方案2】:

如果你只需要处理@plans,我认为答案很简单——你可以让@subscriptions@orders属于@plans,每个都可以定义为have_many

# User model
has_one :subscription
has_many :orders

# Plan model
has_many :subscriptions
has_many :orders

# Subscription model
belongs_to :user
belongs_to :plan

# Order model
belongs_to :user
belongs_to :plan

(我很欣赏你关于它“感觉”就像一个计划应该属于订阅而不是相反的观点,但你必须在这里稍微“使用武力,卢克”。)

我认为折叠@products 的方法可能是使用连接表:

 # Order join table - OrderProduct
 belongs_to :order
 belongs_to :product

 # Subscription join table - SubscriptionProduct
 belongs_to :subscription
 belongs_to :product

然后,我认为,其余的模型看起来像:

# User model
has_one :subscription
has_many :orders    

# Plan model
has_many :subscriptions
has_many :orders

# Subscription model
belongs_to :user
belongs_to :plan
has_many :subscription_products
has_many :products, :through => :subscription_products

# Order model
belongs_to :user
belongs_to :plan
has_many :order_products
has_many :products, :through => :order_products

# Product model
has_many :subscription_products
has_many :subscriptions, :through => :subscription_products
has_many :order_products
has_many :orders, :through => :order_products

创建一个新的@order 可能类似于:

 @order = Order.create(user: @user, plan: @plan)
 @order.products = @products
 @order.save

一个新的@subscription 将是类似的。

如果您想要订阅给定@product 的所有@users 的列表,您可以:

@users = @product.subscriptions.map{|x| x.user}

如果您想查看当前订阅的所有@products

@products = @user.subscription.products

如果您想查看所有曾经订购过产品的@users

@users = @product.orders.map{|x| x.user}.uniq

.uniq 以防用户多次订购同一产品)

【讨论】:

    【解决方案3】:

    has_belongs_to_many 指定与另一个类的多对多关系,即我们可以直接在那些父类中指定,而不是为连接表创建单独的类

    class A < ActiveRecord::Base
      has_many :abs
      .....
    end
    
    class B < ActiveRecord::Base
      has_many :abs
      ....
    end
    
    class AB < ActiveRecord::Base
      belongs_to :a
      belongs_to :b
      ....
    end
    

    除此之外,我们可以直接在类A和B中指定

    class A < ActiveRecord::Base
      has_belongs_to_many :as
      ....
    end
    
    class B < ActiveRecord::Base
      has_belongs_to_many :bs
      ....
    end
    

    希望现在已经清楚 has_belongs_to_many 关联。

    现在对于模型设计,我们必须保留 Order 类,该类专门指向通过订阅订购产品的用户
    即,orders 表将充当连接表,与用户、产品、订阅相关联。

    orders 是一个指向 Order Rails 模型的表

    Rails 协会如下

    class User < ActiveRecord::Base
      has_many :subscriptions
      has_many :orders
      has_many plans, through: :subscription
      ....
    end
    
    class Plan < ActiveRecord::Base
      has_many :subscriptions
      has_many :users, through: :subscriptions
      ....
    end
    
    class Subscription < ActiveRecord::Base
      belongs_to :user
      belongs_to :plan
      has_many :orders
      ....
    end
    
    class Order < ActiveRecord::Base
      belongs_to :user
      belongs_to :product
      belongs_to :subscription
      ....
    end
    
    class Product < ActiveRecord::Base
      has_many :orders
      has_many :users, through: :orders
      ....
    end
    

    希望这对你有用:)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-05
      • 2011-10-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多