Отношения между моделями правильные, но контроллер не может найти никаких записей?

#ruby-on-rails #view #routes #controller

Вопрос:

У меня есть Payment , Client и PaymentTransactions модель. Я пытаюсь показать все PaymentTransactions для данного Client , но контроллер возвращает пустой массив.

Маршрут, которым я пользуюсь, чтобы добраться туда, таков /api/v1/clients/:id/payment_transactions

Это мой файл маршрутов:

 Rails.application.routes.draw do
  namespace :api, defaults: { format: :json } do
    namespace :v1 do
      resources :payments, only: [ :index ]
      resources :clients, only: [ :index ]

      resources :clients, only: [:show] do
        resources :payment_transactions, only: [:index]
      end
    end
  end
end
 

Рельсовые пути:

 Uri Pattern /api/v1/clients/:client_id/payment_transactions
Controller#Action api/v1/payment_transactions#index {:format=>:json}
 

Это мои модели:

 class Payment < ApplicationRecord
  belongs_to :client, optional: true, dependent: :destroy
  has_many :payment_transactions, dependent: :destroy
end

class Client < ApplicationRecord
  has_one :payment, dependent: :destroy
  has_many :payment_transactions, through: :payment, dependent: :destroy
end

class PaymentTransaction < ApplicationRecord
  belongs_to :payment, optional: true
  has_one :client, through: :payment
end
 

А это мой контроллер:

 class Api::V1::PaymentTransactionsController < Api::V1::BaseController
  before_action :set_client

  def index
    @transactions = PaymentTransaction.where(client: @client)
  end

  private

  def set_client
    @client = Client.find(params[:client_id])
  end
end
 

Я могу сделать PaymentTransaction.client и получить Клиента, связанного с этой платежной операцией. Я также могу сделать все, Client.payment_transactions чтобы получить все транзакции для данного Клиента.

Однако, сделав звонок на /api/v1/clients/1/payment_transactions возврат [] .

Редактировать:

Изменение действия контроллера @transactions = PaymentTransaction.where(client_id: @client.id) , приведшее к

 ActionView::Template::Error (PG::UndefinedColumn: ERROR:  column payment_transactions.client_id does not exist
LINE 1: ...transactions".* FROM "payment_transactions" WHERE "payment_t...
                                                             ^
):
    1: json.array! @transactions do |transaction|
    2:   json.extract! transaction, :id, :payment_id, :transaction_identification, :amount, :status
    3: end
 

Комментарии:

1. Просто сделай @transactions = Payment transaction.where(client_id: @client.id) или @transactions = @client.payment_transactions

2. Спасибо! @Maxence. Последнее сработало. Первый из них привел к ошибке, которую я добавил в операцию.

3. Моя ошибка. Модель PaymentTransaction не имеет столбца client_id. Последнее должно сработать.

Ответ №1:

where Метод ActiveRecord ожидает, что его входные данные будут столбцами в вызываемой модели, поэтому вы не можете использовать его для фильтрации по промежуточным ассоциациям. Вместо этого вы можете вызвать определенное payment_transaction asosciation непосредственно из @client объекта.

   def index
    @transactions = @client.payment_transactions
  end
 

Примечание сбоку:
Использование ассоциации напрямую имеет дополнительное преимущество, позволяющее вам загружать записи позже, на случай, если вам когда-либо понадобится перечислить клиентов вместе с их платежными транзакциями. например

 Client.all.includes(:payment_transactions)
 

Использование a where не сделает это легко выполнимым.

Комментарии:

1. Спасибо! @Абдулазиз