PG::UndefinedTable: ERROR: missing FROM-clause entry for table "Teams" - ruby-on-rails

I get the following error when trying to order a query by an associated table's "name" attribute.
Error
PG::UndefinedTable: ERROR: missing FROM-clause entry for table "team"
Query
: SELECT "team_seasons"."id" AS t0_r0, "team_seasons"."season_id" AS t0_r1, "team_seasons"."team_id" AS t0_r2, "team_seasons"."created_at" AS t0_r3, "team_seasons"."updated_at" AS t0_r4, "team_seasons"."points" AS t0_r5, "team_seasons"."goals_for" AS t0_r6, "team_seasons"."goals_against" AS t0_r7, "team_seasons"."games_played" AS t0_r8, "teams"."id" AS t1_r0, "teams"."name" AS t1_r1, "teams"."city" AS t1_r2, "teams"."created_at" AS t1_r3, "teams"."updated_at" AS t1_r4 FROM "team_seasons" LEFT OUTER JOIN "teams" ON "teams"."id" = "team_seasons"."team_id" WHERE "team_seasons"."season_id" = 1 ORDER BY team.name
SeasonsController.rb
class SeasonsController < ApplicationController
load_and_authorize_resource
def show
#season = Season.find(params[:id])
#teamseasons = TeamSeason.where(season: #season).includes(:team).order("team.name")
end
Removing the order or ordering by an attribute on the teamseason record doesn't produce the error so I know it's something related to the ordering of the related record. I thought including it was all I needed to do but obviously it's not working. Any help is much appreciated.

