Belongs_to alias - ruby-on-rails

I want to get the username of comment author like this
comment.commenter
models/comment.rb
class Comment < ActiveRecord::Base
belongs_to :commenter
belongs_to :commentable, polymorphic: true
end
models/user.rb
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
validates :username, presence: true, uniqueness: true
has_many :comments, as: :commenter
end
When i try to create Comment directly to db using this line of code:
Comment.create(commentable_type: 'Pokemon', commentable_id: 1, content: 'great', commenter: 1)
It throws this error
NameError: uninitialized constant Comment::Commenter
from /var/lib/gems/2.3.0/gems/activerecord-4.2.6/lib/active_record/inheritance.rb:158:in `compute_type'
I've read somewhere as: is used only for polymorphic assocciations so that might be the case of my error but couldn't figure out how to get around this problem

I don't think as: is what you are looking for. I think your issue is similar to the issue in belongs_to with :class_name option fails
Try
# user.rb
has_many :comments, foreign_key: "commenter_id"
# comment.rb
belongs_to :commenter, class_name: "User", foreign_key: "commenter_id"

Let's explain a bit before going to the solution, if you write this code:
belongs_to :commentable, polymorphic: true
It implicitly means:
belongs_to :commentable, foreign_key: 'commentable_id', foreign_type: 'commentable_type', polymorphic: true
And
has_many :comments, as: :commentable
It specifies the syntax of polymorphic, that also means the foreign_key is commentable_id and foreign_type is commentable_type so if you want to change commentable to commenter, it is possible, you can do like this:
class Comment < ActiveRecord::Base
belongs_to :commenter, foreign_key: 'commentable_id', foreign_type: 'commentable_type', polymorphic: true
end
class User < ActiveRecord::Base
has_many :comments, as: commentable
end
That 's it!
For detail, please go through has_many and belongs_to documentation

Related

User has_many association not working (error:Could not find the association :user_categories in model Category)

I have three models and here they are when I try to create a has_many. I basically want my users (using devise) to have many categories. And categories to have many users.
user.rb
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable,
:omniauthable
has_many :user_categories
has_many :categories, through: :user_categories
acts_as_messageable
def mailboxer_email(object)
email
end
end
userCategory.rb
class UserCategory < ActiveRecord::Base
belongs_to :user
belongs_to :category
accepts_nested_attributes_for :categories
end
Category.rb
class Category < ActiveRecord::Base
has_many :user_categories
has_many :user, through: :user_categories
validates :name, presence: true, length: {minimum: 3, maximum: 25}
validates_uniqueness_of :name
end
when I run category.users << user I get this error:
ActiveRecord::HasManyThroughAssociationNotFoundError: Could not find the association :user_categories in model Category
I can't say for sure what the problem could be, but a few things I could point out:
UserCategory's accepts_nested_attributes_for, does that mean the you want to be able to dynamically create categories?
Category has_many :users, through: :user_categories, not user
You need to follow the Rails file naming conventions, user.rb, user_category.rb and category.rb
These may not be the problem/solution, but I believe they're in the way of resolving the problem.

Resources for Game Match in Rails?

What would be the best way to architect the model relationships and nested resources to build a game with: Users(from devise), Games, Players(join table w/ Games/Users). My problem is Users exist, but Players need to be created at the same time as games. Creating a game also has to create a player, which is possible but feels icky. Is there a better way to do this? I would like to avoid using transactions or filters to create new resources. Thanks.
class User < ActiveRecord::Base
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable
devise :omniauthable, :omniauth_providers => [:facebook, :twitter]
has_many :games
end
class Player < ActiveRecord::Base
validates :user_id, uniqueness: { scope: :game,
message: "can't join your own game" }
belongs_to :user
belongs_to :game
has_one :board
has_many :ships
end
class Game < ActiveRecord::Base
belongs_to :first_player, class_name: 'Player', foreign_key: 'first_player_id'
belongs_to :second_player, class_name: 'Player', foreign_key: 'second_player_id'
has_one :first_player_board, through: :first_player, source: :board
has_one :second_player_board, through: :second_player, source: :board
end
I ended up solving this by doing away with the player model all together and having Users have_many :games.
class Game < ActiveRecord::Base
belongs_to :first_player, class_name: 'User', foreign_key: 'first_player_id'
belongs_to :second_player, class_name: 'User', foreign_key: 'second_player_id'
has_one :first_player_board, through: :first_player, source: :board
has_one :second_player_board, through: :second_player, source: :board
end

2 references to same model without has_and_belongs_to_many

class Message < ActiveRecord::Base
belongs_to :conversation
belongs_to :user
end
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
has_many :conversations
has_many :conversations, class_name: "Conversation", foreign_key: :user2_id
end
class Conversation < ActiveRecord::Base
belongs_to :user
belongs_to :user2, class_name: "User", foreign_key: :user2_id
has_many :messages
end
spec:
require 'rails_helper'
RSpec.describe Message, type: :model do
it "should be available to 2 users" do
u = User.create(email: 'x#y.com', password: '8888888888')
u2 = User.create(email: 'z#w.com', password: '8888888888')
c = Conversation.create(user_id: u.id, user2_id: u2.id)
expect(u2.conversations.count).to eq 1
expect(u.conversations.count).to eq 1
end
end
It's this line:
expect(u.conversations.count).to eq 1
that fails.
Presumably because of my second has_many
But if I remove it, then expect(u2.conversations.count).to eq 1 fails.
Yes, I explicitly want only 2 users in a conversation. I was trying to avoid doing HABTM.
How do I make this work?
has_many :conversations
has_many :conversations, class_name: "Conversation", foreign_key: :user2_id
You can only have 1 has_many of a set name. Your first has_many is being overwritten by the second as the ruby class loads. I can't think of a better name but you should name one of them different, maybe something to demonstrate the person initiating the conversation.
You could use a has_many :through with a join model. Here is an explanation of how to set that up: http://www.tweetegy.com/2011/02/setting-join-table-attribute-has_many-through-association-in-rails-activerecord/.

Rails 4: has_many :through errors

Here is my join model:
class CompanyUser < ActiveRecord::Base
belongs_to :company
belongs_to :user
end
My User model:
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
ROLES = %w[admin requestor requestor_limited shipping_vendor].freeze
attr_accessor :temp_password
has_many :companies_users
...
end
If I run this in the console:
u = User.first
u.companies
This is the error I am getting:
NameError: uninitialized constant User::CompaniesUser
has_many through relationships should be like this:
In app/models/company.rb file,
has_many :company_users
has_many :users, :through => :company_users
In app/models/user.rb file,
has_many :company_users
has_many :companies, :through => :company_users
In app/models/company_user.rb file,
belongs_to :company
belongs_to :user
If you want to delete the dependent records in company_users table when deleting companies/users,
Add, , :dependent => :destroy at the end of has_many relations in Company and User model.
Hope this helps you..
Thanks.!!
it must be
has_many :company_users
"CompanyUser".tableize => "company_users"
The model shall be either:
class CompaniesUser < ActiveRecord::Base
belongs_to :company
belongs_to :user
end
Or has_many declaration sheel be defined explicitly as:
class User < ActiveRecord::Base
has_many :company_users
end

What is <ActiveRecord::Associations::CollectionProxy []>?

I have these models:
class Item < ActiveRecord::Base
has_many :item_categoryships
has_many :categories, class_name: 'ItemCategoryship', foreign_key: 'category_id', :through => :item_categoryships
belongs_to :user
validates :title, presence: true
end
class Category < ActiveRecord::Base
has_many :item_categoryships
has_many :items, :through => :item_categoryships
belongs_to :user
validates :name, presence: true
end
class ItemCategoryship < ActiveRecord::Base
belongs_to :item
belongs_to :category
validates :item_id, presence: true
validates :category_id, presence: true
end
class User < ActiveRecord::Base
has_many :items
has_many :categories, class_name: 'Category'
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable, :confirmable, :async
end
But I found when I call item.categories will get a empty array !!! I have checked database, there is a record here.
When I test in the rails console, I didn't get any record back, just saw 'ActiveRecord::Associations::CollectionProxy []'.
What is this? I am using Rails 4.0.2.
Thanks you all.
ActiveRecord::Associations::CollectionProxy is ActiveRecord class for collection associations. Now, your code should work if you change line in Item class describing categories association to:
has_many :categories, through: :item_categoryships

Resources