What is 'as' in ruby on rails model? - ruby-on-rails

What is 'as' in ruby on rails model? and how does it work?
e.g.
has_many :something, as: :reasonable
Is it polymorphic?

Yes, this is a polymorphic association which allows a model to belong to multiple models. There should be
class Something < ApplicationRecord
belongs_to :reasonable, polymorphic: true
end
And then any model can have many of these as reasonable without adding another column to Something.
class Thing < ApplicationRecord
has_many :somethings, as: :reasonable
end
class Stuff < ApplicationRecord
has_many :somethings, as: :reasonable
end
Something stores both the class and ID of what its associated with allowing it to be polymorphic.

Related

Why is an association model for a many-to-many relationship only halfway pluralized?

I have a model User and a model Group, between the two I want to create a many-to-many association with a join-table, using through.
user.rb:
class User < ActiveRecord::Base
has_many :groups_user
has_many :groups, :through => :groups_user
end
group.rb:
class Group < ActiveRecord::Base
has_many :groups_user
has_many :users, :through => :groups_user
end
groups_user.rb
class GroupsUser < ActiveRecord::Base
belongs_to :user
belongs_to :group
end
I initially tried to do the same thing naming the joining model class GroupsUsers in groups_users.rb but I got an uninitialized constant error unless I used :class_name to specify the class name.
My question is: What is the logic behind pluralizing the first name, but not the second? The association is many-to-many so both models are on equal footing. In this case group comes first merely because of the lexical order. So why pluralize one and not the other? This makes no sense to me.
The more conventional naming approach would be:
#user.rb:
class User < ActiveRecord::Base
has_many :group_users
has_many :groups, :through => :group_users
end
#group.rb:
class Group < ActiveRecord::Base
has_many :group_users
has_many :users, :through => :group_users
end
#group_user.rb
class GroupUser < ActiveRecord::Base
belongs_to :user
belongs_to :group
end
Conventionally, the model has the singular form. So GroupsUser, not GroupsUsers. But, an instance of the join model has only one Group and one User, So, GroupUser, not GroupsUser.
If you look at the The has_many :through Association section of the Active Record Associations guide, for instance, you will see that the join model (Appointment) is singular. This is the pattern you want to follow.
If you decide to do things unconventionally, then rails needs you to help it - for instance by requiring that you specify class_name.

Associate Rails active model with two different models

Is there a way to use inheritance with Ruby on Rails Active Model?
I have two models to which I want to add comments. It would be cool if I can just use one Comment model that could be associated with both models.
Look into Polymorphic Associations
class Comment < ApplicationRecord
belongs_to :commentable, polymorphic: true
end
class Article < ApplicationRecord
has_many :comments, as: :commentable
end
class Image < ApplicationRecord
has_many :comments, as: :commentable
end

Using rails counter_cache on a non-standard has_many :through

so the standard way to use a has_many :through association would be to use the Physician-Appointment-Patient model from the Active Record Association Guide, right? It's basically a more verbose HABTM, with two models having a has_many :through and the connector model having two belongs_to. Now, in my current project I have a model structure like this:
class Cart < ActiveRecord::Base
has_many :line_items, through: line_item_groups
has_many :line_item_groups
end
class LineItemGroup < ActiveRecord::Base
belongs_to :cart
has_many :line_items
end
class LineItem < ActiveRecord::Base
belongs_to :line_item_group
has_one :cart, through: line_item_group
end
Works fine. But now I want a line_item_count on Cart and can't figure out where I should add the counter_cache attribute.
Any help is appreciated :-)
First add line_item_count field in carts table, then in LineItem model add
class LineItem < ActiveRecord::Base
before_create :increment_counter
before_destroy :decrement_counter
def increment_counter
Cart.increment_counter(:line_item_count, cart.id)
end
def decrement_counter
Cart.decrement_counter(:line_item_count, cart.id)
end
end
I didn't tried it, but I think it will solve your problem.

Change the default polymorphic type-column name

I am using Ruby on Rails 3 and I would like to change the default type-column name used by a polymorphic association.
For example, if I have this class:
class Comment < ActiveRecord::Base
...
end
and I implement for that a polymorphic association, I would like to use the type-column names comm_id and comm_type instead of commentable_id and commentable_type. Is it possible? If so, what I have to change for the Comment class?
There's no way in Rails API to override the default column name used for polymorphic associations.
Take a look at this answer for a possible solution.
I did this in rails 6 on my legacy database using the foreign_type: option. This should work for rails >= 4.2.1 (see here)
# booking model
class Booking < ApplicationRecord
has_many :user_notes, as: :notable, foreign_type: :note_type, foreign_key: :type_id
end
# booking model
# here polymorphic columns are `note_type` and `type_id`
class UserNote < ApplicationRecord
belongs_to :notable, polymorphic: true, foreign_type: :note_type, foreign_key: :type_id
end
In your case, why not just change the association to:
# Comment
belongs_to :comm, :polymorphic => true
# Everything else
has_many :comments, :as => :comm

'has_one :through' association using namespaced classes

I am using Ruby on Rails 3 and I am trying to use an has_one :through association using namespaced classes. I read the official guide about association models but I don't know how to accomplish that.
I have User, Relationship and Groupclasses and I would like to associate Users and Groups through the Relationship class. As well, I would like to autosave related records and delete the relationship records on group or user deletion.
My file system is:
app/models/users/user.rb
app/models/users/relationship.rb
app/models/users/group.rb
In configs/routes.rb I have
namespace :users do
resources :users
resources :relationship
resources :groups
end
Class (Model) statements are:
class Users::User < ActiveRecord::Base
...
end
class Users::Relationship < ActiveRecord::Base
...
end
class Users::Group < ActiveRecord::Base
...
end
How I must write code associations in above model files? Have you some advice about?
UPDATE
My Classes (Models) have these attributes:
User
id
full_name
...
Relationship
id
user_id
group_id
Group
id
name
Your route namespacing has nothing to do with your model namespacing.
class Users::User < ActiveRecord::Base
has_many :relationships, :class_name=>"Users::Relationship", :dependent=>:destroy, :autosave=>true
has_many :groups, :class_name=>"Users::Group", :through=>:relationships
end
class Users::Relationship < ActiveRecord::Base
belongs_to :user, :class_name=>"Users::User"
belongs_to :group, :class_name=>"Users::Group"
end
class Users::Group < ActiveRecord::Base
has_many :relationsips, :class_name=>"Users::Relationship", :dependent=>:destroy, :autosave=>true
end

Resources