2009-05-07 53 views
2

我有以下代碼:生命的變量

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}) %> 

我想要在顯示的頁面中創建一個遊戲,所以我將有很多Ajax移動到那裏,但用戶不會在任何地方點擊。控制器的所有操作都將從Javascript調用。

我得到了@game爲零的錯誤。即使在方法update_game_time 中也是零,我怎樣才能使@game變量在用戶在該頁面時保持有效?

回答

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(); 
    } 
} 

這僅僅是一個基本的例子,但你明白這點。無論如何,最好每隔半秒向服務器發一個請求,以便在客戶端也能很好地工作。

+0

感謝您的回答。 服務器可以通過任何方式發起與客戶端的對話而無需以前的客戶端事件? The 0。5秒更新是我的黑客定期致電服務器,並讓他更新其信息給客戶端。這是我所知道的最好的 – Jordi 2009-05-07 18:04:40

+0

服務器爲什麼要發起連接/對話?我不確定我明白。在* nix平臺上,你*可以使用cron作業(http://en.wikipedia.org/wiki/Cron)從服務器發出請求,但我不知道這種方法是否也是一個好主意。你能對你想要達到的目標做更具體的描述嗎? – andi 2009-05-07 21:30:26

+0

我有一個底層引擎。我想使用Web界面讓用戶知道發生了什麼,並與流程進行交互。 用戶開始一個新遊戲,然後引擎將讀取遊戲定義並創建用戶界面。遊戲有時間限制,有新的傳入數據等。我想發送給用戶的事件。 這是可能的,但我的投票方法肯定不是最有效的 – Jordi 2009-05-08 01:45:29

1

您需要將變量傳遞給partial,以便在該處可見。

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

,然後訪問它在部分像這樣:

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

即使我這樣做 加薪@ game.running_time.to_s 內update_game_time我得到一個消息說,我跑了: nil.running_time.to_s ..... – Jordi 2009-05-07 18:00:20

+0

順便說一句,至少本地部分似乎工作(我試過在一個不相關的控制器)。謝謝你的提示。 – Jordi 2009-05-07 18:05:46

2

在渲染之前,您應該將show方法中的兩條線移動到update_game_time。否則@game未定義,除了呈現show操作時。

+0

Upvoted this,因爲它讓我想起了rails控制器的規則: 對服務器的每個請求==控制器的新實例。因此,ajax調用獲取部分將是一個新的實例(沒有顯示被調用),因此不會有@game變量來做任何事情。 – workmad3 2009-05-07 18:56:53

3

如果您希望@game對象在請求之間持續存在,則需要將其存儲在某處。有很多方法可以做到這一點(例如,您可以將其設置爲ActiveRecord對象並將其保存在數據庫中),但是在我看來,您希望使用該會話。參與Rails中使用會話中的重大問題很好的概述可以在http://www.quarkruby.com/2007/10/21/sessions-and-cookies-in-ruby-on-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