2012-02-23 13 views
9

Tengo una consulta compleja de ActiveRecord que estoy creando con diferentes ámbitos, dependiendo de la selección del usuario. Estoy usando 2 gemas, que parecen ser problemáticas juntas, pero no puedo encontrar quién es el culpable entre: Texto (para la búsqueda completa de Postgresql) (2.0.3) Squeel (para uso de sintaxis de rubí en la consulta de Active Record) squeel (0.9.5) Arel o Active Record mismosRails ActiveRecord :: StatementInvalid: PG :: Error: ERROR: falta la entrada FROM-clause para la tabla

Aquí están mis clases de definiciones:

class Event < ActiveRecord::Base 
    belongs_to :entity, :class_name => "Entity", :foreign_key => :entity_id 
    belongs_to :place, :class_name => "Entity", :foreign_key => :place_id 

class Entity < ActiveRecord::Base 
    has_many :events, :foreign_key => 'entity_id' 
    has_many :events, :foreign_key => 'place_id' 

Y, por último, mi consulta:

Event.joins{entity.outer}.joins{place.outer}.includes(:place).includes(:entity).textsearch('anystring'.downcase) 

* Este es un objeto ActiveRecord :: Relation, cual cr cenizas al llamar con to_a

Esto me da el siguiente error:

ActiveRecord::StatementInvalid: PG::Error: ERROR: missing FROM-clause entry for table "entities_events" 
LINE 1: ... AS t1_r30, "entities"."metro_area_id" AS t1_r31, "entities_... 
                  ^
