I have created an active record enum field: role. Added it to the model and the table. But it doesn't generate the helpers?
Membership model
enum role: [:employee, :admin, :owner]
after_initialize :set_default_membership_role, :if => :new_record?
def set_default_membership_role
self.role ||= :employee
end
pry output
=> [#<Membership id: 1, company_id: 1, user_id: 1, created_at: "2014-11-25 16:06:03", updated_at: "2014-11-25 16:06:03", role: 0>]
[3] pry(main)> #membership.role
from /Users/gtheys/.rbenv/versions/2.1.2/gemsets/worke_rs/gems/activerecord-4.1.5/lib/active_record/relation/delegation.rb:136:in `method_missing'
Is it because because Membership is a join model for user and companies?
model/User.rb
has_many :companies, :through => :memberships, dependent: :destroy
model/Companies.rb
has_many :users, :through => :memberships
Or is there another problem why the enum helpers are not created?
Are you sure you are calling .role on the actual membership model?
In your example (pry output) it looks like #membership is an active_record/relation.
Try #membership.first.role
Related
I currently have a User model
class User < ApplicationRecord
has_one :leases
end
a Lease model
class Lease < ApplicationRecord
belongs_to :tenant, class_name: 'User'
belongs_to :landlord, class_name: 'User'
end
and a Rental model
class Rental < ApplicationRecord
has_one :lease, dependent: :destroy
end
and I only have one user model supporting tenants and landlords.
The problem I'm facing is that a landlord can have multiple leases with many different tenants, but tenants can only have one lease at a time.
I'm somewhat confused on how I should structure this properly. Should I have a has_many relation with the User model and the Lease model instead of the has_one and then just a method say lease on the User model to get the lease for a tenant?
What I would like to have is something like
tenant.lease
and
landlord.leases
Could I just do?
class User < ApplicationRecord
has_one :lease, foreign_key: "tenant_id"
has_many :leases, foreign_key: "landlord_id"
end
this seems to work, but I'm not sure if its the right way to go.
Using STI, you could have the following models
==> user.rb <==
class User < ApplicationRecord
end
==> landlord.rb <==
class Landlord < User
has_many :leases
end
==> tenant.rb <==
class Tenant < User
has_one :lease
end
==> lease.rb <==
class Lease < ApplicationRecord
belongs_to :tenant
belongs_to :landlord
end
Then you can do things like
irb(main):003:0> landlord = Landlord.create(name: 'the landlord')
=> #<Landlord id: 5, name: "the landlord", type: "Landlord", created_at: "2022-01-03 22:16:56", updated_at: "2022-01-03 22:16:56">
irb(main):004:0> tenant = Tenant.create(name: 'the tenant')
=> #<Tenant id: 6, name: "the tenant", type: "Tenant", created_at: "2022-01-03 22:17:09", updated_at: "2022-01-03 22:17:09">
irb(main):005:0> lease = Lease.create(tenant: tenant, landlord: landlord)
=> #<Lease id: 3, tenant_id: 6, landlord_id: 5, created_at: "2022-01-03 22:17:28", updated_at: "2022-01-03 22:17:28">
irb(main):006:0> tenant.lease
=> #<Lease id: 3, tenant_id: 6, landlord_id: 5, created_at: "2022-01-03 22:17:28", updated_at: "2022-01-03 22:17:28">
irb(main):007:0> landlord.leases
=> #<ActiveRecord::Associations::CollectionProxy [#<Lease id: 3, tenant_id: 6, landlord_id: 5, created_at: "2022-01-03 22:17:28", updated_at: "2022-01-03 22:17:28">]>
To accomplish this, you only need to add a type column to your User model and Rails will take care of the rest.
In my opinion, you should go with has_many approach. As landlord and tenant both are users. in place of using tenant_id and landlord_id, you have to use 'user_id' and to identify user, use user_type i.e. tenant and lanlord.
Just an opinion !!
A Manager has many contacts via polymorphic association
class Manager
has_many :contacts, as: :contactable
end
class Contact
belongs_to :contactable, polymorphic: true
end
The relation works fine but now a contact can be associated to many managers.
So, added a new model Contactable, a joins table 'contactables' and moved contactable_id and contactable_type fields from contacts table to contactables table.
class Contactable
belongs_to :contact
belongs_to :contactable, polymorphic: true
end
Now confused about the Manager and Contact relation that how it would be defined in models correctly to make it working. Tried the following but it doesn't work:
class Manager
has_many :contacts, through: :contactables, source: :contactable, source_type: "Contact"
end
So I checked this interesting topic and will tell what I know.
When you create objects as usual in has_many :through:
class Contact
has_many :contactables
has_many :managers, :through => :contactables
end
class Manager
has_many :contactables
has_many :contacts, :through => :contactables
end
class Client
has_many :contactables
has_many :contacts, :through => :contactables
end
class Contactable
belongs_to :contact
belongs_to :manager
belongs_to :client
end
You get to use foreign keys fro each referenced object. Polymorphic looks like a great solution. So:
class Contactable
belongs_to :contact
belongs_to :polymorphic_model, polymorphic: true
end
class Contact
has_many :contactables
has_many :managers, :through => :contactables, :source => :polymorphic_model, :source_type => 'Manager'
end
class Manager
has_many :contactables, :as => :polymorphic_model
has_many :contacts, :through => :contactables
end
Setting the :as option indicates that this is a polymorphic
association
:source => :polymorphic_model is used to tell Rails to get the related object from the subclass. :source means the same as :class_name. Without this option Rails would try to get associated Manager from the Contactables table, while it should be reached via virtual Polymorphic_model.
By adding belongs_to :polymorphic_model to Contactable you enable Contact (witch already sits there, because of belongs_to :contact) to be associated with a Manager or Client, because thats what Polymorphic association does - references two or more parent tables. And because Contact have_many Contactables, the same Contact object can be associated with many managers or clients. So after you understand it, it looks really simple - Joined model belongs to Contact and Joined model also holds references to Manager and Client through Polymorphic association. So in order for Contact to have many managers, you create another Contactable object that belongs to the same Contact, but different Manager. Doesn't look super efficient, but personally me, not knowing a better way..
Here is a tested proof:
Manager.create!(name: "Bravo")
=> #<Manager id: 1, created_at: "2017-04-12 12:17:41", updated_at: "2017-04-12 12:17:41", name: "Bravo">
Manager.create!(name: "Johnny")
=> #<Manager id: 2, created_at: "2017-04-12 12:18:24", updated_at: "2017-04-12 12:18:24", name: "Johnny">
Contact.create!(number:"123")
=> #<Contact id: 1, created_at: "2017-04-12 12:18:59", updated_at: "2017-04-12 12:18:59", number: 123>
c = Contactable.new
c.contact = Contact.first
c.unit = Manager.first
c
=> #<Contactable id: nil, unit_type: "Manager", created_at: nil, updated_at: nil, unit_id: 1, contact_id: 1>
Now to set another Manager to the same contact, we create a new Contactable:
cc = Contactable.new
cc.contact = Contact.first
cc.unit = Manager.last
cc
=> #<Contactable id: nil, unit_type: "Manager", created_at: nil, updated_at: nil, unit_id: 4, contact_id: 1>
And to get all associated:
Contact.first.managers
Contactable's database:
contact_id
unit_id
unit_type
And one interesting quote by #Bill Karwin:
The Polymorphic Associations design breaks rules of relational
database design. I don't recommend using it.
But he wrote this long time ago. Probably irrelevant now.
Why can you not have a foreign key in a polymorphic association?
I have the following model relationship:
class Role < ActiveRecord::Base
has_many :permissions_roles, inverse_of: :role, dependent: :destroy
has_many :permissions, through: :permissions_roles
accepts_nested_attributes_for :permissions_roles, allow_destroy: true
end
class PermissionsRole < ActiveRecord::Base
belongs_to :permission
belongs_to :role
end
Permission class has id, name etc.
I am using Rails 4.2.4 and facing an error with update method of the role model. When I update the nested attribute permissions_roles, it doesn't update the has_many :through permissions attribute of the model. This is what I did to verify the error in rails console:
> role = Role.create(name: 'role', permissions_roles_attributes: [{permission_id: 1}])
# Checking permissions for the role
> role.permissions
[#<Permission:0x007ff3c3963160
id: 1,
name: "read">]
# Updating the nested attributes
> role.update(permissions_roles_attributes: [{permission_id: 10}])
# Checking nested attributed - Return as expected
> role.permissions_roles
=> [#<PermissionsRole:0x007ff3bbade740 id: 78, permission_id: 1, role_id: 11>, #<PermissionsRole:0x007ff3bc8fdee8 id: 79, permission_id: 10, role_id: 11>]
# Checking has_many through relationship. Stale :(
> role.permissions
=> [#<Permission:0x007ff3be1d29f0
id: 1,
name: "read">]
I have to manually call reload on the model or role.permissions attribute to make sure role.permissions is updated. Is there any way for permissions attribute to automatically update whenever I update permissions_roles ?
You have forgot to specify the id of the PermissionRole model, which you want to update:
role.update(permissions_roles_attributes: [{ id: 78, permission_id: 10}])
I have a very odd mass assignment error that shows up when I use association methods to create new objects.
I have a user model that looks like this:
class User < ActiveRecord::Base
has_many :posts, :dependent => :destroy
end
I also have a posts model that looks like this:
class Post < ActiveRecord::Base
belongs_to :user
attr_accessible :body, :title
end
If I do the following in console, I get a mass assignment warning:
> user = User.create(:name => "Daniel");
> user.posts.create(:title => "Hello World")
=> #<Post id: 1, body: nil, title: "Hello World", created_at: "2011-11-03
18:24:06", updated_at "2011-11-03 18:24:06", user_id = 1>
> user.posts
=> WARNING: Can't mass-assign attributes: created_at, updated_at, user_id
When I run user.posts again, however, I get:
> user.posts
=> [#<Post id: 1, body: nil, title: "Hello World", created_at: "2011-11-03
18:24:06", updated_at "2011-11-03 18:24:06", user_id = 1>]
There are a couple of other tricks I can do to avoid the mass assignment error, such as calling user.posts before I do users.posts.create.
Why is this happening and how can I prevent it?
I'm using Rails 3.0.7.
How about changing your user model to include attr_accessible for posts association
class User < ActiveRecord::Base
has_many :posts, :dependent => :destroy
attr_accessible :posts
end
I am trying to update a nested has_one model using mongoid but it will not persist the has_one association
im running Rails 3.07 & Mongoid 2.2
widget model
class Widget
include Mongoid::Document
embeds_many :permissions, :default => []
end
permission model
class Permission
include Mongoid::Document
field :admin, :type => Boolean, :default => false
has_one :user
embedded_in :widget
end
user model
class User
include Mongoid::Document
belongs_to :permission
end
Heres the results im getting from rails console;
#widget.permissions << Permission.new(:user => current_user)
=> [#<Permission _id: 4e5aced1c155df4b33000001, _type: nil, admin: false>]
#widget.save
=> true
#widget.permissions.first.user
=> #<User _id: 4e5ac71ec155df470f000001, _type: nil, email: "ada ..... >
Appears as if the user is saved, however it is not persisted to mongo.
The permission is being saved but has no user.
Any ideas?
Should you be using "embedded_in" rather than "belongs_to" in the User model?