简体   繁体   English

Ruby on Rails:在视图中使用帮助程序初始化实例变量

[英]Ruby on Rails: Initializing instance variables with helpers in view

I'm running into some type of a scope issue that's preventing instance variables from being properly initialized by helpers called from the view. 我遇到了某种类型的范围问题,它阻止实例变量被视图调用的助手正确初始化。

#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 %>

When sample/test is displayed, it dies with an error "while evaluating nil.reverse". 当显示样品/测试时,它会在“评估nil.reverse”时出现错误。 This is surprising because the first two calls to display should have initialized @display I would have thought. 这是令人惊讶的,因为显示的前两个调用应该初始化@display我会想到。 If <%= @display.reverse %> is removed the output is "a aa", indicating that the @display instance variable is getting set by the helper method, but there is no access to it in the view. 如果删除<%= @ display.reverse%>,则输出为“a aa”,表示辅助方法正在设置@display实例变量,但视图中无法访问它。

If the controller is modified so to become (with the original view code): 如果控制器被修改成为(使用原始视图代码):

class SampleController < ApplicationController
  def test
    display
  end
end

The output becomes "aa aaa aa". 输出变成“aa aaa aa”。 If I make it 2 calls to display in the controller, I get, "aaa aaaa aa aa". 如果我在控制器中进行2次调用,我会得到“aaa aaaa aa aa”。 So it seems like only the calls made in the controller will modify the SampleController instance variable, whereas calls in the view will modify an instance variable for the ApplicationController that the view has no access to. 因此,似乎只有在控制器中进行的调用才会修改SampleController实例变量,而视图中的调用将修改视图无法访问的ApplicationController的实例变量。

Is this a bug in Rails or am I misunderstanding and this is for some reason intended functionality? 这是Rails中的错误还是我的误解,这是出于某种原因预期的功能?

The context in which I ran into this bug is trying to create a logged_in? 我遇到这个bug的上下文是试图创建一个logged_in? ApplicationController method that sets up an @user variable the first time it is called, and returns true or false if a user is logged in. This would not work unless I added an unnecessary call in the controller before attempting to use it in the view. ApplicationController方法,在第一次调用时设置@user变量,如果用户登录则返回true或false。除非在尝试在视图中使用它之前在控制器中添加了不必要的调用,否则这将无效。

There are two @display ivars at render time, one in the controller and one in the view. 渲染时有两个@display ivars,一个在控制器中,一个在视图中。 The view can't access the one in the controller and vice versa. 视图无法访问控制器中的视图,反之亦然。 At the start of the render Rails copies all the controller ivars into the view. 在渲染开始时,Rails将所有控制器ivars复制到视图中。 But at that time @display does not exist and is not copied over. 但那时@display不存在,不会被复制。 In any ruby program a call to @my_undefined_ivar will return nil - which is exactly what is happening to you. 在任何ruby程序中,对@my_undefined_ivar的调用都将返回nil - 这正是发生在你身上的事情。

Could be confusing, here it is said another way. 可能令人困惑,这里有另一种说法。 Rails copies ivars from the controller into the view at the start of the render. Rails将ivars从控制器复制到渲染开始时的视图中。 So, changes in the view's ivar are not reflected in the controller ivar and vice versa. 因此,视图的ivar中的变化不会反映在控制器ivar中,反之亦然。 The helper you defined lets the view invoke a method on the controller so the controller's ivar can be passed back to the view as a return value but the change to the controller ivar itself is not reflected in the other, the view's, ivar. 您定义的帮助程序允许视图调用控制器上的方法,以便控制器的ivar可以作为返回值传递回视图,但是对控制器ivar本身的更改不会反映在另一个视图中,ivar。

Just use the helper method in this case and forget about @display in the view. 在这种情况下只需使用辅助方法,忘记视图中的@display。

I think this might be the second reserved words issue I've seen this week... 我想这可能是本周我见过的第二个保留词 ......

Tip: you almost never need to use the return keyword in Ruby. 提示:您几乎不需要在Ruby中使用return关键字。 Also, your use of defined? 另外,你defined?的使用defined? is freaking me out...might be worth trying this: 我吓坏了...可能值得这样做:

  if @display.nil?
    @display = "a"
  else
    @display += "a"
  end

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM