数据传输对象VS域中的域/ ActiveRecord实体

时间:2010-02-23 23:15:18

标签: ruby-on-rails rails-activerecord

我来自.NET背景,其中一种做法是不将域/实体模型直接绑定到不那么基本的CRUD-ish应用程序中的视图,其中视图不直接将实体字段投影为 - 是

我想知道RoR中的做法是什么,默认持久性机制是ActiveRecord。我认为不应该将与演示相关的信息泄露给实体,但不确定这是否真的是RoR头部会这样做。

如果方法是DTO / model per view,你将如何在Rails中完成?

你的想法?

修改

一些例子:
- 视图显示发票列表,其中包含一列中的唯一项目数 - 可能存在欺诈交易的信用卡账户清单。为此,UI需要以红色显示此行。

对于这两种情况,列表不显示实体的所有字段,只显示列表中的一些(如发票号,交易日期,帐户名称,交易金额)

对于发票示例,发票实体没有映射到其上的“行项目数”字段。由于性能原因,数据库尚未进行非规范化,并且在使用聚合函数的查询时间内计算数据库。

对于信用卡帐户示例,卡交易实体肯定没有“Show-in-red”或“IsFraudulent”不变量。是的,这可能是一个商业规则,但对于这个例子,这是一个表示问题,所以我想保持它不受我的域模型的影响。

1 个答案:

答案 0 :(得分:1)

一般情况下,我会回答您的AcitveRecord对象可以包含任何字段,并且您只在视图中显示您想要的内容。 rails脚本中有脚手架任务,但它只是创建一些设置模型,控制器和视图。当我使用Rails时,我根本不使用./script/generate scaffold。相反,我只是分别生成模型和控制器。视图部分我手动添加。

ActiveRecord仅将数据库中的数据映射到一些不错的对象。你在视野中做什么取决于你。

根据表示和业务规则之间的分离,我认为不再举例可以让你清楚如何在Rails中处理它。

对于您的发票示例,我会以这种方式创建视图:

<h1>Invoices</h1>
<table>
  <tr>
    <th>Invoice #</th>
    <th>Date</th>
    <th>Name</th>
    <th>No. of line items</th>
    etc
  </tr>
  <% @invoices.each do |invoice| %>
    <tr>
      <td><%= invoice.number %></td>
      <td><%= invoice.date.to_s %></td>
      <td><%= invoice.name %></td>
      <td><%= invoice.line_items.count %></td>
      etc.
    </tr>
  <% end %>
</table>

或者甚至将包含发票数据的行放入单独的部分中并在上方视图中呈现它。我假设你的模型中有:

# Invoice model
has_many :line_items

现在让我们来看看信用卡示例。我会这样做:

# In CreditCard model add method
def fraudulent?
  #put here some logic that returns true or false
end

然后在您查看此信用卡时:

<div <%= @credit_card.fraudulent? ? 'class="show_in_red"' : '' %>
   here you can show whatever you want
</div>

甚至为它创建帮手:

# credit card helper
def add_show_in_red(credit_card)
  credit_card.fraudulent? ? 'class="show_in_red"' : ''
end

# in Rails 3 or earlier version with plugin that puts `h` method by default 
# your helper should have additional safe_html! call
def add_show_in_red(credit_card)
  (credit_card.fraudulent? ? 'class="show_in_red"' : '').safe_html!
end

并在视野中:

<div <%= add_show_in_red(@credit_card) %>>
   here you can show whatever you want
</div>