2

この特定の方法により、アプリケーションが破損します。

# needed becasuse of a rails bug
def to_s
  "#{self.class.name.underscore}__#{object_id}"
end  

次のエラーが発生します。

ActionView::TemplateError (`@content_for_details_view_builder__2234321380' is not allowed as an instance variable name) in app/views/shared/_details_view.haml:

基本的に、上記の例外につながるコードの実行は次のとおりです。

# controller
def new
  @view_mode = :new
  template = "new"
  render template, :layout => false
end    

# new.haml
- details_view @user do |b, f|

# build_helper
def details_view(model, options = {}, &block)
  # instantiate OptionsWrapper passing a hash of key/value pairs, in this case
  # an empty hash. OptionsWrapper contains a method_missing method so when we
  # invoke mode on our instance of OptionsWrapper, since it does not contain
  # instance method of mode, it invokes method_missing and we set a number of
  # methods on fly.  
  options = OptionsWrapper.new(options) 
  options.mode ||= @view_mode
  model_name = model.class.model_name.singular.dasherize
  options.dom_id = "#{model_name}-details-view"
  # we instantiate DetailsViewBuilder passing in a few arguments (e.g. new,
  # ActionView, user) to the constructor method.
  builder = DetailsViewBuilder.new(options.mode, self, model)
  options.html ||= {}
  options.html[:id] ||= nil
  options.html[:class] = "x-#{options.mode} #{options.html[:class]}".strip
  render :layout => "shared/details_view", :locals => {:builder => builder,
    :model => model, :options => options}, &block
end

#details_view_builder
class DetailsViewBuilder
  attr_accessor :mode, :template, :model, :form

  def initialize(mode, template, model)
    @mode, @template, @model = mode, template, model #new, ActionView, user
  end

  def to_s
    # here's the method causing error!
    "#{self.class.name.underscore}__#{object_id}"
  end
end

# we then render the details_view passing in some locals as shown a
# few lines above:
.details-dialog{:id => options.dom_id }
  case options.mode
  - when :new
- form_for model, options.slice(:url, :html) do |form|
  = yield builder, form

to_sメソッドがエラーの原因であると100%確信しています。どこで呼ばれているのかわかりませんが、このエラーの原因となっています。上記のことに注意してください。ビルダー変数が生成されます。そのビルダー変数には、このメソッドを持つクラスが含まれています。コールスタックを透過的に確認できるように、要素を検査するためのより良い方法を見つける必要があります。メソッドが与えられれば、それがどこで呼び出されているかがわかります。奇妙なことに、この方法は私のローカルマシンでは機能しますが、サーバーでの本番環境でエラーが発生します。バックトレースの概要は次のとおりです。

ActionView::TemplateError
(`@content_for_details_view_builder__-626960428' is not allowed as an
instance variable name) in app/views/shared/_details_view.haml:

searchlogic (2.4.27) lib/searchlogic/rails_helpers.rb:75:in
`fields_for'
searchlogic (2.4.27) lib/searchlogic/rails_helpers.rb:64:in
`form_for'
app/helpers/builders_helper.rb:68:in `details_view'
/home/app-sptr/.rvm/rubies/ruby-1.8.7-p334/lib/ruby/1.8/benchmark.rb:308:in
`realtime'
app/other/restful_component.rb:488:in `new_html'
app/other/restful_component.rb:73:in `new'
app/other/restful_component.rb:72:in `new'
/home/app-sptr/.rvm/rubies/ruby-1.8.7-p334/lib/ruby/1.8/benchmark.rb:308:in
`realtime'
rack (1.1.2) lib/rack/head.rb:9:in `call'
rack (1.1.2) lib/rack/methodoverride.rb:24:in `call'
rack (1.1.2) lib/rack/lock.rb:11:in `call'
rack (1.1.2) lib/rack/lock.rb:11:in `synchronize'
rack (1.1.2) lib/rack/lock.rb:11:in `call'

私もここで質問をしましたが、答えに満足していませんでした: http ://www.ruby-forum.com/topic/1641800#new

4

2 に答える 2

5

使用する提案caller()は、特定のメソッドからスタック トレースを把握するのに適しています。ただし、問題の解決策も共有します (私が思うに)。

このto_sメソッドは、インスタンス変数を動的に設定するために使用される文字列を返します。は変数名の一部ですDetailsViewBuilderobject_idオブジェクト ID は、メモリ内のオブジェクトの場所を表します。直観に反してobject_id、オブジェクトの が負の整数になる場合があります。これが発生するかどうかは、プラットフォームに依存する場合もあります。これは、本番環境でのみこのエラーが表示される理由を説明しています。負のオブジェクト ID により、インスタンス変数名@content_for_details_view_builder__-626960428は、ダッシュを含む のようなものになります。Ruby では、識別子の一部としてダッシュを使用することはできません。したがって、エラー。

のインスタンスをどこかにDetailsViewBuilder引数として使っているようですね。content_forまたは、使用しているライブラリで間接的に発生する可能性があります。

いずれにせよ、これが正しい動作であり、インスタンス変数名のエラーを回避したいだけであれば、修正は簡単です。インスタンス変数にダッシュが含まれないようにするには、次のように変更object_idします。object_id.abs

def to_s
  "#{self.class.name.underscore}__#{object_id.abs}"
end 
于 2011-05-05T07:39:25.873 に答える
0

あなたが投稿したリンクで使用する提案caller()は、実際には非常に良いです。

ドキュメントにはまともな例がありますが、あなたが見逃しているように見えるのはこの部分でした:

オプションのstartパラメーターは、結果から除外する初期スタックエントリの数を決定します。

基本的caller()には、未処理の例外から取得するスタックトレースの本質であり、表示する行数を指定できるのはあなただけです。

于 2011-05-05T05:19:30.247 に答える