- xml - AJAX/Jquery XML 解析
- 具有多重继承的 XML 模式
- .net - 枚举序列化 Json 与 XML
- XML 简单类型、简单内容、复杂类型、复杂内容
我正在使用 Rails 2.3.14
UPDATE 3 我在更新 2 中发现的技巧仅适用于关联的首次访问...因此,我将 set_table_name 行粘贴到我的应用程序 Controller 中。这太奇怪了。我希望这得到解决。 =\
更新 2 如果我在我的环境文件底部为麻烦的类手动/恶意/hackily 设置表格,我将不再收到错误。
应用程序/配置/环境.rb:
Page::Template::Content.set_table_name "template_page_contents"
Page::Template::Section.set_table_name "template_page_sections"
为什么我必须这样做?这个特定用例的 rails 是否损坏?
更新:最初在我的 Page::Template::Content 类中调用 set_table_name 时,它似乎不起作用。
但是如果我在使用关联之前调用它,它会起作用...
ap Page::Template::Content.table_name # prints "contents"
Page::Template::Content.set_table_name "template_page_contents"
ap Page::Template::Content.table_name # prints "template_page_contents"
return self.page_template_contents.first # doesn't error after the above is exec'd
原始问题:
TL; DR:我尝试访问一个 has_many 关系,但 Rails 认为 has_many 关系使用的表是不同的表
我遇到了这个错误,当我尝试通过 访问属于
关系。Page::Template
的 Page::Template::Content
时>has_many
Mysql2::Error: Unknown column 'contents.template_page_id' in 'where clause': SELECT * FROM `contents` WHERE (`contents`.template_page_id = 17) LIMIT 1
查看错误日志,我想我需要开始使用一些打印语句来找出为什么 Rails 试图在错误的表中查找关联对象。
gems_path/activerecord-2.3.14/lib/active_record/associations/association_collection.rb:63:in `find'
我刚刚决定打印 @reflection
对象,因为一切似乎都围绕着它发生。这是我的做法:
require "awesome_print" # best console printer (colors, pretty print, etc)
def find(*args) # preexisting method header
ap "-------" # separator so I know when one reflection begins / ends, etc
ap @reflection # object in question
... # rest of the method
在错误之前打印的最后一个“@reflection”:
"-------"
#<ActiveRecord::Reflection::AssociationReflection:0x108d028a8
@collection = true,
attr_reader :active_record = class Page::Template < LibraryItem {...},
attr_reader :class_name = "Page::Template::Content",
attr_reader :klass = class Content < LibraryItem {...},
attr_reader :macro = :has_many,
attr_reader :name = :page_template_contents,
attr_reader :options = {
:foreign_key => "template_page_id",
:class_name => "Page::Template::Content",
:extend => []
},
attr_reader :primary_key_name = "template_page_id",
attr_reader :quoted_table_name = "`contents`"
>
上面的代码块中有几处错误。
:klass should be Page::Template::Content
:name should be :contents
:quoted_table_name should be `contents`
我的模型是如何设置的:
应用/模型/page.rb:
class Page < LibrayItem
belongs_to :template_page, :class_name => "Page::Template"
app/models/page/template.rb
class Page::Template < Library Item
set_table_name "template_pages"
has_many :page_template_contents,
:class_name => "Page::Template::Content",
:foreign_key => "template_page_id"
app/models/page/template/content.rb
class Page::Template::Content
set_table_name "template_page_contents"
belongs_to :template_page,
:class_name => "Page::Template",
:foreign_key => "template_page_id"
class Page::Template
...
return self.page_template_contents.first
协会选择的类(与我上面的页面/模板结构无关):
class Content < LibraryItem
set_table_name "contents"
# no associations to above classes
那么...是什么原因造成的,我该如何解决?
最佳答案
您的问题不是由于 set_table_name 而是由于 Rails 如何在关联中找到目标模型类以及您拥有顶级模型这一事实(内容>) 与嵌套在更深命名空间 (Page::Template::Content) 中的模型共享其名称。奇怪的行为差异很可能是由于在检查关联时实际加载的类存在差异(请记住,默认情况下,在开发模式下,Rails 在首次引用时按需加载模型类)。
当你定义一个关联时(无论你是像你所做的那样明确指定关联的目标模型的类名还是接受默认值),Rails 都必须将目标模型类的名称转换为 Ruby 常量,以便它可以引用该目标类。为此,它在定义关联的模型类上调用 protected 类方法 compute_type。
例如,你有
class Page::Template < LibraryItem
set_table_name "template_pages"
has_many :page_template_contents,
:class_name => "Page::Template::Content",
:foreign_key => "template_page_id"
end
您可以在 Rails 控制台中测试 compute_type 如何为此类工作:
$ ./script/console
Loading development environment (Rails 2.3.14)
> Page::Template.send(:compute_type, "Page::Template::Content")
=> Page::Template::Content(id: integer, template_page_id: integer)
正如我所料,我看到结果是对类 Page::Template::Content 的引用。
但是,如果我重新启动 Rails 控制台,但这次导致模型类 Content 首先加载(通过引用它)然后再试一次,我看到这个(我没有费心创建Content 模型的表格,但这不会改变重要的行为):
$ ./script/console
Loading development environment (Rails 2.3.14)
>> Content # Reference Content class so that it gets loaded
=> Content(Table doesn't exist)
>> Page::Template.send(:compute_type, "Page::Template::Content")
=> Content(Table doesn't exist)
如您所见,这次我得到的是对内容的引用。
那么你能做些什么呢?
嗯,首先,您应该意识到在 Rails 中(当然是在 2.3 中)使用命名空间模型类是一件非常痛苦的事情。在层次结构中组织模型类很好,但它确实会让生活变得更加困难。正如您在上面看到的,如果您在一个命名空间中有一个类与另一个命名空间中的类具有相同的名称,这将变得更加棘手。
如果您仍然想忍受这种情况,我可以提出一些建议。以下其中一项可能会有所帮助:
在开发模式下开启类缓存。这将导致预加载所有模型类,而不是默认情况下按需加载它们。它会使您上面的代码更可预测,但可能会使开发有些不愉快(因为类将不再随每个请求重新加载)。
明确要求关联有问题的类中的依赖类。例如:
class Page::Template < LibraryItem
require 'page/template/content'
set_table_name "template_pages"
has_many :page_template_contents, ...
end
在您知道引用关联类可能出错的类中覆盖 compute_type 方法,以便它无论如何都返回命名空间类。在不更详细地了解您的类层次结构的情况下,我无法就如何执行此操作给出完整的建议,但下面是一个快速而肮脏的示例:
class Page::Template < LibraryItem
set_table_name "template_pages"
has_many :page_template_contents,
:class_name => "Page::Template::Content",
:foreign_key => "template_page_id"
def self.compute_type(type_name)
return Page::Template::Content if type_name == "Page::Template::Content"
super
end
end
关于ruby-on-rails - 如果模型在深层命名空间中,set_table_name 不起作用 - Rails 2.3.14 中的错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11752151/
我在 Mac OSX 10.6.4 上运行 ruby,使用 Ruby 1.8 和 activerecord 2.3.8。我在 NetBeans 6.9 中运行以下代码,但我使用的是 10.6 中的
我正在使用 Rails3 Edge 和 mongoid 2beta6 以及 ruby 1.9.2-head。 如何手动更改表名称,就像 ActiveRecord 的 set_table_name
我正在尝试通过使用 Active Record 连接到 .sqlite 文件来与它交互。我这样做: require 'active_record' # Connect to DB ActiveReco
由于遗留原因,我模型的表存储在同一 MySQL 服务器上的两个不同数据库中。起初我只是使用 establish_connection 在使用它的模型上指定第二个数据库。但是,当我在不同数据库中的两个模
我正在使用 Rails 2.3.14 UPDATE 3 我在更新 2 中发现的技巧仅适用于关联的首次访问...因此,我将 set_table_name 行粘贴到我的应用程序 Controller 中。
我是一名优秀的程序员,十分优秀!