`
peryt
  • 浏览: 54438 次
  • 来自: ...
最近访客 更多访客>>
社区版块
存档分类
最新评论
  • waiting: 既然都指定了dataType为'script'那就不必特别在b ...
    jQuery

Making a Plugin & 定义和使用block

阅读更多
1.
在上一篇文章中,我们介绍了如何使用edit field来编辑日期和时间,而不是用很多的dropdown menus. 那些日期和时间首先被用文本输入到一个编辑框中,然后被rails用自带的日期解析函数解析成日期和时间存储到数据库中。

例如:
Task name: Task 1
Due at time string:

2009-08-20 08:00:00

为了完成这个任务,我们为Task model创建了一个虚拟属性,叫做due_at_string, 这个属性具有 get method 和 set method, get method 从数据库中读取due_at 字段,然后以某种格式的字符串显示出来, set method则解析用户输入的字符串,将其转化成日期时间类型,并存储到数据库的due_at 字段中, 具体代码如下:
def due_at_string
  due_at.to_s(:db)
end

def due_at_string=(due_at_str)
  self.due_at = Time.parse(due_at_str)
rescue ArguementError
  @due_at_invalid = true
end


这种为某一个属性单独写set method 和 get method的做法处理某一个属性当然可以,但是如果需要单独写set和get 的属性很多呢,例如还有许多其他字段也是日期时间格式?我们代码会有很多的重复。

为了解决这个问题,我们的方法是添加一个类方法,名字叫stringify_time。
这个方法的作用就是动态的为每一个传给他的属性自动创建getter和setter方法。cool把
而且可以预计到,这个方法我们在其他的项目中也会经常用到,因此我们要把他封装成一个plugin。呵呵


2. Create Plugin:
首先,我们要generate 一个空的plugin 名字叫 stringify_time
命令如下:
script/generate plugin stringify_time

这个命令将在我们的工程的vender/plugins文件夹生成一个新的叫stringify_time的文件夹
我们先来看看init.rb文件, 这个是初始化文件,它将在plugin 被load in 之前load 进来,因此,这里我们要在init.rb 中添加如下一行:

这行代码将会把lib目录下的stringify_time.rb 文件load 进来。
require 'stringify_time' 

而在lib/stringify_time.rb 文件中,这里是主要代码所在地,我们将在这里添加类似的getter 和 setter methods, 我们首先要定义一个module,其中含有stringify_time 方法。

module StringifyTime
  def stringify_time(*names)
  end
end


stringify_time这个方法将接收多个字段名字作为参数,这里我们用*names,表示这个方法可以接收多个参数,所有参数构成一个叫names的数组供方法内部调用,这个是个很有用的小知识,一般人我不告诉他哦!

在方法内部,循环使用数组中的名字,使用define_method这个方法,动态的创建名字叫[name]_string 的方法,那么如果我们传递due_at给这个方法,我们就会得到due_at_string方法。

define_method 这个方法接收一个block,block内的代码就是动态定义的方法的内容,以之前的due_at_string方法为例,这个方法从数据库中读取due_at字段,然后将其日期时间类型转换成一个字符串返回,但是这里不能用dua_at 这个名字了,只能用read_attribute 方法获得字段:
def stringify_time(*names)
  names.each do |name|
    define_method "#{name}_string" do
      read_attribut(name).to_s(:db)
    end
  end
end


就是这么简单,我们就创建了很多属性的getter方法。
同样的,我们照葫芦画瓢写出动态创建setter方法的类方法
names.each do |name|
  define_method "#{name}_string=" do |time_str|
    begin  
      write_attribute(name, Time.parse(time_str))
    rescue ArgumentError
      instance_variable_set("@#{name}_invalid", true)
    end
  end
end 


哇噻,太牛逼的程序了,可惜不是我写的,嘿嘿!!!!
可以看到,在setter method 中,我们仍然使用了define_method方法,但是要setter method要接收参数,这个参数可以放在随后的block中.

全部代码如下:
module StringifyTime   
  def stringify_time(*names)   
    names.each do |name|   
         
      define_method "#{name}_string" do  
        read_attribute(name).to_s(:db)   
      end  
         
      define_method "#{name}_string=" do |time_str|   
        begin  
          write_attribute(name, Time.parse(time_str))   
        rescue ArgumentError   
          instance_variable_set("@#{name}_invalid", true)   
        end  
      end  
         
    end  
  end  
end  


稍等,我们已经写好了plugin,但是在程序中如何让没有active record model自动具有这个pulgin的功能呢,这就需要将这个plugin中的的module extend到ActiveRecord::Base这个类中,这个工作要放在init.rb中:
class ActiveRecore:Base
  extend StringifyTime
end


注意我们用的是extend而不是include, extend的作用是将module中的方法作为类方法而不是实例方法添加到ActiveRecord::Base中,因为我们的stringify_time是类方法,而不是实例方法,因为这个方法的运行不需要有任何对象。

而include 将会把StringifyTime中的方法作为实例方法放入到ActiveRecord::Base中。



3. 既然我们已经制作了plugin,而且把他包含进了ActiveRecord::Base类中,那么接下来就是如何使用他了,在我们的Task模型中:
class Task < ActiveRecord::Base
  belongs_to :project
  stringify_time :due_at

  def validate
    errors.add(:due_at, "is_invalid") if @due_at_invalid
  end

end


4. 完善:
我们发现在validate方法中,我们用@due_at_invalid这个实例变量来判断,但是这个实例变量是在plugin中定义的,这里突然冒出来,后面的开发者很可能不知道他是哪里来的,因此我们最好使用方法而不是直接使用实例变量:
def validate
  errors.add(:due_at, "is_invalid") if due_at_invalid?
end

而这个方法的定义自然也应该放在plugin中:
define_method "#{name}_invalid?" do
  return instance_variable_get("#{name}_invalid")
end

至此,我们终于完成了一个plugin的制作。

如果你要在其他的项目中复用这个plugin,只要把这个目录拷贝到该项目的vender/plugin目录下即可,很简单把,嘿嘿。


5. 再说一点题外话:
关于block,例如
class File
  def File.open_and_process(*args)
    f = File.open(*args)
    yield f
    f.close
  end
end

File.open_and_process('testfile', 'r') do |file|
  while line=file.gets
    puts line
  end
end


这就是一个 后面可以跟着block的方法的定义和使用的全过程。


分享到:
评论

相关推荐

    64bit Plugin & key

    64bit Plugin & key 64bit Plugin & key

    SpacEyes3D Plugin & SDK简

    - **SpacEyes3D Software Development Kit (SDK)**:作为核心开发工具包,SpacEyes3D SDK使第三方程序能够在SpacEyes3D Plugin的基础上进行扩展和定制。它包含了创建、编辑和操作三维虚拟项目的必要组件和API。 - *...

    PidginHost Selenium Plugin & SSH Testing Suite

    PidginHost Selenium Plugin & SSH Testing Suite

    JAVA视频教程(三) - Plugin & RCP开发-gonxi

    JAVA视频教程(三) - Plugin & RCP开发 http://blog.csdn.net/gonxi/archive/2006/02/12/597312.aspx

    QT-Plugin的创建和使用

    QT-Plugin的创建和使用是Qt框架中一个重要的特性,它允许程序在运行时动态加载新的功能或组件,极大地增强了软件的灵活性和可扩展性。本文将深入探讨如何创建和使用QT-Plugin,并通过实际例子来阐述相关知识点。 ...

    code & plugin.part1code & plugin.part1code & plugin.part1

    code & plugin.part1 code & plugin.part1 code & plugin.part1 code & plugin.part1 code & plugin.part1

    code & plugin.part2code & plugin.part2code & plugin.part2

    code & plugin.part2 code & plugin.part2 code & plugin.part2 code & plugin.part2 code & plugin.part2

    Ita-IDE-Plugin

    总的来说,"Ita-IDE-Plugin"是一款为Delphi IDE增添趣味性和实用性的插件,它通过提供自定义背景图片的功能,帮助开发者打造个性化的工作空间,让编程过程更加愉快。对于那些注重开发环境体验的程序员来说,这无疑是...

    android DroidPlugin插件使用

    同时,需要遵循DroidPlugin定义的特定规范,如使用特殊的Activity声明和Intent过滤器。 3. **宿主集成**:宿主应用需要集成DroidPlugin框架,这通常涉及到对AndroidManifest.xml的修改,以及对项目构建脚本的调整,...

    Veeam Rman Plugin for Oracle安装和使用手册.docx

    "VEEAM Rman Plugin for Oracle安装和使用手册" VEEAM Rman Plugin for Oracle是VEEAM公司开发的一款插件,旨在为Oracle RAC数据库提供备份和恢复解决方案。该插件可以与VEEAM Backup & Replication集成,提供了一...

    PluginManager - A C# utility to load plugin based components

    2. **插件加载**:找到插件后,PluginManager会使用C#的反射机制来加载和实例化这些插件。反射允许程序在运行时检查类型信息,并动态创建对象实例。 3. **依赖注入**:为了使插件能够正常工作,PluginManager可能...

    alink-plugin

    "alink-plugin"是一个基于Alink框架的插件系统,它扩展了Alink的核心功能,使得开发者可以更加便捷地实现特定的数据处理和机器学习任务。Alink是阿里巴巴开源的一个实时流计算框架,它提供了丰富的算法库,支持大...

    maven plugin maven plugin

    在 Maven 中,插件是通过 Maven 插件管理系统(scm)进行管理和使用的。这个主题主要围绕 Maven 插件的使用、其与 SCM(版本控制系统)的集成以及如何利用 Maven 插件与 Ant 集成来进行项目管理与构建。 首先,让...

    Maven使用tomcat8-maven-plugin插件.docx

    Maven 使用 tomcat8-maven-plugin 插件 Maven 是一个流行的构建自动化工具,它可以帮助开发者自动完成项目的编译、测试、打包、部署等任务。...在本文中,我们详细介绍了 tomcat8-maven-plugin 插件的使用方法和优点。

    微信小程序海报插件,生成海报的小程序组件wxa-plugin-canvas-master.zip

    总之,“wxa-plugin-canvas-master”是一个强大的微信小程序海报生成解决方案,它利用canvas的强大绘图能力,帮助开发者轻松创建个性化的海报,提升了小程序的用户体验和互动性。正确理解和运用这个组件,能够为你的...

    maven-site-plugin和 maven-scr-plugin同时使用时site plugin不能删除target中OSGI-INF\\serviceCo

    当maven-site-plugin和maven-scr-plugin同时使用时,可能遇到的问题是,site plugin试图清理target目录以准备生成新的站点文档,但因为maven-scr-plugin生成的服务元数据(通常位于target/OSGI-INF/serviceComposite...

    Qt Plugin 示例程序

    例如,你可以定义一个`IPlugin`接口,包含`start()`和`stop()`方法,供插件在加载和卸载时使用。 接下来,你需要创建一个实现该接口的插件类。这个类继承自接口,并实现其定义的所有功能。在我们的示例程序...

    download-block-plugin.zip

    WordPress原创插件:Download-block-plugin下载按钮图标美化

    SteamVR Plugin和Vive Input Utility

    在虚拟现实(VR)开发领域,SteamVR Plugin和Vive Input Utility是两个至关重要的工具,尤其对于使用Unity引擎创建HTC Vive体验的开发者而言。这两个工具包极大地简化了与HTC Vive头显交互的复杂性,使开发者能够构建...

    NotePad++ 插件 AnalysePlugin

    本文将重点探讨NotePad++的一款重要插件——AnalysePlugin,帮助用户更高效地分析和处理复杂日志。 AnalysePlugin是一款专门针对NotePad++设计的插件,旨在提高开发者对大型复杂日志文件的分析能力。在处理大量系统...

Global site tag (gtag.js) - Google Analytics