论坛首页 编程语言技术论坛

将常用功能插件化 - 提高开发效率

浏览 7735 次
该帖已经被评为良好帖
作者 正文
   发表时间:2009-08-14  
虽然Rails提供了很多便利的内置方法,能够让我们快速处理开发中常见的需求,但还是会有要写大量相似代码的情景。
利用ruby语言的动态特性,我们可以将这些代码组件化,举一个active record扩展的实际例子:
枚举类型的属性,比如用户的性别属性,在数据库里面用0/1表示男/女,我们有很多地方要用到这个属性:
#在模型中我们需要写validate
validates_inclusion_of :sex, :in => [0,1]
#在页面上我们需要用tag生成下拉选择框
<%= form.select :sex, [['男', 0], ['女', 1]] %>
#在显示输出的时候我们还要判断
<%= user.sex == 0 ? '男' : '女' %>

再比如博客的类型属性,用0~3表示原创/翻译/转载/随笔等类型,也会有一堆相似的代码

利用ruby的module include和class eval等动态特性,我们可以方便地做一个plugin来mixin:
#plugins/your_plugin_name/lib/enum_attr.rb
module EnumAttr
  module Mixin
    def enum_attr(attr, enums)
      attr = attr.to_s
      self.class_eval(%Q{
ENUMS_#{attr.upcase} = enums
validates_inclusion_of attr, :in => enums.map{|e| e[1]}, :allow_nil => true
def #{attr}_name
  ENUMS_#{attr.upcase}.find{|option| option[1] == #{attr}}[0] unless #{attr}.nil?
end
        })
    end
  end
end

#plugins/your_plugin_name/init.rb
require 'enum_attr'
Object.send :include, EnumAttr::Mixin


这样很容易地就增加了一个叫enum_attr的DSL:
class User < ActiveRecord::Base 
  enum_attr :sex, [['男', 0], ['女', 1]]
end

class Blog < ActiveRecord::Base 
  enum_attr :blog_type, [['原创', 0], ['翻译', 1], ['转载', 2], ['随笔', 3]]
end

然后我们就可以这样用:
#在模型中我们不需要写validate了
...
#在页面上我们可以调用常量
<%= form.select :sex, User::ENUMS_SEX %>
#在显示输出的时候我们可以直接调用扩展方法
<%= user.sex_name %>


通过将这些常用的功能插件化,能够更好地提高开发效率,你在开发中有将哪些功能组件化?欢迎交流。
   发表时间:2009-08-14  
学习了。这种地方都是在Model中定义常量数组,值和显示都是一样的汉字。
0 请登录后投票
   发表时间:2009-08-14   最后修改:2009-08-14
非常不错,这样易维护,好理解。

我根据公司的实际需求情况,为了方便大家,将翻译功能搞到了一个插件中去了。
http://wiki.github.com/qichunren/acts_as_translatebox
然后使用起来很方便。
0 请登录后投票
   发表时间:2009-08-15  
对于上面博客类型的例子,如果在state_machine插件里面加上这样的功能,会更加的好用.
0 请登录后投票
   发表时间:2009-08-15  
qichunren 写道
非常不错,这样易维护,好理解。

我根据公司的实际需求情况,为了方便大家,将翻译功能搞到了一个插件中去了。
http://wiki.github.com/qichunren/acts_as_translatebox
然后使用起来很方便。


这个很赞!
3 请登录后投票
   发表时间:2009-08-16  
谢谢分享!
请问如果要有多语言的要求呢?写在model里面就不行了吧
0 请登录后投票
   发表时间:2009-08-18   最后修改:2009-08-18
好像一般性别都用 gender 而不是 sex, 要不然看起来总是浮想联翩
0 请登录后投票
   发表时间:2009-09-09  
kilik52 写道
谢谢分享!
请问如果要有多语言的要求呢?写在model里面就不行了吧


enum_attr :sex, [[I18n.t("male"), 0], ['女', 1]]
0 请登录后投票
   发表时间:2009-12-23  
def #{attr}_name  
  ENUMS_#{attr.upcase}.find{|option| option[1] == #{attr}}[0]unless #{attr}.nil?  
end

很想知道ENUMS_#{attr.upcase}与find{|option| option[1] == #{attr}}中#{attr}有什么区别,按照代码的意思好像前一个#{attr}好像是指属性这里是"sex",后一个#{attr}是指值这里是0或1,晕了。
0 请登录后投票
   发表时间:2009-12-25  
jayliud 写道
def #{attr}_name  
  ENUMS_#{attr.upcase}.find{|option| option[1] == #{attr}}[0]unless #{attr}.nil?  
end

很想知道ENUMS_#{attr.upcase}与find{|option| option[1] == #{attr}}中#{attr}有什么区别,按照代码的意思好像前一个#{attr}好像是指属性这里是"sex",后一个#{attr}是指值这里是0或1,晕了。


以sex为例,这段代码实际生成的就是:
def sex_name
  # 这个模型本来就有sex方法(数据库字段),它存放的值就是0或1
  ENUM_SEX.find { |option| option[1] == sex }[0] unless sex.nil?
end

另外,sex这个词确实会令人浮想联翩
0 请登录后投票
论坛首页 编程语言技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics