4

ビューから呼び出されたヘルパーによってインスタンス変数が適切に初期化されないという、ある種のスコープの問題が発生しています。

#sample_controller.rb
class SampleController < ApplicationController
  def test
  end
end

#application_controller.rb
helper_method :display 
def display
  if not defined? @display
    return @display = "a"
  else
    return @display += "a"
  end
end

#test.html.erb
<%= display %>
<%= display %>
<%= @display %>
<%= @display.reverse %>

サンプル/テストが表示されると、「nil.reverse の評価中」というエラーで終了します。display の最初の 2 つの呼び出しで @display が初期化されているはずだったので、これは驚くべきことです。<%= @display.reverse %> が削除された場合、出力は "a aa" になり、@display インスタンス変数がヘルパー メソッドによって設定されていることを示しますが、ビューにはアクセスできません。

コントローラーが次のように変更された場合 (元のビュー コードを使用):

class SampleController < ApplicationController
  def test
    display
  end
end

出力は「aa aaa a a」になります。コントローラーに表示するために2回呼び出すと、「aaa aaaa aa aa」となります。したがって、コントローラーで行われた呼び出しのみが SampleController インスタンス変数を変更するように見えますが、ビューでの呼び出しは、ビューがアクセスできない ApplicationController のインスタンス変数を変更します。

これはRailsのバグですか、それとも誤解ですか?これは何らかの理由で意図された機能ですか?

このバグに遭遇したコンテキストは、logged_in? を作成しようとしています。初めて呼び出されたときに @user 変数を設定し、ユーザーがログインしている場合は true または false を返す ApplicationController メソッド。ビューで使用する前にコントローラーに不要な呼び出しを追加しない限り、これは機能しません。

4

2 に答える 2

6

レンダリング時に 2 つの @display ivar があり、1 つはコントローラーに、もう 1 つはビューにあります。ビューはコントローラーのビューにアクセスできません。また、その逆も同様です。レンダリングの開始時に、Rails はすべてのコントローラー ivar をビューにコピーします。しかし、その時点では @display は存在せず、コピーされません。どの Ruby プログラムでも、@my_undefined_ivar を呼び出すと nil が返されます。これはまさにあなたに起こっていることです。

紛らわしいかもしれませんが、ここでは別の言い方をしています。Rails は、レンダーの開始時に ivar をコントローラーからビューにコピーします。そのため、ビューの ivar の変更はコントローラの ivar には反映されず、その逆も同様です。定義したヘルパーにより、ビューはコントローラーのメソッドを呼び出すことができるため、コントローラーの ivar を戻り値としてビューに戻すことができますが、コントローラーの ivar 自体への変更は、他のビューの ivar には反映されません。

この場合はヘルパー メソッドを使用し、ビューの @display は忘れてください。

于 2010-01-24T21:33:23.043 に答える
0

これは、今週私が見た 2 番目の予約語の問題かもしれないと思います...

returnヒント: Ruby でキーワードを使用する必要はほとんどありません。また、あなたの使用はdefined?私を驚かせています...これを試す価値があるかもしれません:

  if @display.nil?
    @display = "a"
  else
    @display += "a"
  end
于 2010-01-24T19:35:05.947 に答える