0

首先,一些背景。

我的应用模型是这样的:

  User has_many :subscriptions; has_many :courses, :through => :subscriptions
Subscription belongs_to :course, :user
  Course has_many :subscriptions; has_many :users, :through => :subscriptions

Subscription 是一个连接表,用于存储诸如状态(:active、:inactive、:failed、:passed、:unpaid)之类的信息,并用作连接课程所附带的所有信息(例如Grade模型(尚未添加),付款模型(正在进行中)等)。

我想添加支付模型来存储订阅的支付历史。每次付款可以用于一个或多个订阅。到目前为止,我已经尝试了一个Payment has_many :subscriptions,但我在控制器逻辑上遇到了问题,我想也许有更好的方法来关联“用户订阅课程的付款”的模型。

从技术上讲,在支付显示操作中,我需要来自这些模型中的每一个的信息(course.name、支付用户的 user_id、payment.amount,所有这些都连接到订阅)和 Payment.create 操作,我需要设置订阅状态(我可以做到)。

如果这是关联各种模型的合乎逻辑/有效的方式,我如何以最少的数据库调用在支付展示操作中访问所需的信息(来自每个模型课程、用户、支付和订阅的一些信息)?我正在使用Rails 3.2/Ruby 1.9并希望坚持使用 ActiveRecord/ARel 而不是直接的 sql 语句。我也愿意接受“你做错了”的答案。如果更改关联将使从控制器访问表的效率更高,我也对此持开放态度。

4

2 回答 2

1

做(中config/routes.rb

resources :users do
  resources :courses do
    resources :subscriptions
  end
end

这将允许你做@user.courses.subscriptions

例如,如果您想从coursesback 到users,您可以将路线修改为

resources :users, :shallow => true do
 #...
end

编辑:

对于付款,我会像你说的那样做has_many :subscriptions

当您显示付款时。你会做类似的事情

payment_history = Payment.find(params[:id])
@subscriptions = payment_history.subscriptions

现在您有了指向该付款历史的链接的订阅列表,例如

您将在视图中循环并显示每个订阅

<% @subscriptions.each do |subscription|%>
  <%= subscription.payment.id %>
  <%= subscription.users.size %>
  <%= subscription.courses.size %>
  <%= subscription.paying_user.name  %> <!-- or whereever it exists-->
<% end%>

您需要确保您有一个路由并在更改路由后重新启动服务器

resources :payments, :shallow => true do
   resources :subscriptions
end
于 2012-10-18T19:15:39.587 回答
1

@D3mon-1stVFW 的回答让我走上了解决这个问题的正确轨道。

对于付款显示操作,查询将类似于:

@payment = Payment.find_by_id(params[:id])
@subscriptions = @payment.subscriptions.includes(:course, :user)

这将使访问与订阅相关的课程和用户数据成为可能,如下所示:

<% @subscriptions.each do |subscription|%>
  <%= subscription.payment.amount %>
  <%= subscription.user.email %>
  <%= subscription.course.name %>
  <%= subscription.state  %>
<% end%>

对于还没有 a 的支付 new/create 操作payment.id,查询略有不同:

@unpaid_subs = Subscription.where(:user_id => current_user.id).unpaid.includes(:course)
@payment = Payment.new

current_user将要付款的用户在哪里(创建新的付款),并且.unpaid是模型上的一个范围Subscription,如下所示:

scope :unpaid, -> { where('subscriptions.payment_id' => nil)}

在视图中,您可以使用与显示视图相同的方式访问数据:

<% @unpaid_subs.each do |sub| %>
  <%= sub.course.name %> | <%= sub.course.credits %><br />
<% end %>

我的主要困惑是我不知道您可以从孩子那里访问父母关联。订阅belongs_to 课程,但您仍然可以这样做subscription.course.something

于 2012-10-30T17:52:09.037 回答