简体   繁体   中英

How to reach a table's column from an id in another table rails

I have 2 tables in my project: Transactions and Accounts Every transactions "belong_to" an account. And one account can have many transactions. I modified the models file accordingly.

    ActiveRecord::Schema.define(version: 2021_09_26_204408) do

  create_table "accounts", force: :cascade do |t|
    t.string "title"
    t.float "balance"
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false
  end

  create_table "transactions", force: :cascade do |t|
    t.string "title"
    t.float "value"
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false
    t.string "notes"
    t.integer "account_id"
    t.index ["account_id"], name: "index_transactions_on_account_id"
  end

  add_foreign_key "transactions", "accounts"
end

This is my Accounts controller

        class AccountsController
  def index
    @accounts = Account.all
  end

  def show
    @transaction = Transaction.find(params[:id])
    @account = Account.find_by(id: @transaction.account_id)
  end
end

I am trying to show the Title of the account for every transaction shown on my index. And I'd like to able to sum the values of every transactions with that id to get a balance.

I am able to get the transaction.account_id but I can't reach further into the table.

I tried this in my index.html.erb

<% @accounts.each do |account| %>
    <%= account.title %>
<% end %> 

But I get the @accounts is not defined or Nill.

Routes.rb

Rails.application.routes.draw do
  root "transactions#index"

  resources :transactions
  resources :accounts
end

Thank you for your help

first of all seems you have not all transactions have account_id present.

To fix it I suggest to add validator and not null declaration for transaction table like this

  create_table "transactions", force: :cascade do |t|
    ...
    t.integer "account_id",  null: false
    ... 
  end

that will protect you from having transaction without account on database level.

Next problem what I see is that you are fetching accounts via index action, but transaction via show action.

Assuming you have models like

class Account < ApplicationRecord
  has_many :transactions
end

class Transaction < ApplicationRecord
  belongs_to :account
end

Than your accounts controller might looks like

class AccountsController
  def index
    @accounts = Account.all
  end

  def show
    @account = Account.find(params[:id])
  end
end

Than you can render accounts via template in cycle, like you did.

Regarding question about sum of transactions per account, I'll just give you direction to understand how it works (try use rails console to check next snippet)

@accounts =  Account.joins(:transactions).select("accounts.* ,sum(transactions.value) as transactions_sum ").group("transactions.account_id")

@accounts.each do |account|
   puts account.title
   puts account.transactions_sum.to_s
end

similar question has_many with sum active record

And last typo - use decimals in database for storing amounts, not floats

Good luck!

I don't see the relationships setup in your models file. That is why you can't access the related object.

models/account.rb should have:

has_many:transactions (might want to include dependent: :destroy)

models/transaction.rb should have:

belongs_to:account

To me, I would think you would rather be using the transactions index for this. For example:

class TransactionsController < ApplicationController
  def index
    @transactions = Transaction.all
  end
end

Then your view would look like this:

<%= @transactions.each do |transaction| %>
  <%= transaction.account.title %>
<% end %>

The way you have it setup right, you would have to do an inner loop just to get the accounts transactions.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM