Using a .where IN clause with .includes down and up many nested levels to look up a group of IDs in Rails 3.1 - postgresql

I would like to filter a list of parent emails addresses by a classroom of students.
Here is a simplification of my models:
Class District
has_many :schools
has_many :families
has_many :children, :through => :families
has_many :parents, :through => :families
has_many :enrollments, :through => :children
end
Class Enrollments
belongs_to :child
belongs_to :classroom
end
The email address is associated with the parent record and I would like to filter emails by an array of classroom IDs.
I can get this to work:
idees = [49, 50]
current_district = District.first
#emails = current_district.parents.includes(:family => { :children => { :enrollments => {:classroom => { :program => :location }}}}).where("family_id IN (?)", idees)
# Returns families with ID 49 and 50
But I cannot get anything like this to work
idees = [49, 50]
current_district = District.first
#emails = current_district.parents.includes(:family => { :children => { :enrollments => {:classroom => { :program => :location }}}}).where("family.children.enrollments.classroom_id IN (?)", idees)
# Returns: PGError: ERROR: cross-database references are not implemented: family.children.enrollment.classroom_id
What am I doing wrong or is there another, better way to write this query?

The line below is the problem.
where("family.children.enrollments.classroom_id IN (?)", idees)
Change it to :
where("enrollments.classroom_id IN (?)", idees)

Related

Save lab price on model to database rails

I have 3 models has_many, through relation : lab, medic_record, and lab_medic. In medic_record model, i have a method to calculate lab price and i have created a migration too for add column "lab_price:decimal" to medic_record
medic_record.rb
has_many :lab_medics, :dependent => :destroy
has_many :labs, :through => :lab_medics
before_save :finalize
def lab_price
Lab.where(:id => self.lab_ids).reduce(0) { |sum, x| sum += x[:price].to_f }
end
private
def finalize
self[:lab_price] = lab_price
end
lab.rb
has_many :lab_medics, :dependent => :destroy
has_many :medic_records, :through => :lab_medics
lab_medic.rb
belongs_to :lab
belongs_to :medic_record
My question is how to save a lab_price in medic_record model to database 'column :lab_price'? I have tried using 'before_save :finalize' method but the result on database always "0.0" after i created new record for medic_record.
SOLVED
I has changed method with this and its worked !!
def self.save_tot(medic)
medic.update_attributes(lab_price: Lab.where(:id => medic.lab_ids).reduce(0) { |sum, x| sum += x[:price].to_f })
end

Connecting database view with polymorphic model in rails