: SELECT "events"."id" AS t0_r0, "events"."name" AS t0_r1, "events"."start_at" AS t0_r2, "events"."end_at" AS t0_r3, "events"."created_at" AS t0_r4, "events"."updated_at" AS t0_r5, "events"."entity_id" AS t0_r6, "events"."calendar_id" AS t0_r7, "events"."location" AS t0_r8, "events"."facebook_id" AS t0_r9, "events"."updated_time" AS t0_r10, "events"."privacy" AS t0_r11, "events"."venue_id" AS t0_r12, "events"."description" AS t0_r13, "events"."venue_city" AS t0_r14, "events"."venue_country" AS t0_r15, "events"."venue_state" AS t0_r16, "events"."venue_longitude" AS t0_r17, "events"."venue_latitude" AS t0_r18, "events"."yahoo_city" AS t0_r19, "events"."yahoo_country" AS t0_r20, "events"."yahoo_state" AS t0_r21, "events"."yahoo_updated_at" AS t0_r22, "events"."fb_updated_at" AS t0_r23, "events"."source_id" AS t0_r24, "events"."source_type" AS t0_r25, "events"."source_url" AS t0_r26, "events"."status" AS t0_r27, "events"."category" AS t0_r28, "events"."place_id" AS t0_r29, "events"."metro_area_id" AS t0_r30, "entities"."id" AS t1_r0, "entities"."image_url" AS t1_r1, "entities"."created_at" AS t1_r2, "entities"."updated_at" AS t1_r3, "entities"."name" AS t1_r4, "entities"."facebook_id" AS t1_r5, "entities"."link" AS t1_r6, "entities"."website" AS t1_r7, "entities"."company_overview" AS t1_r8, "entities"."mission" AS t1_r9, "entities"."category" AS t1_r10, "entities"."picture" AS t1_r11, "entities"."city" AS t1_r12, "entities"."zip" AS t1_r13, "entities"."country" AS t1_r14, "entities"."street" AS t1_r15, "entities"."state" AS t1_r16, "entities"."events_updated_at" AS t1_r17, "entities"."fblikes_updated_at" AS t1_r18, "entities"."fb_updated_at" AS t1_r19, "entities"."source_url" AS t1_r20, "entities"."source_type" AS t1_r21, "entities"."source_id" AS t1_r22, "entities"."place" AS t1_r23, "entities"."latitude" AS t1_r24, "entities"."longitude" AS t1_r25, "entities"."yahoo_city" AS t1_r26, "entities"."yahoo_state" AS t1_r27, "entities"."yahoo_country" AS t1_r28, "entities"."yahoo_updated_at" AS t1_r29, "entities"."fetched_elements_at" AS t1_r30, "entities"."metro_area_id" AS t1_r31, "entities_events"."id" AS t2_r0, "entities_events"."image_url" AS t2_r1, "entities_events"."created_at" AS t2_r2, "entities_events"."updated_at" AS t2_r3, "entities_events"."name" AS t2_r4, "entities_events"."facebook_id" AS t2_r5, "entities_events"."link" AS t2_r6, "entities_events"."website" AS t2_r7, "entities_events"."company_overview" AS t2_r8, "entities_events"."mission" AS t2_r9, "entities_events"."category" AS t2_r10, "entities_events"."picture" AS t2_r11, "entities_events"."city" AS t2_r12, "entities_events"."zip" AS t2_r13, "entities_events"."country" AS t2_r14, "entities_events"."street" AS t2_r15, "entities_events"."state" AS t2_r16, "entities_events"."events_updated_at" AS t2_r17, "entities_events"."fblikes_updated_at" AS t2_r18, "entities_events"."fb_updated_at" AS t2_r19, "entities_events"."source_url" AS t2_r20, "entities_events"."source_type" AS t2_r21, "entities_events"."source_id" AS t2_r22, "entities_events"."place" AS t2_r23, "entities_events"."latitude" AS t2_r24, "entities_events"."longitude" AS t2_r25, "entities_events"."yahoo_city" AS t2_r26, "entities_events"."yahoo_state" AS t2_r27, "entities_events"."yahoo_country" AS t2_r28, "entities_events"."yahoo_updated_at" AS t2_r29, "entities_events"."fetched_elements_at" AS t2_r30, "entities_events"."metro_area_id" AS t2_r31 FROM "events" LEFT OUTER JOIN "entities" ON "entities"."id" = "events"."entity_id" LEFT OUTER JOIN "entities" "places_events" ON "places_events"."id" = "events"."place_id" WHERE (to_tsvector('english', "events"."name"::text) @@ to_tsquery('english', 'canadiens'::text)) ORDER BY "rank0.11630770538778923" DESC 
    from /Users/guillaumenm/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-3.2.1/lib/active_record/connection_adapters/postgresql_adapter.rb:1106:in `async_exec' 
    from /Users/guillaumenm/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-3.2.1/lib/active_record/connection_adapters/postgresql_adapter.rb:1106:in `exec_no_cache' 
    from /Users/guillaumenm/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-3.2.1/lib/active_record/connection_adapters/postgresql_adapter.rb:650:in `block in exec_query' 
    from /Users/guillaumenm/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-3.2.1/lib/active_record/connection_adapters/abstract_adapter.rb:280:in `block in log' 
    from /Users/guillaumenm/.rvm/gems/ruby-1.9.2-p290/gems/activesupport-3.2.1/lib/active_support/notifications/instrumenter.rb:20:in `instrument' 
    from /Users/guillaumenm/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-3.2.1/lib/active_record/connection_adapters/abstract_adapter.rb:275:in `log' 
    from /Users/guillaumenm/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-3.2.1/lib/active_record/connection_adapters/postgresql_adapter.rb:649:in `exec_query' 
    from /Users/guillaumenm/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-3.2.1/lib/active_record/connection_adapters/postgresql_adapter.rb:1201:in `select' 
    from /Users/guillaumenm/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-3.2.1/lib/active_record/connection_adapters/abstract/database_statements.rb:16:in `select_all' 
    from /Users/guillaumenm/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-3.2.1/lib/active_record/connection_adapters/abstract/query_cache.rb:63:in `select_all' 
    from /Users/guillaumenm/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-3.2.1/lib/active_record/relation/finder_methods.rb:211:in `find_with_associations' 
    from /Users/guillaumenm/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-3.2.1/lib/active_record/relation.rb:170:in `exec_queries' 
    from /Users/guillaumenm/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-3.2.1/lib/active_record/relation.rb:159:in `block in to_a' 
    from /Users/guillaumenm/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-3.2.1/lib/active_record/explain.rb:40:in `logging_query_plan' 
    from /Users/guillaumenm/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-3.2.1/lib/active_record/relation.rb:158:in `to_a' 
    from /Users/guillaumenm/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-3.2.1/lib/active_record/relation.rb:495:in `inspect' 
    from /Users/guillaumenm/.rvm/gems/ruby-1.9.2-p290/gems/railties-3.2.1/lib/rails/commands/console.rb:47:in `start' 
    from /Users/guillaumenm/.rvm/gems/ruby-1.9.2-p290/gems/railties-3.2.1/lib/rails/commands/console.rb:8:in `start' 
    from /Users/guillaumenm/.rvm/gems/ruby-1.9.2-p290/gems/railties-3.2.1/lib/rails/commands.rb:41:in `<top (required)>' 
    from ./script/rails:6:in `require' 

