6

我有一个模拟房屋的应用程序。House has_many Rooms、Rooms has_many Lights 和 Small_appliances 等。我还有一个名为 Calculator 的控制器,用于访问应用程序。使用计算器控制器将数据添加到房屋(及其房间)。然后生成一个报告,该报告位于 app/views/calculator/report.html.erb。

我的问题是报告的所有计算和逻辑应该去哪里?目前我已经在视图中,在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
4

4 回答 4

5

有几种方法可以解决它,但逻辑肯定不属于视图。如果我正确阅读了您的描述,您可以在清晰的层次结构中将各种模型相互关联,层次结构的顶部是 House 模型。在这种情况下,我将向 House 模型添加一组适当的方法,该方法可能由对与给定 House 实例相关联的 Room 模型中的计算方法的调用组成,并且沿着关联线向下。这样,可以在每个级别执行相关计算,并且通过在 House 模型级别组合一个或多个方法,您可以拥有一种干净、富有表现力和可维护的方式来处理计算。

同样要做的一件事是确保数据库可以执行的任何计算都是正确的。例如,如果有一个 Room 模型可以通过简单地查询它自己的数据来完成计算,那么一定要使用 ActiveRecord 调用这种较低级别的计算逻辑的能力将该计算负担推给 DB。查看API 文档了解详细信息。

我会非常仔细地查看您想要的逻辑,看看如何将其推入模型中,因为这可能是它所属的位置,接近计算的实际数据,并且在具体表示该数据的类结构中;除非您出于某种原因确实需要持久存储计算,否则我不会创建一个模型来处理计算逻辑。

于 2009-11-07T04:18:52.770 回答
1

好的,现在我可以看到发布的代码了。我可以看到calculator_controller 实际上没有计算,它们在视图中吗?试试这个方法:

  1. 编写一个测试,设置一个对象,该对象将返回您需要返回给网页用户的结果,给定房子、房间或任何其他需要的东西。
  2. 建立一个模型(在模型中)以使该测试通过。
  3. 修改上面的控制器代码以使用新的计算器模型
  4. 修改控制器的测试,使它们也通过。当然,这些测试不需要测试任何业务逻辑。

我之前的回复:

如果业务逻辑相当简单并且只在这个 web 应用程序后面使用,那么你可以将它放在你的 app/models 文件夹中。

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 是 MyCoolClass 的instance__variable,如果没有定义访问器方法,模板通常无法访问

于 2009-11-07T05:13:24.353 回答
1

我会在 RAILS_ROOT/lib/ 中创建一个名为 Calculator 的类,并将代码放在那里。

/lib/ 中的类应该加载到应用程序中的任何位置。

您还可以在 /app/models/ 中创建一个普通的 ruby​​ 对象。没有理由他们都必须从 ActiveRecord::Base 继承

于 2009-11-07T04:05:08.313 回答
0

这一切都取决于您正在创建什么样的数据。计算器控制器是什么样的?

您可以在 /lib 中创建自己的类并在模型中使用它们,这是将逻辑与控制器/助手分离的好方法。您是否有理由不能将某些逻辑放入模型中?

于 2009-11-07T03:58:40.650 回答