Undefined method for ActiveRecord_Associations_CollectionProxy - ruby-on-rails-4

I have several models, which are connected to each other:
class InsurerPayment < ActiveRecord::Base
belongs_to :insurer
belongs_to :company
has_many :contracts
end
class Insurer < ActiveRecord::Base
belongs_to :company
has_many :contracts
has_many :insurer_payments, dependent: :destroy
end
class Contract < ActiveRecord::Base
belongs_to :company
belongs_to :insurer
belongs_to :insurer_payment
end
When I do commissions = current_company.contracts.pluck(:commission).sum in my insurer_payments_controller, I get the sum of commission for all the contract related to my current company. But I need to get the sum of commission that belongs to insurers of my current company. Doing something like commissions = current_company.insurers.contracts.pluck(:commission).sum gives me an error: undefined method `contracts' for # Insurer::ActiveRecord_Associations_CollectionProxy:0x007f92450f79c0. How can I get the result I need? Thanks ahead.

You can try this:
current_company.insurers.map { |ins| ins.contracts.pluck(:commission).sum}
You are getting this type of error because when you hit current_company.insurers is return an array, and you hit contracts on this array this is incorrect.

Related

Cascading multiple models

I'm deleting a Place and it's cascading the rows of PlaceUpload, but I also would like to cascade the rows of Match and TagCostumer while I am deleting a Place. How can I do that?
class Place < ActiveRecord::Base
has_many :place_uploads
end
class PlaceUpload < ActiveRecord::Base
belongs_to :place
has_many :matches
has_many :tags_customers
end
class TagsCustomer < ActiveRecord::Base
belongs_to :place_upload
belongs_to :tag
end
class Match < ActiveRecord::Base
belongs_to :place_upload
belongs_to :customer
end
The solution was to use destroy and create a callback to automatically do a deep cascading.
class Place < ActiveRecord::Base
before_destroy :delete_children_objects
has_many :place_uploads, :dependent => :destroy
protected
def delete_children_objects
#places = PlaceUpload.where(place_id: id)
#places.each do |place|
TagsCustomer.where(place_upload_id: place.id).destroy_all
Match.where(place_upload_id: place.id).destroy_all
end
end
end

Rails: multiple associations query

I have associations like this: Profession -> orders -> profile -> location
Class Profession < ActiveRecord::Base
has_many: orders
end
Class Order < ActiveRecord::Base
has_one :profession
belongs_to :profile
end
Class Profile < ActiveRecord::Base
has_one :location
has_many :orders
end
Class Location < ActiveRecord::Base
belong_to :profile
end
And I need to find a professions which are in the location.city.
For example I try this:
Profession.joins(:orders).where(orders: {profile: {location: {city: "Simferopol"}}})
Is this possible?
Thanks.
You might consider an association using through:
class Profession < ActiveRecord::Base
has_many :orders
has_many :profiles, through: :orders
end
This may make life easier for you allowing you to call:
Profession.profiles
This will return all profiles for a given state. It just seems less messy to me. As you still need to reach the location associated with a profile I am sure there is a more optimal solution, but I believe this approach is better than the proposed:
Profession.joins(:orders).where(orders: {profile: {location: {city: "Simferopol"}}})

use of includes or left outer joins for complex nested associations

I have four models
class Company < ActiveRecord::Base
has_many :share_types
belongs_to :user
end
class ShareType < ActiveRecord::Base
has_many :shares
belongs_to :company
end
class Share < ActiveRecord::Base
belongs_to :user
belongs_to :share_type
end
class User < ActiveRecord:Base
has_many :companies
has_many :shares
end
Now list of all companies where company is owned by current_user or user have shares in a company something like this.
Company.joins(share_types:[:shares]).where("shares.user_id=? OR companies.user_id=?", #user.id, #user.id)
but with left outer join another I do not know how to use includes with or conditions another hint is
Company.includes(share_types:[:shares]).where(shares:{user_id: #user.id} OR companies:{user_id: 1})
How can I do that.
I am able to get my expected result with the help of references. Here is my query just posting to help others.
Company.includes(share_types:[:shares]).where("shares.user_id=? OR companies.user_id=?", 1,1).references(:shares)
its working thanks to The Rails 4 Way by Obie Fernandez

How to do a Polymorphic model association with another model

I have two basic models:
class Case < ActiveRecord::Base
has_many :contacts
end
class Contact < ActiveRecord::Base
belongs_to :case
belongs_to :contactable, :polymorphic => true, :foreign_key => :contactable_id
end
I also have quite a few models that are "sub types" of the Contact model:
class Attorney < ActiveRecord::Base
has_one :contact, as: :contactable, dependent: :destroy
accepts_nested_attributes_for :contact
end
class Client < ActiveRecord::Base
has_one :contact, as: :contactable, dependent: :destroy
accepts_nested_attributes_for :contact
end
I used polymorphic associations instead of STI because I don't want one table to store all the fields, which can get a little slow and overwhelming.
I am wondering if the has_many :contacts line from the Case model is correct. I try to use it in my console, but it doesn't really work the way I expected. Am I missing something?
I basically want an association where a Case can have many Contacts and a contact can belong to many cases. The contact can be of any type (Attorney or Client or Contact by itself). I was hoping it was as easy as case has_many :contacts

rails scope through has_many association

I have two models for Show and Performance (show as in a play or comedy show). They are associated like this in the models:
class Show < ActiveRecord::Base
has_many :performances, :dependent => :destroy
accepts_nested_attributes_for :performances
end
class Performance < ActiveRecord::Base
belongs_to :show
end
In the Performance model there is a datetime called :start_time.
How do I define a scope in the model which returns all Shows with at least one performance whose :start_time is in the future?
Also, how do I define a scope that returns all Shows that do not have any performances in whose :start_time is in the future?
class Show < ActiveRecord::Base
has_many :performances, :dependent => :destroy
accepts_nested_attributes_for :performances
scope :shows_with_pending_performance, includes(:performances).where("performances.start_time >= ? ", Date.today)
end
class Performance < ActiveRecord::Base
belongs_to :show
end