Rails where having query - ruby-on-rails

Here's the query I'm trying to run:
Stack.joins(:services)
.select('stacks.id, stacks.name, count(services.id) as services_count')
.group('stacks.id').having('services_count > 2')
The error I'm getting is:
ActiveRecord::StatementInvalid: PG::UndefinedColumn: ERROR: column "services_count" does not exist
LINE 1: ...ack_items"."service_id" GROUP BY stacks.id HAVING services_c...
Here are how my Stack model is related:
class Stack < ActiveRecord::Base
has_many :services, through: :stack_items
end
class StackItem < ActiveRecord::Base
belongs_to :service
belongs_to :stack
end
class Service < ActiveRecord::Base
has_many :stacks, through: :stack_items, dependent: :destroy
end
I just want to get a collection of Stacks that have at least 3 stack items where service.weight == 1.
Any suggestions?

Aliases that you set in the SELECT list in Postgres are not available in a group by clause, so simply change .having('services_count > 2') to .having('count(services.id) > 2').

Related

Rails polymorphism - exception from Action Controller

I'm having trouble implementing polymorphism in between my Rails models.
The intended structure is that I have an object/model called a 'Test'. Each Test has multiple Scenarios and multiple Runs. Each Scenario and each Run has multiple Events. On my 'show' view for Tests, I want to have a list of all events associated with it (through the Scenarios/Runs).
What I have as class definitions:
class Test < ActiveRecord::Base
has_many :scenarios
has_many :runs
end
class Scenario < ActiveRecord::Base
belongs_to :test
has_many :events, :as => :eventhaver
end
class Run < ActiveRecord::Base
belongs_to :test
has_many :events, :as => :eventhaver
end
class Event < ActiveRecord::Base
belongs_to :eventhaver, :polymorphic => true
end
The database is fully set up and contains a selection of records - 1 Test with 4 Scenarios and 2 Runs, each of which has 1 or 2 events. But when I try to go to the show view for the Test:
ActiveRecord::StatementInvalid in Tests#show
Mysql2::Error: Unknown column 'events.eventhaver_id' in 'where clause': SELECT events.* FROM events WHERE events.eventhaver_id = 1 AND events.eventhaver_type = 'Scenario'
This tells me that something isn't working with the polymorphism definitions, because it is looking for the abstract class/model 'eventhaver' instead of the child classes 'Scenario' and 'Run'. What else do I have to do so that Rails makes the connection and looks for either scenario_id or run_id?
You need to have a integer column eventhaver_id and a string column eventhaver_type in your events table.
The error tells you, that at least the column eventhaver_id is missing.
If you have the coloumns scenario_id and run_id in your events table, you can delete them. Polymorphic associations only use the *abstract*_id,*abstract*_type interface.
See: http://guides.rubyonrails.org/association_basics.html#polymorphic-associations
Edit:
If you can't change your database you can use :has_many, :through plus a events method to access all event belonging to a test.
class Test < ActiveRecord::Base
has_many :scenarios
has_many :runs
has_many :scenario_events, through: :scenarios, source: :events
has_many :run_events, through: :runs, source: :events
def events
scenario_events + run_events
end
end
class Scenario < ActiveRecord::Base
belongs_to :test
has_many :events
end
class Run < ActiveRecord::Base
belongs_to :test
has_many :events
end
class Event < ActiveRecord::Base
belongs_to :run
belongs_to :scenario
end

How to query has_one through relationship?

