简体   繁体   English

[X,Y,Z] .each {| m |的区别是什么? 包括m}并包括X,Y,Z?

[英]What is the difference between [X,Y,Z].each {|m| include m} and include X, Y, Z?

Note This originally started as a question about 404 errors, but now it's a question why the patch that I applied would make a difference. 注意这最初是作为一个关于404错误的问题开始的,但是现在这是一个问题,为什么我应用的补丁会产生影响。

How do you get a cached action to return a 404 on all requests that raise an ActiveRecord::RecordNotFound exception, not just the first request? 如何获得缓存操作以在所有引发ActiveRecord :: RecordNotFound异常的请求上返回404,而不仅仅是第一个请求?

For example, if you start an empty rails project, add a Product model and controller, setup your database.yml, setup your cache backend in production.rb, rake db:migrate, then start in production and hit the site for a non-existent object, eg http://localhost:3000/product/show/1234 例如,如果你启动一个空的rails项目,添加一个产品模型和控制器,设置你的database.yml,在production.rb中设置你的缓存后端,rake db:migrate,然后开始生产并点击该网站获取非现有对象,例如http:// localhost:3000 / product / show / 1234

class ProductController < ApplicationController

  caches_action :show

  def show
    @product = Product.find(params[:id])
    render :text => "asdf"
  end

end

The first time the page is hit, it returns the 404 page as expected. 第一次点击页面时,它会按预期返回404页面。 However, every subsequent hit to that URL returns a blank page with 200 OK. 但是,对该URL的每次后续匹配都会返回一个200 OK的空白页面。 How do you get it to return 404 every time? 你怎么得到它每次返回404?

Here are the CURL requests, followed by the logs 以下是CURL请求,后跟日志

~ $ curl -I http://0.0.0.0:3000/product/show/1234
HTTP/1.1 404 Not Found
Connection: close
Date: Mon, 20 Apr 2009 22:49:18 GMT
Content-Type: text/html; charset=utf-8
Cache-Control: no-cache
Content-Length: 14097

~ $ curl -I http://0.0.0.0:3000/product/show/1234
HTTP/1.1 200 OK
Connection: close
Date: Mon, 20 Apr 2009 22:49:19 GMT
X-Runtime: 6
Content-Type: text/html; charset=utf-8
Cache-Control: no-cache
Content-Length: 0

The second response is clearly wrong. 第二个反应显然是错误的。

Here is a copy of the log for the 2 requests: 以下是2个请求的日志副本:

Processing ProductController#show (for 127.0.0.1 at 2009-04-20 17:35:24) [GET]
  Parameters: {"id"=>"1234"}

