ActiveRecord :: StatementInvalid,PG :: UndefinedTable错误,但生成的SQL有效

时间:2018-08-13 19:35:35

标签: ruby-on-rails postgresql

这真令人沮丧。我正在尝试通过工作获得has_many,但我认为我离此太近了,看不到超级明显的东西。每个步骤都可以正常运行,Rails生成的SQL可以正常运行,但是在控制台中却不能。

关于整个设置的一件奇怪的事情是,在salesforce模式中有几个表,并且表名和主键不是标准的。基本结构如下:

class Contact
  self.table_name =  'salesforce.contact'
  self.primary_key = 'sfid'

  has_many :content_accesses
  has_many :inventories, through: :content_accesses # I've tried inventory and inventorys, just to ensure it's not Rails magic
end


class ContentAccess
  belongs_to :inventory
  belongs_to :contact
end


class Inventory
  self.table_name =  'salesforce.inventory__c'
  self.primary_key = 'sfid'

  has_many :content_accesses, foreign_key: 'inventory_id'
end

作品:

c = Contact.first
c.content_accesses # works, gives the related items

c.content_accesses.first.inventory # works, gives the related Inventory item

错误:

c.inventories # Gives:

# ActiveRecord::StatementInvalid (PG::UndefinedTable: ERROR:  relation "content_accesses" does not exist)
# LINE 1: ..._c".* FROM "salesforce"."inventory__c" INNER JOIN "content_a...
#                                                          ^
# : SELECT  "salesforce"."inventory__c".* FROM "salesforce"."inventory__c" INNER JOIN "content_accesses" ON "salesforce"."inventory__c"."sfid" = "content_accesses"."inventory_id" WHERE "content_accesses"."contact_id" = $1 LIMIT $2

但是,当我通过Postico运行该查询时,它运行良好。