If I call the to_sql method on the query, I get a working SQL statement like this : 
=> "SELECT \"events\".*, ts_rank(to_tsvector('english', \"events\".\"name\"::text), to_tsquery('english', 'canadiens'::text)) AS \"rank0.7148935848557265\" FROM \"events\" LEFT OUTER JOIN \"entities\" ON \"entities\".\"id\" = \"events\".\"entity_id\" WHERE (to_tsvector('english', \"events\".\"name\"::text) @@ to_tsquery('english', 'canadiens'::text)) AND ((\"events\".\"start_at\" >= '2012-02-19T00:00:00+00:00' AND \"events\".\"start_at\" <= '2012-02-25T23:59:59+00:00')) ORDER BY \"rank0.7148935848557265\" DESC" 
  • está activo Grabar y Arel totalmente responsable de implementar la instrucción SQL completa?
  • ¿Por qué to_sql no produce el mismo resultado?
  • Cualquier forma de forzar (sin dar la sintaxis completa OUTER JOIN) el nombre de la combinación?

  • ¿Cómo puedo estar seguro de capturar la pieza problemática para completar el informe de error adecuado? Estoy bastante perdido en mi depurador tratando de encontrar qué fragmento de código escribe la declaración de combinación incorrecta || o la cláusula SELECT incorrecta con el nombre de asociación de unión no válida.

Gracias

Respuesta

5

Después de mucha depuración, me encontré con el problema de ser múltiplos :-(.

En primer lugar, la une fin debe coincidir con el orden incluye. Por lo tanto, las líneas 2, doesn' T producen la misma consulta SQL. nombrando alias son diferentes. creo que esto es un problema Arel registro \ activa que va a marcar.

Event.joins{entity.outer}.joins{place.outer}.includes(:place).includes(:entity) 

es diferente que

Event.joins{entity.outer}.joins{place.outer}.includes(:entity).includes(:place) 

Sin embargo, este problema fue transparente, hasta que agregué otro ámbito para la búsqueda de texto. Mi suposición es porque la declaración de SQL cambió para agregar un alias de columna para cada columna. El alias también usaba el alias de la tabla, que era diferente al de las cláusulas FROM y JOIN.

Sin embargo, al cambiar el orden, no solucioné todos mis problemas. Terminé encontrando otro problema donde la cláusula SELECT de la búsqueda de texto completo de mi texto se arranca de la consulta que va al DB. En su lugar, me sale este error:

ActiveRecord::StatementInvalid: PG::Error: ERROR: column "rank0.8601929506100121" does not exist 
LINE 1: ...o_tsquery('english', 'canadiens'::text)) ORDER BY "rank0.860... 

También creo que esto sea o bien un texticle, squeel o error ActiveRecord/Arel, no está seguro de cuál aún ...

tan doloroso que quiero escribir hasta mis propias declaraciones SQL a mano de nuevo ...

+0

Eso es feo. Estoy golpeando problemas similares. – jevy

+1

Lo que hice fue sacar la parte incluye. Esta es la pieza que arroja declaraciones de selecciones personalizadas. Terminé usando uniones externas izquierdas a través del complemento SQUEEL y escribiendo mis instrucciones select manualmente para mis clases "incluidas". Al final, quería limitar las selecciones para el rendimiento, así que supongo que estoy en el punto en el que quería estar. Entonces, el error, al final, es ActiveRecord :: includes, e indirectamente, Texticle permite incluir al objeto de relación AR. – xlash

+0

Estábamos usando un alcance con nombre que usaba el método arel "where". Lo cambiamos para usar las "condiciones" de la vieja escuela y funcionó bien. Parece un error donde el método de alguna manera. – jevy

16

acabo de tener venga el mismo error para mí, con esta línea de código:

SampleItem.joins(:campaign_market).where(campaign_market: {market_id: current_admin_user.market_id}) 

Mi causa era mucho más simple que la de arriba, joins(:campaign_market) era correcta, ya que es un registro belongs_to/padre Sin embargo:

.where(campaign_market: {market_id: current_admin_user.market_id}) 

debería haber sido:

.where(campaign_markets: {market_id: current_admin_user.market_id}) 

La cláusula .where() siempre quiere el nombre de tabla pluralizada, no el nombre de asociación.

Cuestiones relacionadas