Reputation: 324
I'm not sure if this is a problem within my app or my understanding of virtual attributes. Creating a Member
object with a first_name
and last_name
virtual attribute works. However, when I go to retrieve the Member
, the first and last name are nil. I say that it works because the User.invite!
method it invokes successfully creates and saves a new User
with the first and last name. My understanding is from this article below, but I wanted to get some insight whether I was missing or misunderstanding anything.
The Virtual Attribute is a class attribute, which has no representation in the database. It becomes available after object initialization and remains alive while the object itself is available (like the instance methods)
Member
class Member < ApplicationRecord
belongs_to :store
belongs_to :user
attribute :email, :string
attribute :first_name, :string
attribute :last_name, :string
before_validation :set_user_id, if: :email?
private
def set_user_id
self.user = User.invite!({
first_name: first_name,
last_name: last_name,
email: email
})
end
end
Console
Loading development environment (Rails 6.0.0)
irb(main):001:0> Member.last
Member Load (0.5ms) SELECT "members".* FROM "members" ORDER BY "members"."id" DESC LIMIT $1 [["LIMIT", 1]]
=> #<Member id: 55, store_id: 43, user_id: 3, created_at: "2019-09-03 02:05:27", updated_at: "2019-09-03 02:05:27", email: nil, first_name: nil, last_name: nil>
Upvotes: 1
Views: 650
Reputation: 1168
I might go with this:
class Member < ApplicationRecord
belongs_to :store
belongs_to :user
end
class User < ApplicationRecord
has_many :members
has_many :stores, through: :members
def self.invite_to_store(first_name, last_name, email, store_id)
ActiveRecord::Base.transaction do
user = invite!(first_name: first_name, last_name: last_name, email: email)
user.members.create!(store_id: store_id)
end
end
end
Then you can call User.invite_to_store('first name', 'last name', '[email protected]', 1)
Upvotes: 0
Reputation: 181
Actually, I didn't understand why you would like to use the attribute
in this example. I believe that you want/should use delegate.
Basically, It seems to work when you invoke invite!
because you probably are passing these attributes in parameters, so it initialize the object and set this "temporary variables". But, when you try to SELECT
the register from database it's not there anymore.
As you flagged, remains alive while the object itself is available
. Check that it says the object. When you do Member.last
it initializes a new object with the data returned from database.
Upvotes: 1