ActiveRecord::RecordNotFound (Couldn't find Product with ID=1234):
  app/controllers/product_controller.rb:6:in `show'

Rendering rescues/layout (not_found)


Processing ProductController#show (for 127.0.0.1 at 2009-04-20 17:35:30) [GET]
  Parameters: {"id"=>"1234"}
Filter chain halted as [#<ActionController::Caching::Actions::ActionCacheFilter:0x23e36d4 @options={:cache_path=>nil, :store_options=>{}, :layout=>nil}>] rendered_or_redirected.
Filter chain halted as [#<ActionController::Filters::AroundFilter:0x23e3580 @kind=:filter, @options={:unless=>nil, :if=>nil, :only=>#<Set: {"show"}>}, @method=#<ActionController::Caching::Actions::ActionCacheFilter:0x23e36d4 @options={:cache_path=>nil, :store_options=>{}, :layout=>nil}>, @identifier=nil>] did_not_yield.
Completed in 12ms (View: 0, DB: 0) | 200 OK [http://0.0.0.0/product/show/1234]

Indeed, if you pull the cached action out of the cache, it has some sort of empty garbage in there. 实际上,如果你将缓存的操作从缓存中拉出来,那里就会有一些空垃圾。

cache.fetch("views/0.0.0.0:3000/product/show/1234")
=> ["", nil, [], []]

What am I doing wrong here? 我在这做错了什么?

Edit 编辑

I've confirmed that Rails 2.1.2 and 2.2.2 don't exhibit this behavior, but 2.3.2 does. 我已经确认Rails 2.1.2和2.2.2没有表现出这种行为,但2.3.2确实如此。 (ie the older versions don't store an empty response into the cache and they indeed throw a 404 for the subsequent requests) (即旧版本不会将空响应存储到缓存中,并且它们确实会为后续请求抛出404)

I'm having trouble testing against edge Rails, because loading it causes the following error when starting the server: foobar/vendor/rails/activesupport/lib/active_support/dependencies.rb:440:in `load_missing_constant': uninitialized constant ActionController::Failsafe (NameError) 我在测试边缘Rails时遇到问题,因为在启动服务器时加载它会导致以下错误:foobar / vendor / rails / activesupport / lib / active_support / dependencies.rb:440:in`load_missing_constant':uninitialized constant ActionController ::故障安全(NameError)

I've tested against the current head of the 2-3-stable branch, 375e8976e3, and it too exhibits this behavior. 我已经对2-3稳定分支375e8976e3的当前负责人进行了测试,它也表现出这种行为。

Edit #2 I attempted to track down when the change occurred in the Rails codebase to determine if it was intentional. 编辑#2我试图跟踪Rails代码库中发生更改的时间,以确定它是否是故意的。 It seems that this seemingly innocuous commit is where the bug starts. 似乎这个看似无害的提交是bug开始的地方。

Here are the details of the bisection, where 404 denotes the desired behavior, 200 being undesired. 以下是二分的细节,其中404表示期望的行为,200表示不期望的行为。

2-3-stable branch
    375e8976e3 - 200
    b1c989f28d - 200
    beca1f2e15 - 200
    f1fff0a48  - 200
    f1e20ce9a7 - 200
    a5004573d8 - 200
    2e1132fad8 - 200 - the difference seems to start at this commit
    c69d8c043f - 404
    d961592886 - 404
    276ec16007 - 404
    0efec6452  - 404
    13c6c3cfc5 - 404
    fb2325e35  - 404

2-2 stable
    3cb89257b4 - 404

Here is a patch that reverses the change, which when applied to tag v2.3.2.1, ie dc88847e5ce392eed210b97525c14fca55852867, fixes the problem. 这是一个反转更改的补丁,当应用于标记v2.3.2.1,即dc88847e5ce392eed210b97525c14fca55852867时,修复了该问题。 I, however, am not smart enough to fathom why this seemingly small change would actually make a difference! 然而,我不够聪明,不知道为什么这个看似微不足道的变化实际上会有所作为! Perhaps someone smarter than me could shed some light on the situation? 也许比我聪明的人可以对这种情况有所了解?

diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb
index 0facf70..0790807 100644
--- a/actionpack/lib/action_controller/base.rb
+++ b/actionpack/lib/action_controller/base.rb
@@ -1403,12 +1403,9 @@ module ActionController #:nodoc:
   end

   Base.class_eval do
-    [ Filters, Layout, Benchmarking, Rescue, Flash, MimeResponds, Helpers,
-      Cookies, Caching, Verification, Streaming, SessionManagement,
-      HttpAuthentication::Basic::ControllerMethods, HttpAuthentication::Digest::ControllerMethods,
-      RecordIdentifier, RequestForgeryProtection, Translation
-    ].each do |mod|
-      include mod
-    end
+    include Filters, Layout, Benchmarking, Rescue, Flash, MimeResponds, Helpers
+    include Cookies, Caching, Verification, Streaming, SessionManagement
+    include HttpAuthentication::Basic::ControllerMethods, HttpAuthentication::Digest::ControllerMethods
+    include RecordIdentifier, RequestForgeryProtection, Translation
   end
 end

Edit #3 The patch seems to also fix the related bug, showcased above, where the "Completed in XYms (DB: Z) | 404 Not Found [ http://0.0.0.0/product/1234] " did not show up in the log. 编辑#3补丁似乎也修复了上面显示的相关错误,其中“在XYms中完成(DB:Z)| 404找不到[ http://0.0.0.0/product/1234] ”没有显示在日志。

Edit #4 The above patch broke other things in ActionPack, so I delved in and generated a fix for the issue that doesn't cause collateral damage. 编辑#4上面的补丁破坏了ActionPack中的其他内容,因此我深入研究并生成了一个不会导致附带损害的问题。 The patch and any subsequent updates will be at the rails lighthouse 补丁和任何后续更新将在轨道灯塔

It appears that include(X, Y, Z) actually operates in a different order than include X; include Y; include Z 似乎include(X, Y, Z)实际上以与include X; include Y; include Z不同的顺序操作include X; include Y; include Z include X; include Y; include Z include X; include Y; include Z . include X; include Y; include Z

Below I've pasted the C code that implements the Module#include method in Ruby 1.8.6. 下面我粘贴了在Ruby 1.8.6中实现Module#include方法的C代码。

static VALUE
rb_mod_include(argc, argv, module)
    int argc;
    VALUE *argv;
    VALUE module;
{
    int i;

    for (i=0; i<argc; i++) Check_Type(argv[i], T_MODULE);
    while (argc--) {
      rb_funcall(argv[argc], rb_intern("append_features"), 1, module);
      rb_funcall(argv[argc], rb_intern("included"), 1, module);
    }
    return module;
}

Even if you're not familiar with Ruby's C internals, it's pretty clear that this function has a for loop iterating upward to check that the type of all the arguments is T_MODULE, and then uses a while loop iterating downward to actually include the modules - so the modules in include(X, Y, Z) would actually be included in the order Z, Y, X . 即使你不熟悉Ruby的C内部,很明显这个函数有一个for循环向上迭代来检查所有参数的类型是否为T_MODULE,然后使用while循环向下迭代以实际包含模块 - 因此, include(X, Y, Z)的模块实际上将包括在Z, Y, X的顺序中。 I haven't gone through all the Rails modules in question, but I imagine there's something order-dependent that started failing once the include order was switched around. 我还没有浏览过所有相关的Rails模块,但我想有一些依赖于顺序的东西,一旦切换包含顺序就开始失败了。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 模型X和模型Y每个has_many Z,:dependent =&gt;:destroy。 如果我摧毁X,Z会被摧毁吗? - Model X and Model Y each has_many Z, :dependent => :destroy. If I destroy X, does Z get destroyed? 如何创建{x = y | y = z | z = 0}从哈希动态阻止? - How to create { x = y | y = z | z = 0 } block dynamically from hash? 如何查询 ActiveRecord 以仅返回每个 object 的第一个实例,其中 enum = X、Y、Z? - How do I query ActiveRecord to return only the first instance of each object where enum = X, Y, Z? rails:获取标记为x AND y AND z的所有项目 - rails: Get all items tagged x AND y AND z 如何在ActiveRecord准备好的语句中使ruby数组为ax,y,z - how to make a ruby array be a x,y,z in an ActiveRecord prepared statement Z = X + Y时如何防止堆叠顺序? X总是在最前面 - how to prevent stacked ordering when I do Z=X+Y? X is always on top Ruby语法:x(&#39;foo&#39;,y:&#39;bar&#39;,z:&#39;baz&#39;)是否可以不同于x(&#39;foo&#39;,@yz)? - Ruby syntax: can x('foo', y: 'bar', z: 'baz') differ from x('foo', @yz)? / it /和/ \ Ait \ Z /有什么区别 - What is the difference between /it/ and /\Ait\Z/ 会话未创建例外:使用Selenium Webdriver和Chrome时,Chrome版本必须&gt; = xyz - Session not created exception: Chrome version must be >= x.y.z when using Selenium Webdriver with Chrome Ruby:now.strftime(“%a,%d%b%Y%X%z”)给出了错误的时间 - Ruby: now.strftime(“%a, %d %b %Y %X %z”) gives wrong time
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM