How to write has_many_polymorphs in rails 3 - ruby-on-rails

How can I write the following code in rails 3 without using the has_many_polymorphs plugin?
has_many_polymorphs :listings, :from => [:my_properties, :friend_properties, :public_properties, :private_properties, :job_listings, :truck_listings, :open_listings, :sale_listings], :through => :group_listings

This video help me allot to make this #154 Polymorphic Association
in key on your Polymorphic table you need a ID of the record you want to link to and the name of the table you want to link to.
I usual do it like:
Migration
create_table "cards", force: true do |t|
t.string '....', default: ""
t.integer "accountable_id"
t.string "accountable_type", default: ""
end
Cards Model
belongs_to :accountable, :polymorphic => true
Others Model
has_many :cards, :as => :accountable
I hope that this helps

Related

In a Rails Model, will belongs_to cause a rollback if not defined?

Model:
class UserPosition < ApplicationRecord
belongs_to :user
belongs_to :job_title
end
UserPosition's schema:
t.integer :user_id
t.integer :company_id
t.integer :industry_id
t.integer :department_id
t.integer :job_title_id
t.string :job_title_custom
user_positions_controller.rb
def create
#user_position = UserPosition.find_or_create_by(user_id: current_user.id)
#user_position.update_attributes({
:industry_id => params[:industry_id],
:department_id => params[:department_id],
:job_title_id => params[:job_title_id],
:job_title_custom => params[:job_title_custom]
})
I need UserPosition to either create a record with:
user_id
job_title_custom
OR
t.integer :user_id
t.integer :company_id
t.integer :industry_id
t.integer :department_id
t.integer :job_title_id
Currently, if I try to create a UserPosition with just user_id & job_title_custom
It doesn't work, the logs show ROLLBACK the error message is:
#messages={:job_title=>["must exist"]}
What am I doing wrong here? I think it could be because job_title has a relationship defined in the model but the Rails Guide says that they are optional, so I'm not sure.
Turns out this is a new Rails 5 behavior.
"In Rails 5, whenever we define a belongs_to association, it is required to have the associated record present by default after this change.
It triggers validation error if associated record is not present."
"In Rails 4.x world To add validation on belongs_to association, we need to add option required: true ."
"Opting out of this default behavior in Rails 5. We can pass optional: true to the belongs_to association which would remove this validation check."
Full Answer: http://blog.bigbinary.com/2016/02/15/rails-5-makes-belong-to-association-required-by-default.html

Trouble with self referential model in Rails

I have a model named User and I want to be able to self reference other users as a Contact. In more detail, I want a uni-directional relationship from users to other users, and I want to be able to reference an owned user of one user as a 'contact'. ALSO, i want to have information associated with the relationship, so I will be adding fields to the usercontact relation (I just edited this sentence in).
I attempted to do this while using the answer to this question as a guide.
Here is the User model:
user.rb
class User < ActiveRecord::Base
attr_accessible(:company, :email, :first_name, :last_name,
:phone_number, :position)
has_many(:user_contacts, :foreign_key => :user_id,
:dependent => :destroy)
has_many(:reverse_user_contacts, :class_name => :UserContact,
:foreign_key => :contact_id, :dependent => :destroy)
has_many :contacts, :through => :user_contacts, :source => :contact
end
I also created the model UserContact as a part of connecting contacts to users:
usercontact.rb
class UserContact < ActiveRecord::Base
belongs_to :user, :class_name => :User
belongs_to :contact, :class_name => :User
end
Here is the create_users.rb migration file i used:
create_users.rb
class CreateUsers < ActiveRecord::Migration
def change
create_table :users do |t|
t.string :first_name
t.string :last_name
t.string :phone_number
t.string :email
t.string :company
t.string :position
t.timestamps
end
end
end
And here is the create_users_contacts.rb migration:
create_users_contacts.rb
class CreateUsersContacts < ActiveRecord::Migration
def up
create_table :users_contacts, :force => true do |t|
t.integer :user_id, :null => false
t.integer :contact_id, :null => false
t.boolean :update, :null => false, :default => false
end
# Ensure that each user can only have a unique contact once
add_index :users_contacts, [:user_id, :contact_id], :unique => true
end
def down
remove_index :users_contacts, :column => [:user_id, :contact_id]
drop_table :users_contacts
end
end
However, for reasons unknown to me, I believe something has gone awry in the linking since on my users index page, I have a column using <td><%= user.contacts.count %></td>, but I get this error from the line when I attempt to load the page:
uninitialized constant User::UserContact
I think the issue may be something to do with the fact that I want to name users associated with another user as contacts, because I cannot find other examples where that is done, and as far as I can tell I am doing everything properly otherwise (similarly to other examples).
The closest similar problem that I found was outlined and solved in this question. The issue was incorrect naming of his connecting model, however I double checked my naming and it does not have that asker's problem.
Any help is appreciated, let me know if any other files or information is necessary to diagnose why this is occurring.
EDIT
After changing usercontact.rb to user_contact.rb, I am now getting this error:
PG::Error: ERROR: relation "user_contacts" does not exist
LINE 1: SELECT COUNT(*) FROM "users" INNER JOIN "user_contacts" ON "...
^
: SELECT COUNT(*) FROM "users" INNER JOIN "user_contacts" ON "users"."id" = "user_contacts"."contact_id" WHERE "user_contacts"."user_id" = 1
EDIT TWO
The issue was that my linking table, users_contacts, was misnamed, and should have been user_contacts! so I fixed it, and now it appears to work!!
You need to rename your usercontact.rb to user_contact.rb
This is naming convention rails autoload works with.