Try changing team.name to teams.name in (mind s)
TeamSeason.where(season: #season).includes(:team).order("team.name")

Related

I want to join tables and sort them with Geocoder Gem

What I want to solve
I want to combine the Area Model, Shop Model, and Account Model and get the results sorted in order of proximity from the location specified by the Geocoder Gem.
I want to list the results using each in a view.
However, I get a no such column: distance error as shown below.
In this case, no error will occur.
irb(main):043:0> Area.eager_load(:shop).near("tokyo")
SQL (0.4ms) SELECT areas.*, (69.09332411348201 * ABS(areas.latitude - 35.6828387) * 0.7071067811865475) + (59.836573914187355 * ABS(areas.longitude - 139.7594549) * 0.7071067811865475) AS distance, CASE WHEN (areas.latitude >= 35.6828387 AND areas.longitude >= 139.7594549) THEN 45.0 WHEN (areas.latitude < 35.6828387 AND areas.longitude >= 139.7594549) THEN 135.0 WHEN (areas.latitude < 35.6828387 AND areas.longitude < 139.7594549) THEN 225.0 WHEN (areas.latitude >= 35.6828387 AND areas.longitude < 139.7594549) THEN 315.0 END AS bearing, "areas"."id" AS t0_r0, "areas"."prefectures" AS t0_r1, "areas"."municipalities" AS t0_r2, "areas"."house_number" AS t0_r3, "areas"."building_name" AS t0_r4, "areas"."postal_code" AS t0_r5, "areas"."created_at" AS t0_r6, "areas"."updated_at" AS t0_r7, "areas"."latitude" AS t0_r8, "areas"."longitude" AS t0_r9, "shops"."id" AS t1_r0, "shops"."shop_name" AS t1_r1, "shops"."created_at" AS t1_r2, "shops"."updated_at" AS t1_r3, "shops"."shop_type_id" AS t1_r4, "shops"."station_id" AS t1_r5, "shops"."area_id" AS t1_r6 FROM "areas" LEFT OUTER JOIN "shops" ON "shops"."area_id" = "areas"."id" WHERE (areas.latitude BETWEEN 35.3933751337783 AND 35.972302266221696 AND areas.longitude BETWEEN 139.40308602609107 AND 140.11582377390894) ORDER BY distance ASC LIMIT ? [["LIMIT", 11]]
In this case, an error will occur
I want this to work.
irb(main):045:0> Area.eager_load(shop: :accounts).near("tokyo")
SQL (3.3ms) SELECT DISTINCT "areas"."id" FROM "areas" LEFT OUTER JOIN "shops" ON "shops"."area_id" = "areas"."id" LEFT OUTER JOIN "accounts" ON "accounts"."shop_id" = "shops"."id" WHERE (areas.latitude BETWEEN 35.3933751337783 AND 35.972302266221696 AND areas.longitude BETWEEN 139.40308602609107 AND 140.11582377390894) ORDER BY distance ASC LIMIT ? [["LIMIT", 11]]
Traceback (most recent call last):
ActiveRecord::StatementInvalid (SQLite3::SQLException: no such column: distance)
Environment
Ruby 2.6.3
Rails 6.0.3
Geocoder Gem: <https://github.com/alexreisner/geocoder>
Model association
# app/models/area
has_one :shop
# app/models/shop
belongs_to :shop_type
belongs_to :area
belongs_to :station
has_many :accounts
has_many :posts
# app/models/account
belongs_to :shop, optional: true
has_many :post
Addition
I tried the below, but it failed.
irb(main):001:0> Area.near("tokyo").eager_load(shop: :accounts)
(0.9ms) SELECT sqlite_version(*)
SQL (0.4ms) SELECT DISTINCT "areas"."id" FROM "areas" LEFT OUTER JOIN "shops" ON "shops"."area_id" = "areas"."id" LEFT OUTER JOIN "accounts" ON "accounts"."shop_id" = "shops"."id" WHERE (areas.latitude BETWEEN 35.3933751337783 AND 35.972302266221696 AND areas.longitude BETWEEN 139.40308602609107 AND 140.11582377390894) ORDER BY distance ASC LIMIT ? [["LIMIT", 11]]
Traceback (most recent call last):
ActiveRecord::StatementInvalid (SQLite3::SQLException: no such column: distance)
irb(main):002:0> Area.near("tokyo").eager_load(shop: :accounts)
SQL (0.3ms) SELECT DISTINCT "areas"."id" FROM "areas" LEFT OUTER JOIN "shops" ON "shops"."area_id" = "areas"."id" LEFT OUTER JOIN "accounts" ON "accounts"."shop_id" = "shops"."id" WHERE (areas.latitude BETWEEN 35.3933751337783 AND 35.972302266221696 AND areas.longitude BETWEEN 139.40308602609107 AND 140.11582377390894) ORDER BY distance ASC LIMIT ? [["LIMIT", 11]]
Traceback (most recent call last):
ActiveRecord::StatementInvalid (SQLite3::SQLException: no such column: distance)
irb(main):003:0>
The documentation mentions,
You cannot use the near scope with another scope that provides an
includes option because the SELECT clause generated by near will
overwrite it (or vice versa).
Instead of using includes to reduce the number of database queries,
try using joins with either the :select option or a call to preload.
For example:
So, maybe try Area.near("tokyo").eager_load(shop: :accounts) or Area.near("tokyo").joins(shop: :accounts) and see if that works?

ActiveRecord OUTER JOIN

In a Google Group, I've added my question - here infact!
My question is how to express this outer join 'the Rails way':
SELECT
`employees`.`id` AS t0_r0, `employees`.`name` AS t0_r1, `employees`.`last_seen` AS t0_r2, `employees`.`created_at` AS t0_r3, `employees`.`updated_at` AS t0_r4, `employees`.`punch_clock_id` AS t0_r5, `employees`.`account_id` AS t0_r6, `employees`.`born_at` AS t0_r7, `entrances`.`id` AS t1_r0, `entrances`.`employee_id` AS t1_r1, `entrances`.`clocked_at` AS t1_r2, `entrances`.`created_at` AS t1_r3, `entrances`.`updated_at` AS t1_r4, `entrances`.`entrance_type` AS t1_r5
FROM
`employees`
LEFT OUTER JOIN
`entrances` ON `entrances`.`employee_id` = `employees`.`id` AND (`entrances`.`clocked_at` BETWEEN '2015-01-01' AND '2015-01-31’)
WHERE
`employees`.`account_id` = 2
My first take was:
current_user.account.employees.includes(:entrances).where( 'entrances.clocked_at' => #month_range)
but that does only provide for employees with entrances (unless I loose the 'where' part of the statement, in which case I do get all employees (and all 250K entrances!!!))
If you want to include employees with no entrances you'll have to explicitly include that case in your where statement by calling entrances.id IS NULL.
current_user.account.employees.includes(:entrances).where( 'entrances.id IS NULL OR entrances.clocked_at = ?', #month_range)
That last part might look slightly different depending on what #month_range contains.

searching by email in ActiveRecord using named scope "<field> is ambiguous'

Using rails 3.2.6.
# 1 letter domain name in email without scope
> Member.where('UPPER(email) LIKE UPPER(?)' , "a#b.com")
Member Load (0.7ms) SELECT "members".* FROM "members" WHERE (UPPER(email) LIKE UPPER('a#b.com'))
=> []
# 2 letter domain name in email without scope
> Member.where('UPPER(email) LIKE UPPER(?)' , "a#bc.com")
Member Load (0.7ms) SELECT "members".* FROM "members" WHERE (UPPER(email) LIKE UPPER('a#bc.com'))
=> []
# 1 letter domain name in email with scope
> Member.with_households.where('UPPER(email) LIKE UPPER(?)' , "a#b.com")
Member Load (0.7ms) SELECT "members".* FROM "members" WHERE (UPPER(email) LIKE UPPER('a#b.com'))
=> []
# 2 letter domain name in email with scope
> Member.with_households.where('UPPER(email) LIKE UPPER(?)' , "a#bs.com")
SQL (0.6ms) SELECT "members"."id" AS t0_r0, "members"."last_name" AS t0_r1, "members"."first_name" AS t0_r2, "members"."household_id" AS t0_r3, "members"."created_at" AS t0_r4, "members"."updated_at" AS t0_r5, "members"."phone1" AS t0_r6, "members"."phone2" AS t0_r
7, "members"."address1" AS t0_r8, "members"."address2" AS t0_r9, "members"."city" AS t0_r10, "members"."state" AS t0_r11, "members"."zip" AS t0_r12, "members"."notes" AS t0_r13, "members"."active" AS t0_r14, "members"."email" AS t0_r15, "households"."id" AS t1_r0, "ho
useholds"."balance" AS t1_r1, "households"."created_at" AS t1_r2, "households"."updated_at" AS t1_r3, "households"."notes" AS t1_r4, "members_households"."id" AS t2_r0, "members_households"."last_name" AS t2_r1, "members_households"."first_name" AS t2_r2, "members_hou
seholds"."household_id" AS t2_r3, "members_households"."created_at" AS t2_r4, "members_households"."updated_at" AS t2_r5, "members_households"."phone1" AS t2_r6, "members_households"."phone2" AS t2_r7, "members_households"."address1" AS t2_r8, "members_households"."ad
dress2" AS t2_r9, "members_households"."city" AS t2_r10, "members_households"."state" AS t2_r11, "members_households"."zip" AS t2_r12, "members_households"."notes" AS t2_r13, "members_households"."active" AS t2_r14, "members_households"."email" AS t2_r15 FROM "members
" LEFT OUTER JOIN "households" ON "households"."id" = "members"."household_id" LEFT OUTER JOIN "members" "members_households" ON "members_households"."household_id" = "households"."id" WHERE (UPPER(email) LIKE UPPER('a#bs.com'))
ActiveRecord::StatementInvalid: PGError: ERROR: column reference "email" is ambiguous
LINE 1: ..."."household_id" = "households"."id" WHERE (UPPER(email) LIK...
Here's the error:
ActiveRecord::StatementInvalid: PGError: ERROR: column reference "email" is ambiguous
A Household has_many Members.
Here's the with_households scope definition:
scope :with_households, :include => [{:household => :members}]
The email domain length may be a red herring, but I couldn't reproduce the error otherwise. Why is Arel doing a bunch of joins in just this case?
Try
Member.with_households.where('UPPER(members.email) LIKE UPPER(?)' , "a#bs.com")
ActiveRecord StatementInvalid is ambiguous is ARs way of saying: Mister, your SQL statement does not make sense because a field you are examining is found on several tables and I don't know which to use.
I'm guessing the with_households scope looks at another table which also has an email field. Or maybe you have a default_scope which does the same. Try specifying the table name everywhere, e.g. members.email and managers.email.
Member.with_households.where(Member.arel_table[:email].matches("a#bs.com"))

ActiveRecord returns model objects with un-initialized associations

I have a simple join query which in some cases returns ActiveRecord objects with uninitialized associations, and I try to understand why. (My setup: rails 2.3.8 with MySQL)
Here are my models:
class Member
has_many :twitter_status_relations
//has some more unrelated associations
end
class TwitterStatus
has_many :twitter_status_relations
end
class TwitterStatusRelation
belongs_to :member
belongs_to :twitter_status
end
And here is the query I perform:
result = TwitterStatusRelation.all(:joins => :twitter_status,
:conditions=>{:twitter_statuses=>{:sent_at=>1.month.ago..DateTime.now}}, :include=>:member,:group=>"twitter_status_relations.member_id")
Now, when I run in it the first time in the app, it works fine:
print result[0].member, result[0].member.class.reflect_on_all_associations(:has_many)
#=> <Member...>, [<ActiveRecord::Reflection::AssociationReflection,...]
BUT, when I run it again, and try accessing any association of the member, I get nil exception. Print shows the following:
print result[0].member, result[0].member.class.reflect_on_all_associations(:has_many)
#=> <Member...>, [-- empty ---]
Looks like the member object doesn't have any associations, and so when I try to access any of it, I get an exception.
Do you have any idea why ActiveRecord wouldn't initialize associations of the returned objects in some cases? I would appreciate any half-idea because I'm stuck.
Here is the SQL the above query produces (Ran posted the question on my behalf). The SQL has more fields then the query, because I simplified the query when posting it, removing conditions that aren't relevant to the problem.
SELECT `twitter_status_relations`.`id` AS t0_r0,
twitter_status_relations.twitter_status_id AS t0_r1,
twitter_status_relations.source_twitter_identity_id AS t0_r2,
twitter_status_relations.relation_type AS t0_r3,
twitter_status_relations.relation_data AS t0_r4,
twitter_status_relations.linked_twitter_identity_id AS t0_r5,
twitter_status_relations.user_id AS t0_r6,
twitter_status_relations.linked_member_id AS t0_r7, members.id
AS t1_r0, members.user_id AS t1_r1, members.name AS t1_r2,
members.email AS t1_r3, members.member_rating AS t1_r4,
members.created_at AS t1_r5, members.updated_at AS t1_r6,
members.merged_with_member_id AS t1_r7, members.engage_rating
AS t1_r8, members.support_rating AS t1_r9,
members.user_engage_rating AS t1_r10,
members.user_support_rating AS t1_r11,
members.influence_rating AS t1_r12, members.twitter_username
AS t1_r13, members.lead_rating AS t1_r14,
members.follow_rating AS t1_r15, members.unfollow_rating AS
t1_r16, members.followers_count AS t1_r17, members.hidden AS
t1_r18 FROM twitter_status_relations LEFT OUTER JOIN members ON
members.id = twitter_status_relations.linked_member_id WHERE
(twitter_status_relations.user_id = 1 AND
twitter_status_relations.relation_type IN(
'mention','reply','received_dm','retweet','link','term','hashtag' )
AND twitter_status_relations.linked_member_id IN(
83995,128457,21421,138316,128455,97475,128453,436231,82236,441208,138564,138337,436223,436222,441093,21194,441088,441092,438998,442752,138331,138327,138325,444897,9277,12,509521,13,15,534511,7606,7447,200,7,4,17200,5,652302,1,5536,18770,652301,214082,150870,436228,81204,436225,662513,138608,138338
)) AND twitter_status_relations.id IN (8304, 26493, 113492, 113638,
1, 6, 41213, 113493, 20, 26173) GROUP BY
twitter_status_relations.linked_member_id ORDER BY
members.member_rating

Rails, scope, OR and joins

I have a scope:
includes(:countries).where("profiles.sector = :sector OR advices.sector = :sector", :sector => sector)
It produces the following SQL:
SELECT `profiles`.* FROM `profiles` INNER JOIN `advices` ON `advices`.`profile_id` = `profiles`.`id` WHERE (profiles.sector = 'Forestry_paper' OR advices.sector = 'Forestry_paper')
(yes I have country in my Profile and in my Country model)
Unfortunately, the OR seems to fail:
it doesn't render a profile having only the proper sector but no related advice. Thoughts?
You are doing an INNER JOIN, so it requires that the profiles have a corresponding advice. Try the following instead:
Profile
.joins("LEFT JOIN advices ON advices.profile_id = profiles.id")
.where("profiles.sector = :sector OR advices.sector = :sector", :sector => sector)
This will also include profiles that have no advices.
You can do outer joins by specifying a where clause with a hash after the includes:
Post.includes(:comments).where(:comments=>{:user_id=>nil})
produces:
Post Load (0.5ms) SELECT "posts"."id" AS t0_r0, "posts"."created_at" AS t0_r1,
"posts"."updated_at" AS t0_r2, "comments"."id" AS t1_r0, "comments"."user_id"
AS t1_r1, "comments"."post_id" AS t1_r2, "comments"."content" AS t1_r3,
"comments"."created_at" AS t1_r4, "comments"."updated_at" AS t1_r5
FROM "posts" LEFT OUTER JOIN "comments" ON "comments"."post_id" = "posts"."id"
WHERE ("comments"."user_id" IS NULL)
Ryan Bigg wrote a helpful blog post about this.
EDIT
Be aware that this technique is more or less a side effect of the way Rails constructs the SQL for eager-loading associations. An explicit LEFT JOIN is more robust, as suggested in the accepted answer.
Check out http://metautonomo.us/projects/metawhere/ for more query goodness...
meta_where is now unmaintained: https://github.com/activerecord-hackery/meta_where
Rails 5 is introducing OR statements:
Rails 5: ActiveRecord OR query

Resources