I have the following setup which allows a user to have multiple projects and each project can have multiple tasks. A user can favourite multiple projects.
class User < ActiveRecord::Base
has_many :projects
has_many :tasks, :through => :projects
has_many :favourites
has_many :favourite_projects, :through => :favourites, :source => :favourable, :source_type => "Project"
has_many :favourite_tasks, :through => :favourite_projects, :source => :tasks
...
end
class Project < ActiveRecord::Base
belongs_to :user
has_many :tasks
has_many :favourites, :as => :favourable
...
end
class Task < ActiveRecord::Base
belongs_to :project
...
end
class Favourite < ActiveRecord::Base
belongs_to :user
belongs_to :favourable, :polymorphic => true
...
end
This setup allows #user.favourite_tasks to list all the tasks for the projects that they have favourited.
Taking the suggestion from here (http://pivotallabs.com/database-views-performance-rails/) I am trying to replace the multi-level table joins with a database view where possible instead.
The view SQL is:
SELECT tasks.id AS task_id, ..., projects.id AS project_id, ...
FROM tasks INNER JOIN projects ON projects.id = tasks.project_id
My new ProjectTask model is:
class ProjectTask < ActiveRecord::Base
self.primary_key = 'task_id'
end
I've updated my User model to include:
has_many :project_tasks
which works fine for #user.project_tasks.
However, I can't figure out what the has_many/has_one/belongs_to should be in the models for the favourites to work (connecting the favourites to the view rather than the projects table).
I'm aiming for has _many :favourite_project_tasks, :through => :favourites.... so that I can use #user.favourite_project_tasks in my controller and attach any ProjectTask model scopes to it if need be.
I think the fact that the ProjectTask model has task_id as the primary key is causing issue with rails linking the tables/view and because using :through overrides any use of :foreign_key and :primary_key (according to http://apidock.com/rails/ActiveRecord/Associations/ClassMethods/has_many).
Hopefully someone can advise what I should be doing because I've tried loads of combinations of changes with no joy.
Thanks
Issue seems to have been caused by the custom primary key.
By updating the User model with (I was already doing this when it was failing):
has_many :favourite_project_tasks, :through => :favourite_projects, :source => :project_tasks
to use the view and also changing the view to use:
SELECT tasks.id AS id, ...
rather than:
SELECT tasks.id AS task_id, ...
and changing the ProjectTask view model to use:
self.primary_key = :id
it now works.

Form for deep association with CakePHP, almost working

I'm writing my first Cake app and trying to set up my first deep association. It's very nearly working but I have a couple of small issues.
The first part of my app is a customer database. A customer has many addresses, and an address has many contacts. The data structure returned contains duplicated data from the address model.
Here's the 3 models:
class Customer extends AppModel {
public $hasMany = 'CustomerAddress';
}
class CustomerAddress extends AppModel {
public $belongsTo = 'Customer';
public $hasMany = 'CustomerContact';
}
class CustomerContact extends AppModel {
public $belongsTo = 'CustomerAddress';
}
In my customer controller, I want to get associated addresses and their contacts. I can do this by setting recursion on the find command:
CustomerController.php
public function find( $id = NULL) {
$this->set('customers', $this->Customer->find('all', array( 'recursive' => 2)));
}
And this works brilliantly, with one caveat. The data structure returned looks like this:
array(
'Customer' => array(
'id' => '46',
....
),
'CustomerAddress' => array(
(int) 0 => array(
'id' => '35',
'customer_id' => '46',
.....
'Customer' => array(
'id' => '46',
.....
),
'CustomerContact' => array(
(int) 0 => array(
'id' => '29',
'customer_address_id' => '35',
.....
)
)
)
)
)
At a glance, this looks fine, and for all intents and purposes works as the data is formatted how you'd expect. But, CustomerAddress also contains a Customer object, which is a duplicate of the top level Customer object. I assume this is because recursion is working with the belongsTo on the address model.
I've tried setting the recursion to 1, but then I only get the address not the contact. I've tried setting the recursion in the address model, but that doesn't seem to effect the find at the Customer level.
It's not a huge issue, just worried about future performance issues and unnecessary calls to the database.
This is one of the reasons why it is discouraged to use the recursive setting. Most turn off recursion (set it to -1) then use the Containable behavior to get associated models instead. Make sure in AppModel, there is the line
public $actsAs = array('Containable');
Then, to get your data:
$this->Customer->find('all', array('contain' => array('CustomerAddress' => array('CustomerContact'))));

ActiveRecord cannot delete a record

I have my AttachmentsMembers table with the migration as:
class AttachmentsMembers < ActiveRecord::Migration
def change
create_table :attachments_members, :id => false do |t|
t.references :attachment, :null => false
t.references :member, :null => false
end
add_index :attachments_members, [:attachment_id, :member_id]
end
end
If I try to delete any record from my console then I get the following error:
ActiveRecord::StatementInvalid: PG::Error: ERROR: zero-length delimited identifier at or near """"
LINE 1: ...OM "attachments_members" WHERE "attachments_members"."" = $1
^
: DELETE FROM "attachments_members" WHERE "attachments_members"."" = $1
from /home/icicle/.rvm/gems/ruby-2.0.0-p353#ltbuddy/gems/activerecord-3.2.18/lib/active_record/connection_adapters/postgresql_adapter.rb:1208:in `prepare
Code for AttachmentsMember model:
class AttachmentsMember < ActiveRecord::Base
#Relationships
belongs_to :attachment
belongs_to :member
end
In attachment model:
belongs_to :user, class_name: 'User', foreign_key: 'user_id'
belongs_to :attachable, polymorphic: true
belongs_to :referable, polymorphic: true
has_many :attachments, as: :referable, :dependent => :destroy
has_many :attachments_members, :dependent => :destroy
has_many :members, :through => :attachments_members, :dependent => :destroy
In member model:
belongs_to :user, class_name: 'User', foreign_key: 'user_id'
belongs_to :case, class_name: 'Case', foreign_key: 'case_id'
belongs_to :user_type, class_name: 'UserType', foreign_key: 'user_type_id'
has_many :attachments_members, dependent: :destroy
has_many :attachments, :through => :attachments_members, dependent: :destroy
has_many :documents_members, dependent: :destroy
has_many :documents, :through => :documents_members, dependent: :destroy
Even if do AttachmentsMember.last from my console I get the same error but AttachmentsMember.first works.
Any someone explain why the issue is coming?
Resolved the issue by creating the primary key for AttachmentsMember table

What am I missing to define a variable from a page object? Getting undefined error in watir-webdriver

I'm trying to create a page object for the forms I'm automating and getting undefined local variable or method for 'checkout_form', though I thought I've already defined the variable.
This is my page object page:
require "page-object"
class CheckoutForm
include PageObject
# Checkout page
# Billing info
text_field(:billingfirst, :id => 'CheckOut_BillingTag_FirstName')
text_field(:billingmiddle, :id => 'CheckOut_BillingTag_MiddleInitial')
text_field(:billinglast, :id => 'CheckOut_BillingTag_Lastname')
text_field(:billingaddress, :id => 'CheckOut_BillingTag_Address1')
text_field(:billingaddress2, :id => 'CheckOut_BillingTag_Address2')
text_field(:billingcity, :id => 'CheckOut_BillingTag_City')
text_field(:billingstate, :id => 'CheckOut_BillingTag_State')
text_field(:billingzip, :id => 'CheckOut_BillingTag_ZipCode')
text_field(:billingphone, :id => 'CheckOut_BillingTag_Phone')
text_field(:billingemail, :id => 'CheckOut_BillingTag_Email')
def billing_info( billingfirst, billingmiddle, billinglast, billingaddress, billingaddress2, billingcity, billingstate, billingzip, billingphone, billingemail )
self.billingfirst = billingfirst
self.billingmiddle = billingmiddle
self.billinglast = billinglast
self.billingaddress = billingaddress
self.billingaddress2 = billingaddress2
self.billingcity = billingcity
self.billingstate = billingstate
self.billingzip = billingzip
self.billingphone = billingphone
self.billingemail = billingemail
end
end
On a different page that will use the page object I've added ' require_relative "checkout-form.rb" '
And there I set up the driver:
#b = Watir::Browser.new :ff
checkout_form = CheckoutForm.new(#b)
And interacting with the pageobject methods here:
checkout_form.billing_info.set 'Mike', 'L', 'Jones', '13677 Ruette Le Parc', 'Unit G', 'Del Mar', 'CA', '92014', 'aaaaa', 'mike.jones#gmail.com'