编辑后添加:

  • 我将content_accesses移入了salesforce模式,并在模型上正确设置了self.table_name,但是问题仍然存在。因此,我认为这与跨模式无关。
  • 那只会让我觉得这个问题很奇怪。 :(

表的DDL:

CREATE TABLE salesforce.inventory__c (
    createddate timestamp without time zone,
    isdeleted boolean,
    name character varying(80),
    systemmodstamp timestamp without time zone,
    inventory_unique_name__c character varying(255),
    sfid character varying(18),
    id integer DEFAULT nextval('salesforce.inventory__c_id_seq'::regclass) PRIMARY KEY,
    _hc_lastop character varying(32),
    _hc_err text
);

CREATE UNIQUE INDEX inventory__c_pkey ON salesforce.inventory__c(id int4_ops);
CREATE INDEX hc_idx_inventory__c_systemmodstamp ON salesforce.inventory__c(systemmodstamp timestamp_ops);
CREATE UNIQUE INDEX hcu_idx_inventory__c_sfid ON salesforce.inventory__c(sfid text_ops);


CREATE TABLE salesforce.contact (
    lastname character varying(80),
    mailingpostalcode character varying(20),
    accountid character varying(18),
    assistantname character varying(40),
    name character varying(121),
    mobilephone character varying(40),
    birthdate date,
    phone character varying(40),
    mailingstreet character varying(255),
    isdeleted boolean,
    assistantphone character varying(40),
    systemmodstamp timestamp without time zone,
    mailingstatecode character varying(10),
    createddate timestamp without time zone,
    mailingcity character varying(40),
    salutation character varying(40),
    title character varying(128),
    mailingcountrycode character varying(10),
    firstname character varying(40),
    email character varying(80),
    sfid character varying(18),
    id integer DEFAULT nextval('salesforce.contact_id_seq'::regclass) PRIMARY KEY,
    _hc_lastop character varying(32),
    _hc_err text
);

CREATE UNIQUE INDEX contact_pkey ON salesforce.contact(id int4_ops);
CREATE INDEX hc_idx_contact_systemmodstamp ON salesforce.contact(systemmodstamp timestamp_ops);
CREATE UNIQUE INDEX hcu_idx_contact_sfid ON salesforce.contact(sfid text_ops);

CREATE TABLE content_accesses (
    id BIGSERIAL PRIMARY KEY,
    inventory_id character varying(20),
    contact_id character varying(20),
    created_at timestamp without time zone NOT NULL,
    updated_at timestamp without time zone NOT NULL
);

CREATE UNIQUE INDEX content_accesses_pkey ON content_accesses(id int8_ops);

编辑2:作为调试的一部分,我尝试在控制台中运行生成的查询:

  • 如果我使用ActiveRecord::Base.connection.execute运行生成的查询,则查询有效。
  • 如果我通过Contact.connection.execute运行它,则会出现相同的错误。

感觉Rails没弄清楚什么,但是我不知道在哪里,为什么或什么。

编辑3:根据要求,框架跟踪:

activerecord (5.2.0) lib/active_record/connection_adapters/postgresql_adapter.rb:669:in `prepare'
activerecord (5.2.0) lib/active_record/connection_adapters/postgresql_adapter.rb:669:in `block in prepare_statement'
/Users/timsullivan/.rvm/rubies/ruby-2.5.1/lib/ruby/2.5.0/monitor.rb:226:in `mon_synchronize'
activerecord (5.2.0) lib/active_record/connection_adapters/postgresql_adapter.rb:664:in `prepare_statement'
activerecord (5.2.0) lib/active_record/connection_adapters/postgresql_adapter.rb:609:in `exec_cache'
activerecord (5.2.0) lib/active_record/connection_adapters/postgresql_adapter.rb:592:in `execute_and_clear'
activerecord (5.2.0) lib/active_record/connection_adapters/postgresql/database_statements.rb:81:in `exec_query'
activerecord (5.2.0) lib/active_record/connection_adapters/abstract/database_statements.rb:469:in `select_prepared'
activerecord (5.2.0) lib/active_record/connection_adapters/abstract/database_statements.rb:55:in `select_all'
activerecord (5.2.0) lib/active_record/connection_adapters/abstract/query_cache.rb:101:in `select_all'
activerecord (5.2.0) lib/active_record/querying.rb:41:in `find_by_sql'
activerecord (5.2.0) lib/active_record/relation.rb:554:in `block in exec_queries'
activerecord (5.2.0) lib/active_record/relation.rb:578:in `skip_query_cache_if_necessary'
activerecord (5.2.0) lib/active_record/relation.rb:542:in `exec_queries'
activerecord (5.2.0) lib/active_record/association_relation.rb:34:in `exec_queries'
activerecord (5.2.0) lib/active_record/relation.rb:414:in `load'
activerecord (5.2.0) lib/active_record/relation.rb:200:in `records'
activerecord (5.2.0) lib/active_record/relation.rb:195:in `to_ary'
activerecord (5.2.0) lib/active_record/relation/finder_methods.rb:530:in `find_nth_with_limit'
activerecord (5.2.0) lib/active_record/associations/collection_proxy.rb:1136:in `find_nth_with_limit'
activerecord (5.2.0) lib/active_record/relation/finder_methods.rb:515:in `find_nth'
activerecord (5.2.0) lib/active_record/relation/finder_methods.rb:125:in `first'
actionview (5.2.0) lib/action_view/template.rb:159:in `block in render'
activesupport (5.2.0) lib/active_support/notifications.rb:170:in `instrument'
actionview (5.2.0) lib/action_view/template.rb:354:in `instrument_render_template'
actionview (5.2.0) lib/action_view/template.rb:157:in `render'
actionview (5.2.0) lib/action_view/renderer/template_renderer.rb:54:in `block (2 levels) in render_template'
actionview (5.2.0) lib/action_view/renderer/abstract_renderer.rb:44:in `block in instrument'
activesupport (5.2.0) lib/active_support/notifications.rb:168:in `block in instrument'
activesupport (5.2.0) lib/active_support/notifications/instrumenter.rb:23:in `instrument'
activesupport (5.2.0) lib/active_support/notifications.rb:168:in `instrument'
actionview (5.2.0) lib/action_view/renderer/abstract_renderer.rb:43:in `instrument'
actionview (5.2.0) lib/action_view/renderer/template_renderer.rb:53:in `block in render_template'
actionview (5.2.0) lib/action_view/renderer/template_renderer.rb:61:in `render_with_layout'
actionview (5.2.0) lib/action_view/renderer/template_renderer.rb:52:in `render_template'
actionview (5.2.0) lib/action_view/renderer/template_renderer.rb:16:in `render'
actionview (5.2.0) lib/action_view/renderer/renderer.rb:44:in `render_template'
actionview (5.2.0) lib/action_view/renderer/renderer.rb:25:in `render'
actionview (5.2.0) lib/action_view/rendering.rb:103:in `_render_template'
actionpack (5.2.0) lib/action_controller/metal/streaming.rb:219:in `_render_template'
actionview (5.2.0) lib/action_view/rendering.rb:84:in `render_to_body'
actionpack (5.2.0) lib/action_controller/metal/rendering.rb:52:in `render_to_body'
actionpack (5.2.0) lib/action_controller/metal/renderers.rb:142:in `render_to_body'
actionpack (5.2.0) lib/abstract_controller/rendering.rb:25:in `render'
actionpack (5.2.0) lib/action_controller/metal/rendering.rb:36:in `render'
actionpack (5.2.0) lib/action_controller/metal/instrumentation.rb:46:in `block (2 levels) in render'
activesupport (5.2.0) lib/active_support/core_ext/benchmark.rb:14:in `block in ms'
/Users/timsullivan/.rvm/rubies/ruby-2.5.1/lib/ruby/2.5.0/benchmark.rb:308:in `realtime'
activesupport (5.2.0) lib/active_support/core_ext/benchmark.rb:14:in `ms'
actionpack (5.2.0) lib/action_controller/metal/instrumentation.rb:46:in `block in render'
actionpack (5.2.0) lib/action_controller/metal/instrumentation.rb:87:in `cleanup_view_runtime'
activerecord (5.2.0) lib/active_record/railties/controller_runtime.rb:31:in `cleanup_view_runtime'
actionpack (5.2.0) lib/action_controller/metal/instrumentation.rb:45:in `render'
actionpack (5.2.0) lib/action_controller/metal/implicit_render.rb:35:in `default_render'
actionpack (5.2.0) lib/action_controller/metal/basic_implicit_render.rb:6:in `block in send_action'
actionpack (5.2.0) lib/action_controller/metal/basic_implicit_render.rb:6:in `tap'
actionpack (5.2.0) lib/action_controller/metal/basic_implicit_render.rb:6:in `send_action'
actionpack (5.2.0) lib/abstract_controller/base.rb:194:in `process_action'
actionpack (5.2.0) lib/action_controller/metal/rendering.rb:30:in `process_action'
actionpack (5.2.0) lib/abstract_controller/callbacks.rb:42:in `block in process_action'
activesupport (5.2.0) lib/active_support/callbacks.rb:132:in `run_callbacks'
actionpack (5.2.0) lib/abstract_controller/callbacks.rb:41:in `process_action'
actionpack (5.2.0) lib/action_controller/metal/rescue.rb:22:in `process_action'
actionpack (5.2.0) lib/action_controller/metal/instrumentation.rb:34:in `block in process_action'
activesupport (5.2.0) lib/active_support/notifications.rb:168:in `block in instrument'
activesupport (5.2.0) lib/active_support/notifications/instrumenter.rb:23:in `instrument'
activesupport (5.2.0) lib/active_support/notifications.rb:168:in `instrument'
actionpack (5.2.0) lib/action_controller/metal/instrumentation.rb:32:in `process_action'
actionpack (5.2.0) lib/action_controller/metal/params_wrapper.rb:256:in `process_action'
activerecord (5.2.0) lib/active_record/railties/controller_runtime.rb:24:in `process_action'
actionpack (5.2.0) lib/abstract_controller/base.rb:134:in `process'
actionview (5.2.0) lib/action_view/rendering.rb:32:in `process'
actionpack (5.2.0) lib/action_controller/metal.rb:191:in `dispatch'
actionpack (5.2.0) lib/action_controller/metal.rb:252:in `dispatch'
actionpack (5.2.0) lib/action_dispatch/routing/route_set.rb:52:in `dispatch'
actionpack (5.2.0) lib/action_dispatch/routing/route_set.rb:34:in `serve'
actionpack (5.2.0) lib/action_dispatch/journey/router.rb:52:in `block in serve'
actionpack (5.2.0) lib/action_dispatch/journey/router.rb:35:in `each'
actionpack (5.2.0) lib/action_dispatch/journey/router.rb:35:in `serve'
actionpack (5.2.0) lib/action_dispatch/routing/route_set.rb:840:in `call'
warden (1.2.7) lib/warden/manager.rb:36:in `block in call'
warden (1.2.7) lib/warden/manager.rb:35:in `catch'
warden (1.2.7) lib/warden/manager.rb:35:in `call'
rack (2.0.5) lib/rack/tempfile_reaper.rb:15:in `call'
rack (2.0.5) lib/rack/etag.rb:25:in `call'
rack (2.0.5) lib/rack/conditional_get.rb:25:in `call'
rack (2.0.5) lib/rack/head.rb:12:in `call'
actionpack (5.2.0) lib/action_dispatch/http/content_security_policy.rb:18:in `call'
rack (2.0.5) lib/rack/session/abstract/id.rb:232:in `context'
rack (2.0.5) lib/rack/session/abstract/id.rb:226:in `call'
actionpack (5.2.0) lib/action_dispatch/middleware/cookies.rb:670:in `call'
activerecord (5.2.0) lib/active_record/migration.rb:559:in `call'
actionpack (5.2.0) lib/action_dispatch/middleware/callbacks.rb:28:in `block in call'
activesupport (5.2.0) lib/active_support/callbacks.rb:98:in `run_callbacks'
actionpack (5.2.0) lib/action_dispatch/middleware/callbacks.rb:26:in `call'
actionpack (5.2.0) lib/action_dispatch/middleware/executor.rb:14:in `call'
airbrake (7.2.1) lib/airbrake/rack/middleware.rb:52:in `call'
actionpack (5.2.0) lib/action_dispatch/middleware/debug_exceptions.rb:61:in `call'
web-console (3.6.1) lib/web_console/middleware.rb:135:in `call_app'
web-console (3.6.1) lib/web_console/middleware.rb:30:in `block in call'
web-console (3.6.1) lib/web_console/middleware.rb:20:in `catch'
web-console (3.6.1) lib/web_console/middleware.rb:20:in `call'
actionpack (5.2.0) lib/action_dispatch/middleware/show_exceptions.rb:33:in `call'
railties (5.2.0) lib/rails/rack/logger.rb:38:in `call_app'
railties (5.2.0) lib/rails/rack/logger.rb:26:in `block in call'
activesupport (5.2.0) lib/active_support/tagged_logging.rb:71:in `block in tagged'
activesupport (5.2.0) lib/active_support/tagged_logging.rb:28:in `tagged'
activesupport (5.2.0) lib/active_support/tagged_logging.rb:71:in `tagged'
railties (5.2.0) lib/rails/rack/logger.rb:26:in `call'
sprockets-rails (3.2.1) lib/sprockets/rails/quiet_assets.rb:13:in `call'
actionpack (5.2.0) lib/action_dispatch/middleware/remote_ip.rb:81:in `call'
actionpack (5.2.0) lib/action_dispatch/middleware/request_id.rb:27:in `call'
rack (2.0.5) lib/rack/method_override.rb:22:in `call'
rack (2.0.5) lib/rack/runtime.rb:22:in `call'
activesupport (5.2.0) lib/active_support/cache/strategy/local_cache_middleware.rb:29:in `call'
actionpack (5.2.0) lib/action_dispatch/middleware/executor.rb:14:in `call'
actionpack (5.2.0) lib/action_dispatch/middleware/static.rb:127:in `call'
rack (2.0.5) lib/rack/sendfile.rb:111:in `call'
webpacker (3.4.3) lib/webpacker/dev_server_proxy.rb:18:in `perform_request'
rack-proxy (0.6.4) lib/rack/proxy.rb:57:in `call'
railties (5.2.0) lib/rails/engine.rb:524:in `call'
puma (3.11.4) lib/puma/configuration.rb:225:in `call'
puma (3.11.4) lib/puma/server.rb:632:in `handle_request'
puma (3.11.4) lib/puma/server.rb:446:in `process_client'
puma (3.11.4) lib/puma/server.rb:306:in `block in run'
puma (3.11.4) lib/puma/thread_pool.rb:120:in `block in spawn_thread'

2 个答案:

答案 0 :(得分:1)

正如您所说,当您直接调用生成的SQL时,它就会起作用,问题根位于将返回的数据映射回对象的过程中的某个位置。 即使您的设置看起来不错,也似乎是非标准的,所以我会尝试为Rails提供更多有关关联如何相互关联的提示。

首先,应为source关系(docs)设置一个through

has_many :inventories, through: :content_accesses, source: :inventory

如果仍然不能提供正确的线索,则可以尝试在另一个inverse_of上设置foreign_keyprimary_keyclass_name甚至belongs_tohas_many关联,以向rails提供所需的提示。很难说出什么可能有用,但是在非标准设置中,您有时会遇到自动推断名称的某些问题。

答案 1 :(得分:0)

令人尴尬的是,这是一个配置问题。 salesforce模式的内容是从服务器而不是从本地数据库加载的。这是我不希望再次检查的一件事,并且本地salesforce架构的内容有效,因为我已经从服务器还原了备份。

为我的本地Postgres服务器设置适当的HEROKUCONNECT_URL可以解决此问题,尽管我可以通过将ContentAccess的表移到Salesforce中,然后从服务器创建数据库的新副本以供本地使用来解决此问题。

如果您想进一步嘲笑我的愚蠢,可以check out the followup question,我是PBKAC的一个不同但相似的例子。