为什么文件存在时偶尔会发生丢失的部分错误?

时间:2016-02-01 14:06:19

标签: ruby-on-rails

在运行Cucumber测试时,它会不时地间歇性地失败。错误是:

*** ActionView::Template::Error Exception: Missing partial items/_fields with {:locale=>[:en], :formats=>[:html], :variants=>[], :handlers=>[:erb, :builder, :raw, :ruby, :coffee, :haml]}. Searched in:
  * "/my/path/to/application/app/views"
  * "/my/path/to/rvm/gems/ruby-2.1.5/gems/kaminari-0.16.3/app/views"
  * "/my/path/to/rvm/gems/ruby-2.1.5/gems/devise-3.5.4/app/views" 

是的,部分文件确实存在于/my/path/to/application/app/views/items/_fields.html.haml

踢球者有时候测试会通过,有时候会失败。我在Red Hat 5机器上运行。

所以为了调试这个,我决定投入一个begin/rescue

.fields
  - begin
    = render partial: 'items/fields', locals: {f: f}
  - rescue Exception => e
    = byebug

  - if f.can_modify?(:object_a)
    = render partial: 'layouts/object_a_field', locals: {f: f, field: :object_a}
   - else
    .field#object_a
      = render partial: 'layouts/attribute', locals: {label: 'Object A', value: f.object.object_a_id ? f.object.object_a_number : 'Not Assigned'}

    .field#name
    - if f.can_modify?(:name)
      = f.label :name
      = f.text_field :name, {class: 'inputbox large_field', readonly: f.cannot_modify?(:name)}
      .smltxt (short description of the item)
    - else
      = render partial: 'layouts/attribute', object: f.object, locals: {field: :name}

对于那些好奇的部分items/fields

.field
  - if f.can_modify?(:name)
    = f.label :name, 'Item'
    = f.text_field :name, {class: 'inputbox uppercase', maxlength: 16, readonly: !f.object.identifier.new_record?}
    .smltxt (character identifier)
  - else
    = render partial: 'layouts/attribute', object: f.object, locals: {field: :name, label: 'Item'}

当它通过时,我显然没有击中旁路,但是当它失败时,我会这样做!这允许我在Rails控制台类型环境中使用它。

所以我决定运行那个特定的命令:

(byebug) render partial: 'items/fields', locals: {f: f}

我得到了:

*** ActionView::Template::Error Exception: Missing partial items/_fields with {:locale=>[:en], :formats=>[:html], :variants=>[], :handlers=>[:erb, :builder, :raw, :ruby, :coffee, :haml]}. Searched in:
  * "/my/path/to/application/app/views"
  * "/my/path/to/rvm/gems/ruby-2.1.5/gems/kaminari-0.16.3/app/views"
  * "/my/path/to/rvm/gems/ruby-2.1.5/gems/devise-3.5.4/app/views" 

所以我想我会删除当地人以查看是否有任何改变:

(byebug) render partial: 'items/fields'

我得到了:

*** ActionView::Template::Error Exception: undefined local variable or method `f' for #<#<Class:0x0000002a907610>:0x00000027beae48>

很明显,它现在神奇地找到了局部变量,它知道它缺少一个局部变量f

更新1

为了清楚起见,我添加了上面调用部分视图的其余视图。

在尝试进行故障排除时,我还将items/_fields.html.haml的内容放在我render partial: 'items/fields', locals: {f: f}的位置...然后测试通过,这意味着文件中的其他部分没有也没问题。因此,它似乎与文件的内容无关。

更新2

似乎通过将@javascript标记添加到我们的第一个Cucumber功能中,通常可以解决此问题。以某种方式在其他测试之前加载浏览器,提高了传递的机会。对我没有任何意义,也许其他人对此有所了解?

更新3

今天发现这个错误根本与黄瓜无关。在生产中发现了同样的错误。 Web界面显示Missing Partial错误,但对于确实存在的文件。使用touch tmp/restart.txt重新启动Passenger服务器后,错误消失了。所以它仍然是非常间歇性的。

更新4

我添加了似乎随机丢失的部分内容。

我如何去发现为什么Rails找不到实际存在的部分?

6 个答案:

答案 0 :(得分:1)

当请求的格式不同且没有可以响应它的模板示例format.jsformat.html等时,通常会发生此错误。请求仅在模板{{1如果请求格式是html

,它只会是正确的

如果您想使用任何请求格式回复,我认为您可以将文件重命名为items/_fields.html.haml

答案 1 :(得分:0)

我认为您可以尝试指定要渲染的部分格式和处理程序:

= render(
  partial: 'items/fields',
  formats:  [:html],
  handlers: [:haml],
  locals: {f: f}
)

答案 2 :(得分:0)

我有一个类似的问题,但有另一个手柄的宝石。通常是因为缓存。

尝试黄瓜设置设置

ActionView::Base.cache_template_loading = false

如果上述情况有效,则 DO 会在制作时出现缓存问题。

在此处存在未在启用模式下启用缓存的问题:https://github.com/indirect/haml-rails/search?utf8=%E2%9C%93&q=cache_template_loading

答案 3 :(得分:0)

Rails中最常用的内容类型是:js:json:html。如果您使用的是Rails UJS,则可以在链接或表单元素中指定内容类型。一个例子如下:

<%= form_for @task, remote: true, data: {'type' => :json} %>
  ...

在我们的控制器中,我们会做出相应的回应:

def create
  respond_to do |format|
    format.json { render json: { status: 200, html: render_to_string(partial: 'form') }.to_json }
  end
end

现在,如果您的表单部分如下:

tasks/_form.html.erb

Rails会引发一个ActionView :: Template :: Error异常:缺少部分。您将内容类型指定为json,因此它正在搜索:

tasks/_form.json.erb

现在,如果您将表单更改为:

<%= form_for @task, remote: true, data: {'type' => :html} %>
  ...

这样的控制器:

def create
  respond_to do |format|
    format.html { render text: { status: 200, html: render_to_string(partial: 'form') } }
  end
end

您甚至可以在html内容类型响应中呈现json:

def create
  respond_to do |format|
    format.html { render json: { status: 200, html: render_to_string(partial: 'form') }.to_json }
  end
end

然后在javascript中:

JSON.parse(data);

上面的scenerio可以正常工作,因为它会在渲染的调用中搜索html文件扩展名。 这是重要的一部分。对render的调用是引发错误的原因。使用渲染时,必须确保拥有与内容类型匹配的模板或部分

上面提到的一个解决方案是删除扩展名。但除非你对多种格式做出回应,否则看起来有点矫枉过正。我推荐的解决方案是查看错误消息告诉您的预期。在你的情况下,它期待html:

:formats=>[:html]

答案 4 :(得分:0)

我坚信升级到Ruby 2.3.1为我们解决了这个问题。我不确定可能会有什么变化。当我们调查这个时,我的同事和我认为我们在Rails源代码中找到了一条基于Ruby版本不同地呈现部分内容的行。

我现在很难找到,但我仍然想发布自从我们升级到更新的Ruby以来问题似乎已经消失。

答案 5 :(得分:0)

尝试从您的终端访问该文件以查看其是否可用。 如果您无法在终端上找到它,请在文本编辑器中转到您的应用文件夹,然后手动将其删除。

然后,使用终端再次创建它。

即使文件在文本编辑器中可见,它似乎也不可读,但是从终端访问该文件时却不可见。

出于某种奇怪的原因,这行得通。

注意:同样适用于文件夹