2009-11-07 87 views
5

我有一個模擬房子的應用程序。房子has_many房間,房間has_many燈和small_appliances等,我也有一個名爲計算器控制器是如何訪問該應用程序。使用計算器控制器將數據添加到房屋(及其房間)。然後生成一個報告,位於app/views/calculator/report.html.erb。計算邏輯應該放到Rails應用程序中去哪裏?

我的問題是,報告的所有計算和邏輯都應該放在哪裏?目前我在視圖中都有,在calculator_helper中有一些東西。通常這會在模型中進行,對吧?但計算器沒有生成的模型。這是什麼標準?

這裏是計算器控制器。

class CalculatorController < ApplicationController 
    def index 
    end 

    def save_house 
    @house = House.new(params[:house]) 
    respond_to do |format| 
     if @house.save 
     format.html { render :action => 'add_rooms', :id => @house } 
     format.xml { render :xml => @house, :status => :created, :location => @house } 
     else 
     format.html { render :action => 'index' } 
     format.xml { render :xml => @house.errors, :status => :unprocessable_entity } 
     end 
    end 
    end 

    def add_rooms 
    @house = House.find(params[:id]) 
    @rooms = Room.find_by_house_id(@house.id) 

    rescue ActiveRecord::RecordNotFound 
    logger.error("Attempt to access invalid house #{params[:id]}") 
    flash[:notice] = "You must create a house before adding rooms" 
    redirect_to :action => 'index' 
    end 

    def add_room 
    @room = Room.new(params[:room]) 
    @house = @room.house 

    respond_to do |format| 
     if @room.save 
     flash[:notice] = "Room \"#{@room.name}\" was successfully added." 
     format.html { render :action => 'add_rooms' } 
     format.xml { render :xml => @room, :status => :created, :location => @room } 
     else 
     format.html { render :action => 'add_rooms' } 
     format.xml { render :xml => @room.errors, :status => :unprocessable_entity } 
     end 
    end 
    rescue ActiveRecord::RecordNotFound 
    logger.error("Attempt to access invalid house #{params[:id]}") 
    flash[:notice] = "You must create a house before adding a room" 
    redirect_to :action => 'index' 
    end 

    def report 
    flash[:notice] = nil 
    @house = House.find(params[:id]) 
    @rooms = Room.find_by_house_id(@house.id) 
    rescue ActiveRecord::RecordNotFound 
    logger.error("Attempt to access invalid house #{params[:id]}") 
    flash[:notice] = "You must create a house before generating a report" 
    redirect_to :action => 'index' 
    end 
end 
+0

請向我們展示您的計算器類。 – 2009-11-07 06:27:12

+0

我喜歡James的回答。我想你應該問自己的另一個問題就是爲什麼你要突破常規 - 計算器控制器爲什麼要處理似乎屬於控制器的東西?我不是說你做錯了,我只是說這是值得多加思考的。 – 2009-11-07 08:38:21

+0

好點,安迪。 Ryan,在你開始擔心控制器和視圖之前,先獲取MODELS。使用這種方法,您可能會發現所有計算的正確位置是House模型。 – 2009-11-07 16:11:14

回答

0

這一切都取決於您創建的數據類型。計算器控制器是什麼樣的?

您可以在/ lib中創建自己的類並在模型中使用它們,這可以很好地將邏輯從控制器/幫助程序中分離出來。你有沒有理由不能在模型中加入一些邏輯?

+0

calculator_controller保存數據並將用戶移動到允許他們輸入更多信息的下一頁。 模型正在驗證,但就是這樣。正在執行的計算主要是基於房屋和房間參數的數字計算。 我試着製作一個計算器的模型,但後來我無法從視圖中訪問這些變量。我需要做出所有的全局變量嗎? – Ryan 2009-11-07 04:08:36

1

我會在RAILS_ROOT/lib/called中創建一個類,例如Calculator,並將代碼放在那裏。

/lib /中的類應該在應用程序中的任何位置加載。

您還可以在/ app/models /中創建一個普通的ruby對象。沒有理由他們都必須繼承ActiveRecord :: Base

+0

我已經在應用程序/模型中創建了一個不能從ActiveRecord繼承的calculator.rb文件。但是,當我將代碼移到該文件時,我無法再從視圖中訪問它。我假設這是因爲我用局部變量做了所有事情。解決這個問題的最好方法是什麼?我嘗試將它們更改爲全局變量,但似乎沒有幫助。 – Ryan 2009-11-07 04:47:12

+0

將方法放入模型中而不是lib /中的類可以更好地將邏輯與基礎數據關聯。另外,它具有明顯的優點,即不會遇到與實例變量有關的問題,因爲您可以調用已在控制器和視圖中處理的模型實例上的方法。 如果在代碼庫中使用多個類,比如Mixin模塊,或者您正在重構爲可重用的邊車項目/插件,則將代碼編入到lib /中是最有意義的。如果邏輯是代碼庫的一部分,請將其保存在主代碼中。 – 2009-11-08 00:12:40

5

有幾種方法來處理它,但邏輯肯定不屬於視圖。如果我正確地閱讀了你的描述,你就可以將各種模型與層次結構的頂層作爲House模型進行清晰的層次關聯。既然如此,我會爲House模型添加一套合適的方法,這些方法可能由與給定House實例關聯的房間模型中的計算方法調用以及關聯關係組成。通過這種方式,可以在每個級別執行相關計算,並且通過在衆議院模型級別組合一種或多種方法,您可以擁有清晰,富有表現力且可維護的方式來處理計算。

要做的一件事就是確保任何可以由數據庫執行的計算。例如,如果有一個房間模型可以通過簡單地查詢它自己的數據來進行計算,那麼通過所有的方式,使用ActiveRecord調用這樣的較低級別計算邏輯的能力來將該計算負擔推送到數據庫。詳情請查看API docs

我會仔細看看你想要的邏輯,看看它是如何被推入模型的,因爲這可能是它屬於的地方,靠近計算的實際數據,並且在表示該數據的類結構中特別;我不會創建一個模型來處理計算邏輯,除非您真的需要持續存儲計算出於某種原因。

1

好的,現在我可以看到發佈的代碼。我可以看到calculator_controller實際上沒有計算它們,它們在視圖中嗎?試試這個辦法:

  1. 寫一個測試,給出了一套房子,房間或其他任何需要設置的對象將返回您需要返回到該網頁的用戶的結果。
  2. 建立一個模型(在模型中)使測試通過。
  3. 修改上面的控制器代碼以使用您的新計算器模型
  4. 修改您的控制器的測試,以便它們也通過。這些測試當然不需要測試任何業務邏輯。

我之前respose:

如果業務邏輯相當簡單,只用這背後的Web應用程序,那麼你可以把它放在你的應用程序/模型文件夾中。

class MyCoolClass 
    def initialize(clues) 
    @other_things = OtherThing.all 
    end 
    def do_cool_thing; end 
    def calculate_coolness 
    @other_things.length 
    end 
end 

然後在你的控制器,創建模型的實例

def index 
    @mcc = MyCoolClass "A clue as to what I want" 
    render 
end 

然後在你的模板,您可以訪問它

<%=h @mcc.calculate_coolness %> 

注意@other_things是一個instance__variable MyCoolClass並且通常無法在沒有定義訪問器方法的情況下訪問模板

+0

當邏輯開始混淆AR模型時,我喜歡建立這樣的模型。 – 2009-11-07 16:12:06

相關問題