My models:
metro_station.rb
class MetroStation < ActiveRecord::Base
belongs_to :metro_line
has_one :city, through: :metro_line, autosave: false
end
metro_line.rb`
class MetroLine < ActiveRecord::Base
belongs_to :city
has_many :metro_stations
end
city.rb
class City < ActiveRecord::Base
has_many :metro_lines
end
When I run:
MetroStation.where(city: City.first)
I get
PG::UndefinedColumn: ERROR: column metro_stations.city_id does not exist
: SELECT "metro_stations".* FROM "metro_stations" WHERE "metro_stations"."city_id" = 1
(pry) output error: #<ActiveRecord::StatementInvalid: PG::UndefinedColumn: ERROR: column metro_stations.city_id does not exist
LINE 1: ...CT "metro_stations".* FROM "metro_stations" WHERE "metro_sta...
While this query works:
MetroStation.joins(:metro_line).where(metro_lines: {city_id: 1})
To find out why your first approach doesn't work type in
MetroStation.where(city: City.first).to_sql
You should see something like
... WHERE metro_stations.city_id = 1
forming part of the query. The MetroStation model simply doesn't have the city_id attribute, as a result your first approach forms an invalid SQL statement.
The join works since it is filtering on the MetroLine table which has the relationship to the City model in form of the city_id field.
Nothing wrong with your models it is just the way Rails generates the SQL statements which in the world of SQL makes sense.
A has_many relationship on City to MetroStation through MetroLine delivers the desired results for your question (which metro stations are in a city).
Example
class City < ActiveRecord::Base
has_many :metro_lines
has_many :metro_stations, through: :metro_lines
end
class MetroLine < ActiveRecord::Base
belongs_to :city
has_many :metro_stations
end
class MetroStation < ActiveRecord::Base
belongs_to :metro_line
has_one :city, through: :metro_line
end
# Return all metro stations for a city
# * assuming City has name 'name' field
london_stations = City.find_by_name('London').metro_stations
Hope this helps!
City should also:
has_many :metro_stations, :through => :metro_lines
And then you write:
City.first.metro_stations

Postgresql Group_by error

I am trying to do the following:
#business.placements.includes(:employee).group(:month). order('points DESC').map(&:employee)
But I keep getting the following error (whenever I use group_by I run into problems because of my lack of postgresql knowledge):
ActiveRecord::StatementInvalid (PG::Error: ERROR: column "placements.id" must appear in the GROUP BY clause or be used in an aggregate function
LINE 1: SELECT "placements".* FROM "placements" INNER JOIN "employee...
^
: SELECT "placements".* FROM "placements" INNER JOIN "employees" ON "placements"."employee_id" = "employees"."id" WHERE "employees"."business_id" = 43 GROUP BY month ORDER BY points DESC)
My schema looks as follows (if any help):
class Business < ActiveRecord::Base
has_many :employees, dependent: :destroy
has_many :placements, through: :employees
class Employee < ActiveRecord::Base
belongs_to :business
has_many :placements
class Placement < ActiveRecord::Base
belongs_to :employee
class Vote < ActiveRecord::Base
belongs_to :employee

Problems with CamelCase and underscore Rails 3

I have two models with a has many through association between them like below:
TipoDocumento < ActiveRecord::Base
has_many :dependencias
has_many :TipoRequisitos, :through => :dependencias
...
end
TipoRequisito < ActiveRecord::Base
has_many :dependencias
has_many :TipoDocumentos, :through => :dependencias
...
end
Dependencia < ActiveRecord::Base
belongs_to: TipoDocumento
belongs_to: TipoRequisito
...
end
The id's attributes for the join model Dependencia are TipoDocumento_id and TipoRequisito_id.
Now, when I try this in the rails console:
x = TipoDocumento.find(1)
x.TipoRequisitos
I get this error:
ActiveRecord::StatementInvalid: SQLite3::SQLException: no such column: dependencia.tipo_documento_id: SELECT "tipo_requisitos".* FROM "tipo_requisitos" INNER JOIN "dependencia" ON "tipo_requisitos"."id" = "dependencia"."TipoRequisito_id" WHERE "dependencia"."tipo_documento_id" = 1
also if I try the opposite with TipoRequisito it's the same.
It seems that Rails is changing somehow the TipoDocumento_id column name for tipo_documento_id when it performs the query. So, I tried to change the id's column's names from their CamelCase to their snake_case, but I get the analog error (Cannot find TipoDocumento_id or TipoRequisito_id.)
I don't see what's wrong.
You need to follow the Rails convention and use down-cased names when you refer to models when defining relations:
TipoDocumento < ActiveRecord::Base
has_many :dependencias
has_many :tipo_requisitos, through: :dependencias
...
end
TipoRequisito < ActiveRecord::Base
has_many :dependencias
has_many :tipo_documentos, :through => :dependencias
...
end
Dependencia < ActiveRecord::Base
belongs_to :tipo_documento
belongs_to :tipo_requisito
...
end
you need to lower-case it, like this:
x = TipoDocumento.find(1)
x.tipo_requisitos
Please also check: http://guides.rubyonrails.org/association_basics.html

Trouble update has_many :through record

I am having an issue updating a has_many through record. Here is my setup:
class TastingGroup < ActiveRecord::Base
has_many :group_wine
has_many :wines, through: :group_wine
end
class GroupWine < ActiveRecord::Base
belongs_to :tasting_group
belongs_to :wine
end
class Wine < ActiveRecord::Base
has_many :group_wine
has_many :tasting_groups, through: :group_wine
end
I was trying to use the acts_as_list for this, because the order of the wines in a TastinGroup matter, so I have added a 'position' attribute to the GroupWine model.
However, when I try to even update a GroupWine record, I get the following error, and here is what I am doing.
gw = GroupWine.first
#<GroupWine:0x007fd9f7c38b50> {
:wine_id => 1,
:tasting_group_id => 1,
:position => nil
}
gw.position = 1
gw.save
And here is the error I get...
ActiveRecord::StatementInvalid: Mysql2::Error: Unknown column 'group_wines.' in 'where clause': UPDATE `group_wines` SET `position` = 3 WHERE `group_wines`.`` IS NULL
What is up with the NULL for group_wines, and why is it adding that where clause?
Thanks.
Try pluralizing the group_wine object to group_wines
class TastingGroup < ActiveRecord::Base
has_many :group_wines
has_many :wines, through: :group_wines
end
class GroupWine < ActiveRecord::Base
belongs_to :tasting_group
belongs_to :wine
end
class Wine < ActiveRecord::Base
has_many :group_wines
has_many :tasting_groups, through: :group_wines
end

Resources