ruby-on-rails - 多态关联的 PG::UndefinedColumn 错误(仅在控制器中,在控制台中工作)
问题描述
我有一个多态关联,可以在 rails 控制台中正常工作,但无论我如何构造它,从控制器调用时都无法正常工作。
基本代码:
# in property.rb
has_many :property_contacts, as: :property_contactable, dependent: :destroy
has_many :contacts, through: :property_contacts
# in property_contact.rb
belongs_to :contact, optional: true
belongs_to :property_contactable, polymorphic: true, optional: true
# in properties_controller.rb
def show
@property = Property.find(params[:id])
end
# in schema.rb
create_table "property_contacts", force: :cascade do |t|
t.bigint "property_id" # old, before polymorphic relationship added, will remove after data migration
t.bigint "contact_id"
t.string "property_contactable_type"
t.bigint "property_contactable_id"
# ...
end
# and output from psql, just to show that there doesn't appear to be any disconnect between the schema and postgres itself
# project_name_development=# \d property_contacts
# Table "public.property_contacts"
# Column | Type | Collation | Nullable | Default
# ---------------------------+--------------------------------+-----------+----------+-----------------------------------------------
# property_id | bigint | | |
# contact_id | bigint | | |
# # ...
# property_contactable_type | character varying | | |
# property_contactable_id | bigint | | |
在一个视图中,如果我调用@property.property_contacts
,我会收到此错误:
ActiveRecord::StatementInvalid - PG::UndefinedColumn: ERROR: column property_contacts.property_contactable_id does not exist
LINE 1: ...operty_contacts".* FROM "property_contacts" WHERE "property_...
^:
如果我强制查询在控制器本身中运行(使用类似的东西@property_contacts = @property.property_contacts.load
),那么我会得到指向控制器中该行的相同错误。
如果我从查询中省略property_contactable_id
并仅基于该列构建查询property_contactable_type
,则会收到一条错误消息,指出该property_contactable_type
列也不存在。
如果我尝试绕过关联并直接构建查询,像这样,我会得到同样的错误:
# in controller:
@property = Property.find(params[:id])
@property_contacts = PropertyContact.for(@property)
# in property_contact.rb
def self.for(property)
# tried both versions, same result
# where("property_contactable_id = ? AND property_contactable_type LIKE ?", property.id, property.class.name)
# where("property_contacts.property_contactable_id = ? AND property_contacts.property_contactable_type LIKE ?", property.id, property.class.name)
end
但是,当我从 rails 控制台运行它们时,所有这些都运行得很好,例如:
property = Property.find(123)
# both versions work
property_contacts = property.property_contacts
property_contacts = PropertyContact.for(property)
如果我调用to_sql
查询,我得到的输出与控制器中的调用与控制台中的调用略有不同:
# from console:
"SELECT \"property_contacts\".* FROM \"property_contacts\" WHERE \"property_contacts\".\"property_contactable_id\" = 4675010 AND \"property_contacts\".\"property_contactable_type\" = 'Property'"
# from controller:
"SELECT \"property_contacts\".* FROM \"property_contacts\" WHERE (property_contacts.property_contactable_id = 4675010 AND property_contacts.property_contactable_type = 'Property')"
我尝试在我的控制器中运行这些查询的原始 sql 版本并得到相同的错误。我尝试了一些不同的变化:
sql = "SELECT \"property_contacts\".* FROM \"property_contacts\" WHERE \"property_contacts\".\"property_contactable_id\" = #{@property.id} AND \"property_contacts\".\"property_contactable_type\" = 'Property'"
sql = "SELECT property_contacts.* FROM property_contacts WHERE property_contacts.property_contactable_id = #{@property.id} AND property_contacts.property_contactable_type = '#{@property.class.name}' ORDER BY property_contacts.created_at desc"
sql = "SELECT property_contacts.* FROM property_contacts WHERE property_contactable_id = #{@property.id} AND property_contactable_type = '#{@property.class.name}'"
sql = "SELECT property_contacts.* FROM property_contacts WHERE property_contacts.property_contactable_type = '#{@property.class.name}' ORDER BY property_contacts.created_at desc"
sql = "SELECT \"property_contacts\".* FROM \"property_contacts\" WHERE \"property_contacts\".\"property_contactable_id\" = 4675010 AND \"property_contacts\".\"property_contactable_type\" = 'Property'"
@property_contacts = PropertyContact.find_by_sql(sql)
@property_contacts = ActiveRecord::Base.connection.execute(sql)
任何人都可以发现我做错了什么,或者给我其他我可以尝试的建议吗?
解决方案
发现了问题——我正在处理的应用程序带有一个手动多租户模块,而我创建的迁移只是迁移公共模式。它在整个应用程序中并不经常使用,因此很容易忘记它的存在。我通过控制台与公共架构进行交互,但通过 Web 服务器与特定租户的架构(没有我添加的新列)交互。
推荐阅读
- python - 为什么从 IronPython 调用 Python 时命令窗口会闪烁打开和关闭?
- vim - Neovim scp 不提示输入密码
- git - Git fetch 或 Git pull 来更新 Web 服务器上的文件?
- javascript - 如何从javascript中的API字符串中确定多个不同大小的子字符串
- javascript - 使用 Javascript 计算小时和分钟的差异并将结果填充到另一个字段中
- perl - perl 函数定义因未初始化值而失败
- python - 使用 TFLearn 将模型保存和加载为 .pb?
- html - 如何在 div:after 中使用 ng-style?
- python - 如何按字母顺序对用逗号分隔的字符串进行排序,并按成员姓氏的字母顺序排序?
- php - Laravel 5.6 MySQL 服务器已经消失