`

Rails 3, 不使用数据库的Active Model用法介绍

阅读更多

在第193篇【视频, 文本】中,介绍了一种不使用实际数据库的ActiveRecord的用法。实际这只是因为需求而进行的hack的做法,因为ActiveRecord没有设计这样用。不过在Rails 3里,这个情况已经改变。在Rails3里ActiveMode是设计来解决不想存储到数据库的数据的需求。
这篇的主题就是介绍ActiveMode的用法。在正式介绍开始前,我们先看看我们将要用来展示的例子。



截图展示一个用rails 脚手架创建的应用,其中Message是一个ActiveRecord的Mode。也就是脚手架默认的把Mode关联到数据库。我们将要做的是,我们只是把消息通过email发送但是不保持消息本身。
当然,在你要开始使用ActiveMode的时候你应该确认你是不是真的有这样的需求不使用数据库,因为,把数据库存到数据库可以作为一种数据的备份,或者用来进行后台的异步操作(译者晓夜注:比如当前例子的message可以存到数据库后异步调用发送)。对于我们的演示而言,我们就是要演示怎么使用ActiveMode,也没什么好考虑。那么,首先,看一下Message的
#/app/models/message.rb
	class Message < ActiveRecord::Base  
	 validates_presence_of :name  
	 validates_format_of :email, :with => /^[-a-z0-9_+\.]+\@([-a-z0-9]+\.)+[a-z0-9]{2,4}$/i  
	 validates_length_of :content, :maximum => 500  
	end 


从Message Mode的源代码我们可以看到,Message是继承自ActiveRecord::Base,也就是我们要不使用数据库,那么我们就要解除来自ActiveRecord的继承关系。然而,显然当我们去掉对应的ActiveRecord继承,那么对应的输入验证也就会失效。也就是我们将使用ActiveMode来支持这样的输入验证,这点在后文我们会看到。

查看Rails 3的源代码会看到 activerecord 和 activemodel的文件夹。实际上,Rails核心团队把所有和数据库无关的代码放到ActiveMode下。所以,ActiveRecord实际上依赖ActiveMode,而ActiveMode是经过了测试,并且可以独立于ActiveRecord使用的。
查看ActiveMode目录如下:




从代码列表我们可以大概看出来,这个目录下将包括如下功能处理回调,dirty tracking, 序列化和验证,等等。比较显然,最后的三个文件是我们需要的。
打开validations的源代码,我们会看到如下的注释。从注释我们会知道使用验证相当容易,只要把加载 Validations模块和提供getter方法给我们要验证的属性。
# == Active Model Validations  
#     
# Provides a full validation framework to your objects.  
#   
# A minimal implementation could be:  
#   
#   class Person  
#     include ActiveModel::Validations  
#   
#     attr_accessor :first_name, :last_name  
#  
#     validates_each :first_name, :last_name do |record, attr, value|  
#       record.errors.add attr, 'starts with z.' if value.to_s[0] == ?z  
#     end  
#   end  
#   


那么,我们可以根据注释修改我们的Message Mode如下:
#/app/models/message.rb
class Message  
  include ActiveModel::Validations  
    
  attr_accessor :name, :email, :content  
   
  validates_presence_of :name  
  validates_format_of :email, :with => /^[-a-z0-9_+\.]+\@([-a-z0-9]+\.)+[a-z0-9]{2,4}$/i  
  validates_length_of :content, :maximum => 500  
end  


那么,当前我们修改后的代码会有两个问题:1. 当我们创建Message的时候,Message.new方法会因为我们的initializer方法中不能创建接收参数的数据库插入操作而失效。2. 同样的save方法,原本会保存到数据库现在也将失效。
#/apps/controllers/messages_controller.rb
class MessagesController < ApplicationController  
  def new  
    @message = Message.new  
  end  
  
  def create  
    @message = Message.new(params[:message])  
    if @message.save  
      # TODO send message here  
      flash[:notice] = "Message sent! Thank you for contacting us."  
      redirect_to root_url  
    else  
      render :action => 'new'  
    end  
  end  
end  


我们首先修改保存的问题,因为我们并不需要保存message本身,所以save方法只需要进行验证操作就可以。也就是我们只需要用@message.valid? 方法代替@message.save方法就可以了。
#/app/controllers/messages_controllers.rb
def create  
  @message = Message.new(params[:message])  
  if @message.valid?  
    # TODO send message here  
    flash[:notice] = "Message sent! Thank you for contacting us."  
    redirect_to root_url  
  else  
    render :action => 'new'  
  end  
end  


至于,创建的问题,我们可以创建一个initialize的方法来接收传入Message的哈希参数,在initializer方法中,通过调用send(译者晓夜:调用变量对应的方法)方法给指定的属性赋值。

看起来应该没有什么问题了,可是当我们重新加载页面会看到如下错误:



#/app/models/message.rb
class Message  
  include ActiveModel::Validations  
    
  attr_accessor :name, :email, :content  
   
  validates_presence_of :name  
  validates_format_of :email, :with => /^[-a-z0-9_+\.]+\@([-a-z0-9]+\.)+[a-z0-9]{2,4}$/i  
  validates_length_of :content, :maximum => 500  
    
  def initialize(attributes = {})  
    attributes.each do |name, value|  
      send("#{name}=", value)  
    end  
  end  
end   

问题是在于我们没有在Message中定义to_key方法,form_for默认的认为我们model提供这样的方法,那么,我们需要添加这个功能。

实际上,在我们不知道Rails都需要我们的model提供什么功能的时候,我们可以加载ActiveModel::Lint::Tests模块到我们的modle测试中。在Lint::Tests模块中展示出包括to_key在内的Rails定义的model需要提供的方法。 至于,如何解决缺少方法的问题,我们可以加载一组ActiveRecord的模块来解决。 Conversion是其中包括to_key方法的模块。我们也需要Naming 方法,这里我们不使用include而是使用extend因为我们需要类方法(译者晓夜:对应于include类实例方法)。
我们引入了Conversion,那么我们需要重新定义persisted?方法,因为我们不需要使用数据库所以,我们呢需要persisted方法返回false。所以,我们的Message Model将会修改如下:
#/app/models/message.rb
class Message  
  include ActiveModel::Validations  
  include ActiveModel::Conversion  
  extend ActiveModel::Naming  
    
  attr_accessor :name, :email, :content  
   
  validates_presence_of :name  
  validates_format_of :email, :with => /^[-a-z0-9_+\.]+\@([-a-z0-9]+\.)+[a-z0-9]{2,4}$/i  
  validates_length_of :content, :maximum => 500  
    
  def initialize(attributes = {})  
    attributes.each do |name, value|  
      send("#{name}=", value)  
    end  
  end  
    
  def persisted?  
    false  
  end  
end  


这时,我们再刷新页面我们会看到已经能够正常显示了,也就是说我们的Message model已经提供了Rails3需要的方法。提交form我们会发现验证的功能也可以正常使用了。




实际上我们只是介绍了ActiveMode中很少的一部分功能。ActiveMode中还有更多值得了解的方法,幸好这部分的代码结构和注释写的很好,在你需要使用的时候,只要参考对应的源代码就可以很好的了解如何使用。
  • 大小: 37.5 KB
  • 大小: 186.1 KB
  • 大小: 46.3 KB
  • 大小: 94.7 KB
2
0
分享到:
评论

相关推荐

    Ruby on Rails

    Active Record允许您将数据库行中的数据显示为对象,并使用业务逻辑方法修饰这些数据对象。虽然大多数 Rails 模型都由数据库支持,但模型也可以是普通的 Ruby 类,或者是实现Active Model模块提供的一组接口的 Ruby ...

    rails2.3.2

    Ruby on Rails(通常简称为 Rails)是一个基于 Ruby 语言的开源 Web 应用程序框架,它遵循 Model-View-Controller (MVC) 设计模式,用于构建数据库驱动的 Web 应用程序。Rails 强调“约定优于配置”(Convention ...

    种使用MVC架构开发的Trello,使用Active Record进行数据库查询.zip

    在本文中,我们将深入探讨如何使用MVC(Model-View-Controller)架构开发一个类似Trello的应用,并结合Active Record进行数据库查询。MVC是一种广泛应用于Web应用开发的设计模式,它将业务逻辑、数据处理和用户界面...

    好用的rails 2.0 Api 文档

    综上所述,Rails 2.0 API文档包含了Rails框架的各个重要组件和概念,对于学习和使用Rails 2.0的开发者来说,是不可或缺的参考资料。通过深入研究这个文档,开发者能够更好地理解和利用Rails的强大功能,提高开发效率...

    ruby on rails在线考试系统

    3. RESTful设计:Rails鼓励使用REST(Representational State Transfer)架构风格来构建Web应用,通过HTTP方法(GET、POST、PUT、DELETE等)实现资源的增删改查,使接口清晰、易于理解。 4. 模板引擎:Rails使用ERB...

    Rails 4 in Action, Second Edition.pdf

    - **Active Record Query Interface**:Rails 4在Active Record中引入了一个新的查询接口,使数据库操作更加直观和高效。 - **Secure Cookies**:为了提高安全性,Rails 4引入了一种新的安全cookie机制,可以更好地...

    Rails 敏捷开发实践

    在 Rails 中,Active Record 是一个典型的 ORM 实现,它允许开发者使用面向对象的方式与数据库交互,避免了复杂的 SQL 语句编写。例如: ```ruby # 查询状态为 "paid" 的订单,并关联用户信息,限制返回 5 条记录,...

    Ruby-RecordCache在Rails3中缓存ActiveModelRecords

    它不依赖于Rails的默认缓存机制,如Action Cache或Page Cache,而是提供了一个更直接的方法来缓存模型实例。 **RecordCache的工作原理** RecordCache的核心思想是将模型实例序列化为JSON格式,并存储在内存中的...

    ruby on rails实践

    Rails还采用了"Active Record"模式,将数据库操作与对象关联,使得数据操作更加直观。 二、安装与环境配置 在开始Ruby on Rails实践之前,你需要安装Ruby、Gem(Ruby的包管理器)、Bundler(依赖管理工具)以及...

    rails-exporter-源码.rar

    Rails 的 Active Record 提供了强大的 ORM(对象关系映射),使得数据库操作变得简单。 2. Controllers:控制器文件可能包含了导出操作的处理逻辑,如响应用户请求,调用模型方法获取数据,然后调用视图或直接生成...

    Crafting Rails 4 Applications

    - **框架内部工作原理**:深入探讨Rails框架内部的工作机制,包括但不限于MVC模式的实现、Active Record的使用方法以及Rails配置选项等。 - **代码优化技巧**:提供了多种方法来优化Rails应用程序的性能,如缓存策略...

    无线点餐系统的服务端,使用ruby on rails框架

    Rails还采用了Active Record,这是ORM(对象关系映射)库,使得与数据库交互变得异常简单。 在无线点餐系统的服务端,Rails将扮演处理HTTP请求、执行业务逻辑、与数据库交互的角色。模型(Model)通常代表数据库中...

    基于ruby on rails 的简单blog

    3. **生成模型**:使用`rails generate model Post title:string content:text`创建一个Post模型,包含title和content字段。 4. **迁移数据库**:运行`rails db:migrate`命令创建对应的数据库表。 5. **生成控制器**...

    Agile Web Development with Rails, 4th Edition, Rails 3.1

    - 本书通过实际案例展示了如何使用Active Record进行CRUD(创建、读取、更新、删除)操作,并介绍了关联关系(如一对一、一对多、多对多)的定义和使用方法。 4. **路由管理** - 路由是Web应用的核心组件之一,...

    Ruby-ActiveModel的自定义验证用于检查数组是否包含在另一个中

    在Ruby开发中,ActiveModel是Rails框架的一部分,它提供了一种模型层的接口,使得非ActiveRecord对象也能具有类似于ActiveRecord的行为。这个标题提到的"Ruby-ActiveModel的自定义验证用于检查数组是否包含在另一个...

Global site tag (gtag.js) - Google Analytics