Well, I’ll post right here what was the solution I found and meets all my needs.
First I created Gem delegate_associations and added to my project.
The next step was to adjust my migrations:
class CreatePeople < ActiveRecord::Migration
def change
create_table :people do |t|
t.string :name
t.string :cpf_cnpj
t.timestamps
end
end
end
class CreateUsers < ActiveRecord::Migration
def change
create_table :users, id: false do |t|
t.primary_key :person_id
t.string :login
t.string :password
t.timestamps
end
end
end
class CreateSellers < ActiveRecord::Migration
def change
create_table :sellers, id: false do |t|
t.primary_key :person_id
t.decimal :comission, default: 0.0
t.timestamps
end
end
end
Notice that I removed the column id
of User
and Seller
and added as primary key to column person_id
. I did this so that when I associate for example a Seller
for a sale, I will always have the id of the Person
which is the same as Seller
.
After that I created 2 Modules:
# app/models/concerns/person_helper.rb
module PersonHelper
extend ActiveSupport::Concern
included do
validates :name, presence: true
end
end
# app/models/concerns/is_a_person.rb
module IsAPerson
extend ActiveSupport::Concern
included do
include PersonHelper
belongs_to :person, autosave: true
delegate_associations to: :person
delegate_attributes to: :person
def self.find_by_id(value)
find_by_person_id(value)
end
def person
super || build_person
end
end
end
My models were as follows:
# app/models/person.rb
class Person < ActiveRecord::Base
include PersonHelper
has_one :user
accepts_nested_attributes_for :user
has_one :seller
accepts_nested_attributes_for :seller
end
# app/models/user.rb
class User < ActiveRecord::Base
include IsAPerson
validates :login, :password, presence: true
end
# app/models/seller.rb
class Seller < ActiveRecord::Base
include IsAPerson
end
Now all the validations and methods that a person has I will not put directly into the model of Person
and yes in the module PersonHelper
so that my User
and my Seller
may also have the same things.
With this I can have for example these possibilities:
> user = User.new(name: 'Nome da pessoa', login: 'admin', password: '123456')
> user.save # true
> user.person.persisted? # true
> user.seller #nil
> user.build_seller # Irá instanciar um Seller e associar com a Person
> user.seller.comission # 0.0
> user.name = 'Joe'
> user.person.name # Joe
Notice it’s like the User
had the attribute name
, and every time I get a new name for the user
he automatically arrow in person
. This happens by the use of the Gem I made where I use the artifices of delegate.
Perhaps this is not the most appropriate option, but it has met all my needs and works perfectly.
this way that you posted will also work, even I was doing it that way. I posted what was the solution I found to meet my need. Thank you for responding.
– Bmucelini