I have created few models which are shown below.
Base models are TransactionType and TransactionItem
ExpenseType and IncomeType derives from TransactionType.
Expense and Income derives from TransactionItem.
class TransactionType < ActiveRecord::Base
scope :expense_types, -> { where(tran_type: ‘ExpenseType’) }
scope :income_types, -> { where(tran_type: ‘IncomeType’) }
self.inheritance_column = “tran_type”
validates :name, uniqueness: true
end
class ExpenseType < TransactionType
end
class IncomeType < TransactionType
end
class TransactionItem < ActiveRecord::Base
validates :note, length: { in: 2…255 }
end
class Expense < TransactionItem
belongs_to :expense_type
validates :expense_type, presence: true
end
class Income < TransactionItem
belongs_to :income_type
validates :income_type, presence: true
end
I can create objects for ExpenseType.
But, it throws error when Expense or Income object created.
ExpenseType.new(:name => "Grocceries").save!
ExpenseType.new(:name => "Travel").save!
IncomeType.new(:name => "Salary").save!
IncomeType.new(:name => "Bonus").save!
Expense.new(:note => "a soda", :expense_type => ExpenseType.first)
2.1.2 :006 > Expense.new(:note => “a soda”, :expense_type =>
ExpenseType.first)
ExpenseType Load (0.1ms) SELECT “transaction_types”.* FROM
“transaction_types” WHERE “transaction_types”.“tran_type” IN
(‘ExpenseType’) ORDER BY “transaction_types”.“id” ASC LIMIT 1
ActiveModel::MissingAttributeError: can’t write unknown attribute
`expense_type_id’
from
It would be great if someone shares your idea for solving this.
Thanks,
Masc
On Friday, 11 July 2014 13:36:32 UTC-5, Ruby-Forum.com User wrote:
validates :name, uniqueness: true
end
2.1.2 :006 > Expense.new(:note => “a soda”, :expense_type =>
ExpenseType.first)
ExpenseType Load (0.1ms) SELECT “transaction_types”.* FROM
“transaction_types” WHERE “transaction_types”.“tran_type” IN
(‘ExpenseType’) ORDER BY “transaction_types”.“id” ASC LIMIT 1
ActiveModel::MissingAttributeError: can’t write unknown attribute
`expense_type_id’
I don’t think this is an inheritance problem. What does the schema for
your
transaction_items table look like? The error message suggests that it
doesn’t have a column expense_type_id
, which is what belongs_to :expense_type
is going to be looking for.
A wild guess: maybe you’ve got a transaction_type_id
column instead?
In
that case, you should use this on Expense
:
belongs_to :expense_type, foreign_key: :transaction_type_id
(and similar for :income_type
on Income
)
–Matt J.
Hi Matt,
Schema looks like this.
sqlite> .schema transaction_items
CREATE TABLE “transaction_items” (“id” INTEGER PRIMARY KEY AUTOINCREMENT
NOT NULL, “transaction_type_id” integer, “note” varchar(255),
“transaction_date” datetime, “created_at” datetime, “updated_at”
datetime);
sqlite> .schema transaction_types
CREATE TABLE “transaction_types” (“id” INTEGER PRIMARY KEY AUTOINCREMENT
NOT NULL, “name” varchar(255), “tran_type” varchar(255), “created_at”
datetime, “updated_at” datetime);
There is no specific table for expense_type and income_type.
transaction_types table’s tran_type column decides whether it is a
income / expense type.
My idea is to write common code for IncomeType and ExpenseType in it’s
base class transaction_type which extends ActiveRecord::Base.
Thanks.
I have uploaded the source code of model and migration at below link.
Anyone can create simple rails application, copy model & migration files
on place.
Run rails console and execute below commands to reproduce error.
ExpenseType.new(:name => “Grocceries”).save!
ExpenseType.new(:name => “Travel”).save!
IncomeType.new(:name => “Salary”).save!
IncomeType.new(:name => “Bonus”).save!
Expense.new(:note => “a soda”, :expense_type => ExpenseType.first)
Hi Matt,
Thanks for your input. Actually I made it working without using STI. Not
sure this is the right way of doing it. But, this is what I wanted.
class TransactionItem < ActiveRecord::Base
validates :note, length: { in: 2…255 }
validates :transaction_date, presence: true
end
class Expense < TransactionItem
belongs_to :expense_type, :class_name => “TransactionType”,
:foreign_key => “transaction_type_id”
validates :expense_type, presence: true
end
class Income < TransactionItem
belongs_to :income_type, :class_name => “TransactionType”,
:foreign_key => “transaction_type_id”
validates :income_type, presence: true
end
Let me know your thoughts.
Thanks.
On Monday, 14 July 2014 16:30:03 UTC-4, Ruby-Forum.com User wrote:
base class transaction_type which extends ActiveRecord::Base.
Couple things:
-
the code you posted has a single transaction_items table, but two
classes
(Income and Expense) that both descend from ActiveRecord::Base. That
definitely won’t work. If you really want a common transaction_items
table,
you’ll need to include a column to put the STI type in and a base class
of
TransactionItem rather than a module.
-
as noted previously, if you have a column on transaction_items called
transaction_type_id
but want to refer to the corresponding association
as
expense_type
or income_type
, you’ll need to pass the foreign_key
option to belongs_to
.
–Matt J.
On Thursday, 17 July 2014 12:59:30 UTC-4, Ruby-Forum.com User wrote:
end
Not sure what you mean by “without using STI”. Do you have a type
column
on the transaction_items table?
–Matt J.