Rails中变量的生命

时间:2009-05-07 17:44:41

标签: ruby-on-rails ruby

我有以下代码:

   def show
    @game = $site.new_game_of_type(params[:id])
    @game.start
  end

  def update_game_time
    render :partial => 'countdown', :layout => false
  end

和倒计时部分:

<div id=countdown> <%= @game.running_time %></div>

在show.html.erb中我有:

Time: <div id="countdown"> </div>

<%= periodically_call_remote(:frequency => 0.5, 
   :update => 'countdown', :url => {:action => :update_game_time}) %>

我想在show中显示的页面中创建一个游戏,所以我会在那里移动很多ajax但是用户不会在任何地方点击。控制器的所有操作都将从Javascript调用。

我得到@game为零的错误。即使在方法update_game_time中也是零 当用户在该页面中时,如何使@game变量保持有效?

4 个答案:

答案 0 :(得分:3)

如果希望@game对象在请求之间保持不变,则需要将其存储在某处。有很多方法可以做到这一点(例如,你可以使它成为一个ActiveRecord对象并将其保存在数据库中)但它看起来像你想要使用会话。可以在http://www.quarkruby.com/2007/10/21/sessions-and-cookies-in-ruby-on-rails找到在Rails中使用会话所涉及的主要问题的一个很好的概述,但基本用法是:

def show
  @game = $site.new_game_of_type(params[:id])
  @game.start
  session[:game] = @game
end

def update_game_time
  @game = session[:game]
  render :partial => 'countdown', :layout => false
end

答案 1 :(得分:2)

每0.5秒向服务器发出一个请求并不是一个好主意。
我的建议是加载running_time一次,然后使用javascript来增加/减少它。

也许你可以这样做:

<div id=countdown><%= @game.running_time %></div>

在视图中然后使用一些javascript来更新计时器:

window.onload = function() {
  var countdownDiv = document.getElementById('countdown');

  var timerValue = parseInt(countdownDiv.innerHTML); // assuming that your running_time is an int (seconds)

  var dateObj = new Date();

  dateObj.setTime( timerValue*1000 );
  countdownDiv.innerHTML = dateObj.getMinutes() + ":" + dateObj.getSeconds();

  var timer = setInterval("dispalyTimer()", 1000);

  dispalyTimer = function() {
    dateObj.setTime( ( (dateObj.getTime()/1000) + 1 )*1000 );
    countdownDiv.innerHTML = dateObj.getMinutes() + ":" + dateObj.getSeconds();
  }
}

这只是一个基本的例子,但你明白了。无论如何,最好每半秒向服务器发出一次请求,这对于一个在客户端也可以很好地工作的计时器来说。

答案 2 :(得分:2)

在渲染之前,您应该将show方法中的两条线移动到update_game_time。否则@game未定义,除了呈现show操作时。

答案 3 :(得分:1)

您需要将变量传递给partial,以便在那里可见。

def update_game_time
 render :partial => 'countdown', :layout => false, :locals => { :game => @game }
end

然后在部分中访问它:

<div id=countdown> <%= game.running_time %></div>