0

I am building a simple expenses management app on rails 5.1.4. I am using the following five models.

Payees

class Payee < ApplicationRecord
  has_many :expenses
  validates :title, uniqueness: true, presence: true
end

Accounts

class Account < ApplicationRecord
 before_save :update_balance
 validates :balance, numericality: { greater_than_or_equal_to: 0 }
 has_many :expenses
end

Budgets

class Budget < ApplicationRecord
 belongs_to :categories
 has_many :expenses, through: :categories
end

Categories

class Category < ApplicationRecord
  validates :title, uniqueness: true, presence: true
  has_many :expenses
  has_one :budget
end

Expenses

class Expense < ApplicationRecord
  belongs_to :categories
  belongs_to :budgets
  belongs_to :payees
  belongs_to :accounts
  validates :title, :value, presence: true
  before_save :default_account
end

When I try to create a new expense I am facing a validation error

Validation failed: Categories must exist, Budgets must exist, Payees must exist, Accounts must exist

The issue is that all the above records exist. To explain my self let's say I am passing the params account_id: 1, payee_id: 1, category_id: 1. If I do:

Account.find(1) #=> Finds the record
Category.find(1) #=> also ok
Payee.find(1) #=> also ok

I am aware of the solution referred in this question (adding optional: true) but I don't get why I should do that while all of the above exist

Edit

The code that is raising the error is:

def create
  @expense = Expense.create!(title: params[:expense]['title'],
                           value: params[:expense]['value'],
                           date: params[:expense]['date'],
                           comment: params[:expense]['comment'],
                           payee_id: params[:expense]['payee_id'],
                           category_id: params[:expense]['category_id'],
                           account_id: params[:expense]['account_id'])
end

The parameters that are passed through the form are

{"utf8"=>"✓", "authenticity_token"=>"DWd1HEcBC3DhUahfOQcdaY0/oE+VHapxxE+HPUb0I6iSiqMxkz6l+vlK+1zhb66HnZ/vZRUVG4ojTdWUCjHtGg==", "expense"=>{"title"=>"test", "value"=>"-20", "category_id"=>"1", "payee_id"=>"2", "date"=>"2018-01-21", "account_id"=>"1", "comment"=>""}, "commit"=>"Submit"}

dstrants
  • 7,423
  • 2
  • 19
  • 27
  • I totally forgot to mention that I am on rails **5.1.4** – dstrants Jan 19 '18 at 19:41
  • 1
    Perhaps you should show the code (by editing your question) that is raising the error along with the stack trace. – jvillian Jan 19 '18 at 19:45
  • I have just updated my question! Thanks for mentioning that @jvillian – dstrants Jan 19 '18 at 19:55
  • And the stack trace? – jvillian Jan 19 '18 at 20:03
  • `ActiveRecord::RecordInvalid in ExpensesController#create` at the `@expense` line of the controller ( `app/controllers/expenses_controller.rb:14:in 'create' ` ) – dstrants Jan 19 '18 at 20:07
  • That's not the stack trace. It should start with something like `Started GET "/" for ::1 at 2018-01-19 12:09:25 -0800` and show parameters, error trace, etc. And, please add to your question instead of putting in comments. – jvillian Jan 19 '18 at 20:10
  • Are you sure the params are received correctly in the controller? You should post the stack trace showing the parameters in the post action. – Pablo Jan 20 '18 at 14:01
  • @Pablo the parameters are received correctly in the controller for sure as the form used to work perfectly before I added the relations to the models. – dstrants Jan 21 '18 at 08:12

2 Answers2

0

I would first start by commenting out all your model validations, then creating an expense. Add back one model validation at a time, each time test creating an expense to see what validation is causing the error.

also you may want to change how you're creating the expense to something like below.

change your controllers create action to

def create
  @expense = Expense.new(expense_params)   
  if @expense.save
    flash[:success] = "expense created"
    redirect_to expense_url(@expense.id)
  else
    render 'new'
  end
end

next under your private method at the bottom of your controller you want to do something like this

private
    # Never trust parameters from the scary internet, only allow the white list through.
    def expense_params
      params.require(:expense).permit(:title, :value, :date, etc...)
    end
random_user_0891
  • 1,863
  • 3
  • 15
  • 39
  • thanks for your response but the model validations and the controller were working fine before I added the model relations. The error I am facing is weird because it says that the category I am trying to relate to my `Expense.new` does not exist although it does. The problem occurs on the database and I can't see why – dstrants Jan 21 '18 at 08:16
0

I finally found out where the problem is! It was the naming of the classes/models that raised the error. I had named my models on singular (Account, Category, etc) while all references are searching for plurals ( Accounts, Categories, etc). I had to re-do all migrations from the very beginning in order to make it work the proper way!

Thanks to everyone for spending the time though!

dstrants
  • 7,423
  • 2
  • 19
  • 27