Reputation: 3568
In RoR, whenever you create a nested resource, is there to set attributes during creation of a resource with a parent association, within the model?
I have this Role model that may belong_to and have_many other roles.
employee = Role.find_by_slug :employee
employee.role
=> nil
employee.roles
=> [...more roles...]
waitress = employee.roles.create(slug: :waitress)
=> #<Role id...
waitress.role
=> #<Role slug: 'employee'...
waitress.roles
=> []
The role model has a boolean attribute of subtype. Whenever I create a role from an existing role, I'd like for subtype to be set to true.
employee.subtype
=> false
And waitress would look like this:
waitress.subtype
=> true
Upvotes: 1
Views: 76
Reputation: 76774
Whenever I create a role from an existing role, I'd like for subtype to be set to true.
#app/models/Role.rb
class Role < ActiveRecord::Base
belongs_to :role
has_many :roles
validate :role_exists, if: "role_id.present?"
before_create :set_subtype, if: "role_id.present?"
private
def set_subtype
self.subtype = true
end
def role_exists
errors.add(:role_id, "Invalid") unless Role.exists? role_id
end
end
The above will require another db request; it's only for create & it will happen when the model is invoked (IE you can call it whatever you like when you need it).
--
An alternative to this would be to use acts_as_tree
or a similar hierarchy gem.
AAT adds a parent_id
column in your db, to which it will then append a series of instance methods you can call (parent
, child
, etc).
This would permit you to get rid of the has_many :roles
, and replace it with a children
instance method:
#app/models/role.rb
class Role < ActiveRecord::Base
acts_as_tree order: "slug"
#no need to have "subtype" column or has_many :roles etc
end
root = Role.create slug: "employee"
child1 = root.children.create slug: "waitress"
subchild1 = child1.children.create slug: "VIP_only"
root.parent # => nil
child1.parent # => root
root.children # => [child1]
root.children.first.children.first # => subchild1
Upvotes: 1
Reputation: 3568
The following changes did the trick for me:
from:
has_many :roles
to:
has_many :roles do
def create(*args, &block)
args[0][:subtype] = true
super(*args, &block)
end
end
Upvotes: 0
Reputation: 5977
According to your description, a given Role
is considered a subtype if it has no parent role. In this case, simply add the following method to Role
:
def subtype?
!self.role.nil?
end
Upvotes: 0