Torrm Torrm - 2 months ago 7
Ruby Question

Rails Model Associations when nesting - Confusion

Perhaps I am approaching this all wrong, I have the following models setup:

The

User
model has many
Questions
, a
Question
belongs_to a
User


This means I can easily do:
u = User.last.questions
and see all of the questions associated with the user last added.

Following this, I have a
Payment
model that belongs_to a
Question
. A
Question
has_one
payment
meaning I can easily do
u = User.last.questions.last.payment
, getting the payment details from the question last added by the last added user (daft example perhaps!).

Now the bit that is confusing me

I have a model called
PaymentOption
which is used to populate a drop down list, for different prices, the
PaymentOption
belongs_to a
Payment
and a
Payment
has_one
PaymentOption


This is all working correctly, but the only way for me to find out the details of the payment option, such as the amount, would be to do something like this:

payment_amount = PaymentOption.find(User.last.questions.last.payment.payment_option_id).amount


Ideally I would do something like this:
amount = User.last.questions.last.payment.payment_option.amount


By doing it in the way I have, it is as good as doing two seperate queries, one to get the payment option ID and another to find a detail relating to that particular payment option. Surely there is a better way to approach this?

Thanks in advance

EDIT 1

To clarify my answer, I have included the schema for Payments and PaymentOptions

create_table "payment_options", force: :cascade do |t|
t.integer "amount"
t.text "description"
t.string "title"
t.boolean "user_accessible", default: true
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end

create_table "payments", force: :cascade do |t|
t.string "email"
t.string "token"
t.integer "question_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "payment_option_id"
end

add_index "payments", ["payment_option_id"], name: "index_payments_on_payment_option_id"
add_index "payments", ["question_id"], name: "index_payments_on_question_id"

Answer

I think here is you problem:

I have a model called PaymentOption which is used to populate a drop down list, for different prices, the PaymentOption belongs_to a Payment and a Payment has_one PaymentOption

You said you've setup Payment has_one PaymentOption and PaymentOption belongs_to Payment. But in the schema described in the end Payment has a payment_option_id.

In this case, Payment belongs_to PaymenteOption and not the opposite. See this example in the Rails Guide. Account has supplier_id so Supplier has one Account and Account belongs_to Supplier.

Your models should be like this:

class Payment < ActiveRecord::Base

  belongs_to :payment_option

end

class PaymentOption < ActiveRecord::Base
  has_one :payment # Or even has_many :payments
end