Making ActiveRecord join model attributes available in query results

Given User and Book models, I've created a join model, ViewedBook, that contains additional attributes. Below is the essence of what I've come up with:
create_table "users"
t.string "username"
end
create_table "books"
t.string "title"
t.integer "user_id"
t.date "authored_date"
end
create_table "books_viewings"
t.integer "book_id"
t.integer "user_id"
t.boolean "finished"
t.date "last_viewed_date"
end
class User
belongs_to :book_viewing
has_many :authored_books,
:class_name => "Book",
:source => :book
has_many :book_viewings
has_many :viewed_books :through => :book_viewings
:order => "book_viewings.last_viewed_date DESC"
has_many :finished_books :through => :book_viewings
:conditions => "book_viewings.finished = TRUE",
:order => "book_viewings.last_viewed_date DESC"
end
class Book
belongs_to :user
has_one :author, :class_name => "User"
end
class BookViewing
belongs_to :book
belongs_to :user
end
I think this works for most of the queries I need to create. However, I want each of the Book objects returned by user.viewed_books to include the finished attribute as well. Further, I will have additional queries like Book.best_sellers that I would also like to scope to a given user so that they also include the finished attribute.
From my limited exposure to ActiveRecord, it appears there's probably an elegant way to manage this and generate efficient queries, but I have yet to find an example that clarifies this scenario.
EDIT: to clarify, the other queries I'm looking for will not themselves be restricted to books that have been finished, but I need to have the finished attribute appended to each book if it exists for the given book and scoped user in book_viewings.
See my answer here https://stackoverflow.com/a/8874831/365865
Pretty much, no there isn't a specific way to do this, but you can pass a select option to your has_many association. In your case I'd do this:
has_many :books, :through => :book_viewings, :select => 'books.*, book_viewings.finished as finished'

How to access information using Rails in Join Model

I have two models:
USERS
has_many :celebrations
has_many :boards, :through => :celebrations
BOARDS
has_many :celebrations
has_many :users, :through => :celebrations
CELEBRATIONS
:belongs_to :user
:belongs_to :board
I understand that I create a third join table and model called "Celebrations" which does not require an ID.
create_table :, :id => false do |t|
t.column :board_id, :int, :null => false
t.column :user_id, :int, :null => false
t.column :role, :string, :null => false
t.column :token, :string
t.timestamps
end
end
How do I access the information?
user.celebrations.role
user.celeberations.token
user.boards
board.users
Thanks in advance. I understand its a real newbie question.
Yes, you can but if the join table has additional attributes then you should convert it to the full model. I mean to create a new Rails model with id, article_id, author_id and additional fields like role.
This is the Rails way of implementing such things. There is a small overhead of making the join table a little bit bigger. However with full join model it is possible to use standard Rails functions to create and update that model.
As far I remember has_many :through option was added to support better join models.

how do I get foreign_key to work in this simple has_many, belongs_to relationship?

I'm pulling data from Harvest. Here are my two models and schema:
# schema
create_table "clients", :force => true do |t|
t.string "name"
t.integer "harvest_id"
end
create_table "projects", :force => true do |t|
t.string "name"
t.integer "client_id"
t.integer "harvest_id"
end
# Client.rb
has_many :projects, :foreign_key => 'client_id' # not needed, I know
# Project.rb
belongs_to :client, :foreign_key => 'harvest_id'
I'm trying to get the Projects to find their client by matching Project.client_id to a Client.harvest_id. Here is what I'm getting instead.
> Project.first.client_id
=> 187259
Project.first.client
=> nil
Client.find(187259).projects
=> []
Is this possible? Thanks!
Might not seem intuitive, but the foreign_key for both relations has to be the same. Let's say you decide to use harvest_id as the foreign key. It should be set up like this:
# Client.rb
has_many :projects, :foreign_key => 'harvest_id'
# Project.rb
belongs_to :client, :foreign_key => 'harvest_id'
You would also only have the harvest_id field in the projects table, since the client has_many projects.
Since your belongs_to relationship in Project model is on harvest_id, you have to ensure the harvest_id attribute is set in the project object.
> Project.first.harvest_id
=> ??
Your problem can occur if the harvest_id is not set.
Projects to find their client by matching Project.client_id to a Client.harvest_id
This does not seem to make sense as client and harvest are supposed to be different objects/records and you cannot match them.
It is like "Find apples where there are Orange-like seeds".
So we probably need more context.
You defined your relations the following way:
On the Project side you say "it is related to client via client_id", but on the Client you say that "it is related to Project via harvest_id"
There you have discrepancy.
So it seems you just have incorrect mappings defined.
Not sure how harvest_id is supposed to be used, so will make the assumption it is just association:
# Client.rb
has_many :projects
belongs_to :harvest
# Project.rb
belongs_to :client
belongs_to :harvest
# Harvest
has_one :client
has_one :project

Resources