Active Model Serializers:nil的未定义方法`url_for':NilClass

时间:2014-06-18 09:01:57

标签: ruby-on-rails active-model-serializers

我在我的应用程序中使用active_model_serializers gem来发送高级json响应。它实际上工作正常但是因为我已经安装了这个gem,使用几分钟后,应用程序崩溃,显示上面的错误。

不确定我的代码是否与它有关但不知何故,我还需要发回部分代码。由于它似乎没有得到宝石的支持,我做了一个解决方法:

class AppSerializer < ActiveModel::Serializer

  def render_partial_to_json(options = {})
    partial = options[:partial] || nil
    locals  = options[:locals] || nil

    context = Rails.configuration.paths['app/views']
    view    = ActionView::Base.new(context)

    view.class.class_eval do
      include Rails.application.routes.url_helpers
      include ApplicationHelper
    end

    view.render(
      partial: partial,
      locals: locals
    )
  end
end

然后,在我的序列化器中,我可以这样做:

class ActivitySerializer < AppSerializer

  attributes :id, :kind, :data, :created_at, :html

  has_many :comments
  has_one :user

  def id
    ScatterSwap.hash(object.id)
  end

  def html
    render_partial_to_json(
      partial: 'activities/post',
      locals: { activity: object }
    )
  end
end

此代码工作正常,我将部分视为JSON属性。 奇怪的是,错误在任何页面上逐渐出现。删除它的唯一方法是重新启动服务器。但是,经过几分钟的使用后,问题又回来了。

以下是日志的一部分:

Completed 500 Internal Server Error in 65ms

NoMethodError - undefined method `url_for' for nil:NilClass:
actionpack (4.0.3) lib/action_dispatch/routing/url_for.rb:155:in `url_for'
actionpack (4.0.3) lib/action_view/routing_url_for.rb:83:in `url_for'
turbolinks (2.2.1) lib/turbolinks/xhr_url_for.rb:12:in `url_for_with_xhr_referer'
actionpack (4.0.3) lib/action_dispatch/routing/route_set.rb:234:in `call'
actionpack (4.0.3) lib/action_dispatch/routing/route_set.rb:178:in `call'
actionpack (4.0.3) lib/action_dispatch/routing/route_set.rb:274:in `block (2 levels) in define_url_helper'
app/views/activities/_post.html.haml:2:in `_app_views_activities__post_html_haml__1000109198282705156_2214339020'
actionpack (4.0.3) lib/action_view/template.rb:143:in `block in render'
activesupport (4.0.3) lib/active_support/notifications.rb:161:in `instrument'
actionpack (4.0.3) lib/action_view/template.rb:141:in `render'
actionpack (4.0.3) lib/action_view/renderer/partial_renderer.rb:306:in `render_partial'
actionpack (4.0.3) lib/action_view/renderer/partial_renderer.rb:279:in `block in render'
actionpack (4.0.3) lib/action_view/renderer/abstract_renderer.rb:38:in `block in instrument'
activesupport (4.0.3) lib/active_support/notifications.rb:159:in `block in instrument'
activesupport (4.0.3) lib/active_support/notifications/instrumenter.rb:20:in `instrument'
activesupport (4.0.3) lib/active_support/notifications.rb:159:in `instrument'
actionpack (4.0.3) lib/action_view/renderer/abstract_renderer.rb:38:in `instrument'
actionpack (4.0.3) lib/action_view/renderer/partial_renderer.rb:278:in `render'
actionpack (4.0.3) lib/action_view/renderer/renderer.rb:47:in `render_partial'
actionpack (4.0.3) lib/action_view/helpers/rendering_helper.rb:27:in `render'
haml (4.1.0.beta.1) lib/haml/helpers/action_view_mods.rb:10:in `block in render_with_haml'
haml (4.1.0.beta.1) lib/haml/helpers.rb:89:in `non_haml'

你们中的任何一个人已经面临过类似的事情

编辑:
根据要求,这是我的观点代码:

%article#comment-id-1.comment-item.m-t


= link_to profile_url(activity.user), class: "pull-left thumb-sm avatar" do
  = display_picture_for activity.user, resizing_by: "36x36"
  %span.arrow.left
  %section.comment-body.panel.panel-default
    %header.panel-heading.bg-white
      = link_to profile_url(activity.user) do
        = activity.user.fullname
      %span.text-muted.m-l-sm.pull-right
        %i.fa.fa-clock-o
        = time_ago_in_words activity.created_at
    .panel-body
      %div
        = activity.data[:message]
      .comment-action.m-t-sm
        %a.btn.btn-default.btn-xs.active{"data-toggle" => "class", href: "#"}
          %i.fa.fa-star-o.text-muted.text
          %i.fa.fa-star.text-danger.text-active
          Like
        %a.btn.btn-default.btn-xs{href: "#comment-form"}
          %i.fa.fa-mail-reply.text-muted
          Reply

编辑2:

经过多挖掘后,我发现这段代码:

class AppSerializer < ActiveModel::Serializer

  def render_partial_to_json(options = {})
    partial = options[:partial] || nil
    locals  = options[:locals] || nil

    context = Rails.configuration.paths['app/views']
    view    = ActionView::Base.new(context)

    view.class.class_eval do
      include Rails.application.routes.url_helpers
      include ApplicationHelper
    end

    view.render(
      partial: partial,
      locals: locals
    )
  end
end

当调用覆盖Rails助手和加载库时,会导致整个系统不工作。但是,我该如何解决呢?

1 个答案:

答案 0 :(得分:2)

好的,我终于找到了解决方法。问题确实来自上面帖子中的编辑2 点。

要修复它,因为我已经在我的应用中使用rails_config gem(https://github.com/railsjedi/rails_config),我已经使用它以便能够直接从我的序列化器渲染我的部分而不会破坏Rails魔术自动加载。

首先,我将上下文设置为配置(设置):

# application_controller
class ApplicationController < ActionController::Base
  before_filter :set_context_for_serializer

  def set_context_for_serializer
    Settings.context = self
  end
end

然后,在我的序列化器中,我需要做的就是:

class ApplicationSerializer < ActiveModel::Serializer
  def render_partial_to_json(options = {})
    partial = options[:partial] || nil
    locals  = options[:locals] || nil

    Settings.context.render_to_string(
      partial: partial,
      layout: false,
      formats: :html,
      locals: locals
    )
  end
end

class ActivitySerializer < ApplicationSerializer
  attributes :id, :kind, :data, :created_at, :html

  def html
    render_partial_to_json(
      partial: 'activities/post',
      locals: { activity: object }
    )
  end
end

就是这样,现在它完美无缺。如果你们有其他方式(更像Rails),我会很想知道它。

由于