瘦controller,富model

----先看这么一段rhtml代码:渲染模板中加入了这么多的逻辑,看起来不伦不类,这么做行是行,但是缺点很多,新手一般有这个毛病。那么这样做,首先是可读性很差,因为在渲染代码中最好都是贴近HTML代码,而这堆代码里把C的内容也加进来了。

<% people = Person.find(
:conditions => ["added_at > ? and deleted = ?", Time.now.utc, false],
:order => "last_name, first_name") %>
<% people.reject { |p| p.address.nil? }.each do |person| %>
<div id="person-<%= person.new_record? ? "new" : person.id %>">
<span class="name">
<%= person.last_name %>, <%= person.first_name %>
</span>
<span class="age">
<%= (Date.today - person.birthdate) / 365 %>
</span>
</div>
<% end %>

再看看controller和model里的东西:

# app/controllers/people_controller.rb
class PeopleController < ActionController::Base
end

# app/models/person.rb
class Person < ActiveRecord::Base
has_one :address
end

空荡荡的controller,而在model里仅仅有一句关系声明。这么组合成的MVC显得很别扭,似乎就是一层渲染模板。几乎把C与M都忽略了。

无论如何这在MVC框架里是糟糕透顶的现象,MVC经过这么多年的实践考验,它的优点在于“可读性强”“可维护性好”“模块化”“关注点的分离”等等,我想你用MVC框架也就是想实现这些优点哇?那么首先需要改进的是尽可能的将逻辑内容搬到controller中,controller 的作用就是介于view和model之间,起到一个类似中介的作用。下面来看下这样改动之后的代码:

<!-- app/views/people/index.rhtml -->
<% @people.each do |person| %>
<div id="person-<%= person.new_record? ? "new" : person.id %>">
<span class="name">
<%= person.last_name %>, <%= person.first_name %>
</span>
<span class="age">
<%= (Date.today - person.birthdate) / 365 %>
</span>
</div>
<% end %>



# app/controllers/people_controller.rb
class PeopleController < ActionController::Base
def index
@people = Person.find(
:conditions => ["added_at > ? and deleted = ?", Time.now.utc, false],
:order => "last_name, first_name")
@people = @people.reject { |p| p.address.nil? }
end
end

这样看起来就好多了,模板中的代码更像是HTML的结构,而且你粗略的看一下controller里的代码就能知道在这个action渲染的模板中会显示什么数据。

还可以更进一步做的事情就是将现在模板代码中关于一部分数据的处理挪到Model中来:

# app/models/person.rb
class Person < ActiveRecord::Base
# ...

def name
"#{last_name}, #{first_name}"
end

def age
(Date.today - person.birthdate) / 365
end

def pseudo_id
new_record? ? "new" : id
end
end


<!-- app/views/people/index.rhtml -->
<% @people.each do |person| %>
<div id="person-<%= person.pseudo_id %>">
<span class="name"><%= person.name %></span>
<span class="age"><%= person.age %></span>
</div>
<% end %>

这样通过在model中添加几个虚拟属性,在view里调用,显得很合理,而且模板代码更简洁明了了。

下一步就是将controller里的代码理一理。因为controller只能算是个中介,不应该参与很多的逻辑处理。

# app/models/person.rb
class Person < ActiveRecord::Base
def self.find_recent
people = find(
:conditions => ["added_at > ? and deleted = ?", Time.now.utc, false],
:order => "last_name, first_name")
people.reject { |p| p.address.nil? }
end

# ...
end


# app/controllers/people_controller.rb
class PeopleController < ActionController::Base
def index
@people = Person.find_recent
end
end

现在看index这个action,扫一眼就知道它要干吗。而且如果find_recent方法在以后需要改变时,可以直接在model里进行修改。

--总结一下,尽量使得controller的actions中的代码和view中的代码更少,在action中要是能只写一行达到效果最好。在view中要尽量使代码贴近html结构。

还有一个不太明显的好处就是,瘦action可以使得 respond_to 结构更突出,可以看出输出的类型是什么。

class PeopleController < ActionController::Base
def index
@people = Person.find_recent

respond_to do |format|
format.html
format.xml { render :xml => @people.to_xml(:root => "people") }
format.rss { render :action => "index.rxml" }
end
end
end
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值