Reputation: 357
I have a concept of a Share which represents a specific stock owned by a particular shareholder. What I am trying to add now is functionality that supports tracking the "history" of this Share over time, given it can be transferred to other shareholders etc.
In my database, for each Share
record there is currently a column t.string "transaction_ids"
. I should probably change the column type I am assuming to something easier to work with. Open to suggestions here.
The two relevant methods are when creating new shares and then transferring ownership of the shares.
Here is how the Share is created initially.
@number_of_share_numbers_to_create.times do |i|
Share.create(
owner_id: params[:buying_shareholder_id],
captable_id: @transaction.captable.id,
company_id: @transaction.company.id,
share_number: @latest_share += 1,
transaction_ids: @transaction.id #Save transaction id to DB
)
end
Then when a Share
is transferred, I have the following method.
@share_numbers_on_cap.each do |share|
share.update_attribute(:owner_id, @buying_shareholder.id)
# TODO Capture share history by pushing @transaction.id into the transaction_ids column.
# Perhaps I could do something like share.transaction_ids >> @transaction.id or something?
end
I know this current solution is not optimal, and I'd love some guidance on how to solve this in a more scalable way. Perhaps I should use a different column type and build an array? Would love some push in the right direction.
Thanks!
Upvotes: 3
Views: 1293
Reputation: 54882
I suggest creating another model to "log" the transactions that happened for a specific Share
object.
For example:
class ShareTransfer < ApplicationRecord
belongs_to :share
belongs_to :transaction
# don't forget to enforce the presence of
# both foreign keys share_id and transaction_id
# bonus: "freezing" the object after creation so you can never
# update the logged object (= data integrity)
before_save(on: :update) do
errors.add(:base, :immutable, "Cannot update a frozen object")
end
end
And change your current Share#transaction_ids
to a simple integer
column with a foreign key to the transactions
table - an probably rename it as well - to end up with something like:
class Share < ApplicationRecord
belongs_to :transaction # implies you have renamed the column transaction_ids to transaction_id (and changed the column type)
has_many :share_transfers
end
Which enables you to do the following when a Share
is transferred:
@share_numbers_on_cap.each do |share|
# [your previous logic to change ownership]
share.share_transfers.create!(transaction_id: share.transaction_id)
# ^ to create history of the ownership change
end
This schema allows you to add extra fields to the ShareTransfer
model, for example, the exact time when the transfer occurred (ex: occurred_at
), the IP of both parties when the transfer was validated, etc. You can even lock
the ShareTransfer
table to be "insert only", preventing any user (or code) to update the data in there and ensuring the integrity of your logs.
Upvotes: 2
Reputation: 23317
You can use an array column type (if you use postgres). But what I'd do is to move transaction ids to a separate DB table. It will let you easily add new ids and query them fast.
Upvotes: 2