- 浏览: 2683106 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
80后的童年2:
深入浅出MongoDB应用实战开发网盘地址:https://p ...
MongoDB入门教程 -
shliujing:
楼主在不是精通java和php的前提下,请不要妄下结论。
PHP、CakePHP哪凉快哪呆着去 -
安静听歌:
希望可以一给一点点注释
MySQL存储过程之代码块、条件控制、迭代 -
qq287767957:
PHP是全宇宙最强的语言!
PHP、CakePHP哪凉快哪呆着去 -
rryymmoK:
深入浅出MongoDB应用实战开发百度网盘下载:链接:http ...
MongoDB入门教程
Rails宝典之第二式: 动态find_by方法
忘了声明了,这个系列主要是Rails入门教学。
今天Rails宝典教大家的是动态find_by方法,我们先看一段代码:
很类似Hibernate的数据库查询hql语句,但显然我们的Rails不可能这么逊,看看改良的方法:
我们的Task这个Model类没有定义find_all_by_complete啊,我们为什么可以调用这个方法呢?
请看active_record/base.rb中的一段代码:
看看第一行代码:if match = /^find_(all_by|by)_([_a-zA-Z]\w*)$/.match(method_id.to_s)
这是一个正则表达式匹配:
^匹配一行的开始
$匹配一行的结束
\w匹配一个词语,可以是数字、字母、下划线
[]匹配括号里面符合的一个字符
*匹配0个或多个它前面的字符或短语
则([_a-zA-Z]\w*)则匹配以下划线或任意小写字母或任意大写字母开头的一个字符串
具体参考《Programming Ruby》中的Regular Expressions一章
而extract_attribute_names_from_match方法也很有意思,match.captures返回匹配的字符串组成的数组,last返回最后一个元素,如:
这样,第一行代码所匹配的方法名具体为find_by(或all_by)_aaaBBB形式
而extract_attribute_names_from_match允许我们匹配形式为find_by(或all_by)_aaaBBB_and_cccDDD_and_eeeFFF_and_...的方法
即我们可以无限添加查询条件,通过_and_连接字段名即可
而且可以看出,我们还可以调用find_by_columnName、find_or_initialize_by_columnName、find_or_create_by_columnName等动态方法。
参考Rails源码研究之ActiveRecord:一,基本架构、CRUD封装与数据库连接
总结:
动态语言可以做出很强大的框架,完成很多有意思的工作,这是Java、C#这种静态语言望尘莫及的。
本例中的find_by方法就是利用Ruby的method_missing语法特性来为Model动态生成方法,我们可以称其为POJO增强。
JavaScript也是一门大家可能忽略了但又十分强大的动态语言,参考Ruby和Python,JavaScript还有很大潜力可挖。
这个complete是database里已经定义好的列了吧?
这行代码里的all_attributes_exists?方法是否会去数据库中检查相对应的列有没有存在?
如果存在就初始化类的实例,否则就抛出错误。类似于这样的错误:
NoMethodError: undefined method `find_all_by_name'?
因为在database里没有name这个column
忘了声明了,这个系列主要是Rails入门教学。
今天Rails宝典教大家的是动态find_by方法,我们先看一段代码:
class TasksController < ApplicationController def incomplete @tasks = Task.find(:all, :conditions => ['complete = ?', false]) end end
很类似Hibernate的数据库查询hql语句,但显然我们的Rails不可能这么逊,看看改良的方法:
class TasksController < ApplicationController def incomplete @tasks = Task.find_all_by_complete(false) end end
我们的Task这个Model类没有定义find_all_by_complete啊,我们为什么可以调用这个方法呢?
请看active_record/base.rb中的一段代码:
def method_missing(method_id, *arguments) if match = /^find_(all_by|by)_([_a-zA-Z]\w*)$/.match(method_id.to_s) finder = determine_finder(match) attribute_names = extract_attribute_names_from_match(match) super unless all_attributes_exists?(attribute_names) attributes = construct_attributes_from_arguments(attribute_names, arguments) case extra_options = arguments[attribute_names.size] when nil options = { :conditions => attributes } set_readonly_option!(options) ActiveSupport::Deprecation.silence { send(finder, options) } when Hash finder_options = extra_options.merge(:conditions => attributes) validate_find_options(finder_options) set_readonly_option!(finder_options) if extra_options[:conditions] with_scope(:find => { :conditions => extra_options[:conditions] }) do ActiveSupport::Deprecation.silence { send(finder, finder_options) } end else ActiveSupport::Deprecation.silence { send(finder, finder_options) } end else raise ArgumentError, "Unrecognized arguments for #{method_id}: #{extra_options.inspect}" end elsif match = /^find_or_(initialize|create)_by_([_a-zA-Z]\w*)$/.match(method_id.to_s) instantiator = determine_instantiator(match) attribute_names = extract_attribute_names_from_match(match) super unless all_attributes_exists?(attribute_names) if arguments[0].is_a?(Hash) attributes = arguments[0].with_indifferent_access find_attributes = attributes.slice(*attribute_names) else find_attributes = attributes = construct_attributes_from_arguments(attribute_names, arguments) end options = { :conditions => find_attributes } set_readonly_option!(options) find_initial(options) || send(instantiator, attributes) else super end end def extract_attribute_names_from_match(match) match.captures.last.split('_and_') end
看看第一行代码:if match = /^find_(all_by|by)_([_a-zA-Z]\w*)$/.match(method_id.to_s)
这是一个正则表达式匹配:
^匹配一行的开始
$匹配一行的结束
\w匹配一个词语,可以是数字、字母、下划线
[]匹配括号里面符合的一个字符
*匹配0个或多个它前面的字符或短语
则([_a-zA-Z]\w*)则匹配以下划线或任意小写字母或任意大写字母开头的一个字符串
具体参考《Programming Ruby》中的Regular Expressions一章
而extract_attribute_names_from_match方法也很有意思,match.captures返回匹配的字符串组成的数组,last返回最后一个元素,如:
/^(a)_(b)_(\w*)$/.match("a_b_c_d_e_f_g").captures # => ["a", "b", "c_d_e_f_g"] /^(a)_(b)_(\w*)$/.match("a_b_c_d_e_f_g").captures.last # =>"c_d_e_f_g" /^find_(all_by|by)_([_a-zA-Z]\w*)$/.match("find_by_a_and_b_and_c").captures.last # => "a_and_b_and_c"
这样,第一行代码所匹配的方法名具体为find_by(或all_by)_aaaBBB形式
而extract_attribute_names_from_match允许我们匹配形式为find_by(或all_by)_aaaBBB_and_cccDDD_and_eeeFFF_and_...的方法
即我们可以无限添加查询条件,通过_and_连接字段名即可
而且可以看出,我们还可以调用find_by_columnName、find_or_initialize_by_columnName、find_or_create_by_columnName等动态方法。
参考Rails源码研究之ActiveRecord:一,基本架构、CRUD封装与数据库连接
总结:
动态语言可以做出很强大的框架,完成很多有意思的工作,这是Java、C#这种静态语言望尘莫及的。
本例中的find_by方法就是利用Ruby的method_missing语法特性来为Model动态生成方法,我们可以称其为POJO增强。
JavaScript也是一门大家可能忽略了但又十分强大的动态语言,参考Ruby和Python,JavaScript还有很大潜力可挖。
评论
8 楼
yuwang
2007-11-06
那上面1分不到,hideto讲的好,怎么详细,把上面没有的都弄出来了,谢谢
7 楼
hideto
2007-08-11
是的是的
6 楼
rainlife
2007-08-11
楼主,请问这些是否都是根据www.railscasts.com上面的视屏教程写出来的?
5 楼
blackanger
2007-08-05
引用
我们的Task这个Model类没有定义find_all_by_complete啊,我们为什么可以调用这个方法呢?
这个complete是database里已经定义好的列了吧?
super unless all_attributes_exists?(attribute_names)
这行代码里的all_attributes_exists?方法是否会去数据库中检查相对应的列有没有存在?
如果存在就初始化类的实例,否则就抛出错误。类似于这样的错误:
NoMethodError: undefined method `find_all_by_name'?
因为在database里没有name这个column
4 楼
blackanger
2007-07-29
google不是要用javascript来搞一套ROR吗。。。infoq上看到的消息。。。
3 楼
Readonly
2007-07-25
这个不错,可以结合起来写, 又学了一招
2 楼
hideto
2007-07-25
我仔细看了上面的源码中的method_missing方法,其中有这么一段:
这就意味着使用动态find_by后仍然可以使用:conditions参数,额外的条件会使用with_scope来约束,如:
或者也可以直接使用with_scope,不过代码没上面这样写简单。
使用动态find_by结合:conditions即可做非等号的查询,我试验了一下,结果是可以的。
if extra_options[:conditions] with_scope(:find => { :conditions => extra_options[:conditions] }) do ActiveSupport::Deprecation.silence { send(finder, finder_options) } end else ActiveSupport::Deprecation.silence { send(finder, finder_options) } end
这就意味着使用动态find_by后仍然可以使用:conditions参数,额外的条件会使用with_scope来约束,如:
Book.find_by_title('title', :conditions => ['price > ?', price])
或者也可以直接使用with_scope,不过代码没上面这样写简单。
使用动态find_by结合:conditions即可做非等号的查询,我试验了一下,结果是可以的。
1 楼
Readonly
2007-07-25
hideto的系列文章很不错啊,偶再来补充几点:
1. 动态查询支持nil, array 以及range作为参数
比如要查询上海或者北京, 年龄在18~38之间的用户,就可以这样用:
2. 动态查询不支持like以及单边范围的查找,比如查询名字中包括"read",年龄大于30的老头用户:
name like '%read%' and age > 30
就无法用动态查询来做了
通过查询源代码,可以看到这样一段在做转换:
偶的想法是:如果多加一个Struct的支持来实现非等号单操作符的查询,是不是可行呢,比如:
1. 动态查询支持nil, array 以及range作为参数
比如要查询上海或者北京, 年龄在18~38之间的用户,就可以这样用:
User.find_all_by_city_and_age(['Shanghai','Beijing'], (18...38))
2. 动态查询不支持like以及单边范围的查找,比如查询名字中包括"read",年龄大于30的老头用户:
name like '%read%' and age > 30
就无法用动态查询来做了
通过查询源代码,可以看到这样一段在做转换:
def attribute_condition(argument) case argument when nil then "IS ?" when Array then "IN (?)" when Range then "BETWEEN ? AND ?" else "= ?" end end
偶的想法是:如果多加一个Struct的支持来实现非等号单操作符的查询,是不是可行呢,比如:
find_all_by_name_and_age(like('%read%'), greater(30))
发表评论
-
用了TextMate才知道什么叫神级Editor
2011-03-09 04:51 57999一直用Eclipse作为开发Ruby和Java项目的IDE,但 ... -
Ruby使用OAuth登录新浪微博和豆瓣
2011-01-09 12:49 4465首先需要安装oauth这个gem包 gem install ... -
使用Passenger+nginx部署Rails
2010-12-28 15:12 50331. Install Passender gem instal ... -
markItUp+rdiscount搭建Rails下可视化Markdown编辑器
2010-12-21 17:48 5471markItUp是基于jQuery的可视化编辑器,支持Html ... -
Rails3 and MongoDB Quick Guide
2010-12-10 14:13 2760Install MongoDB Download: http: ... -
基于ruby-protobuf的rpc示例
2009-08-11 11:51 41521, 安装ruby-protobuf gem instal ... -
Ruby导出xls和csv的utf-8问题的解决
2009-02-04 15:05 6860数据库数据为utf-8格式,包括中文和拉丁文等等 导出文件xl ... -
URL/HTML/JavaScript的encode/escape
2009-01-04 13:03 9346最近经常被URL、HTML、JavaScript的encode ... -
各种排序的Ruby实现
2008-11-27 14:51 4008Θ(n^2) 1, Bubble sort def bu ... -
12月5日北京RoR活动!
2008-11-26 18:38 3024又是一年过去了,Rails在国内的发展势态良好,很多使用RoR ... -
Rails程序开发的最大问题是代码规范
2008-08-28 11:56 5584使用Rails开发大型复杂B2B应用一年了,这个项目目前开发人 ... -
Web开发大全:ROR版——推荐序
2008-07-09 00:39 2430来自http://www.beyondrails.com/bl ... -
深入ActionMailer,使用Sendmail发邮件
2008-07-03 11:41 3399来自: http://www.beyondrails.com/ ... -
Rails里如何结合ExceptionNotification配置gmail账户发邮件
2008-06-19 19:56 31031,安装ExceptionNotification rub ... -
使用coderay和railscasts样式进行代码高亮
2008-06-17 00:16 2400CodeRay是一个语法高亮的Ruby库,效率很不错。 Cod ... -
Capistrano试用
2008-06-16 19:05 19631,客户端机器安装Capistrano gem insta ... -
lighttpd真垃圾啊
2008-06-04 18:38 2548使用lighttpd+fcgi跑Rails程序,文件上传会si ... -
将gem变成plugin
2008-06-04 11:27 1809有什么样的需求就有什么样的对策 当vhost上的帐号没有ge ... -
在Rails里使用ReCaptcha添加验证码
2008-06-03 15:51 42741,去http://recaptcha.net/sign up ... -
Rails里给文件上传添加progress_bar
2008-05-27 17:00 2098文件上传很慢时,UI没有什么用户提示,这样让人很费解,所以我们 ...
相关推荐
持续移动且不破坏事物 :factory: :building_construction: :construction: :construction_worker: 正在建设中-请稍后再回来!
Rails::API 是 Rails 的精简版本,针对不需要使用完整 Rails 功能的开发者。 Rails::API 移除了 ActionView 和其他一些渲染功能,不关心Web前端的开发者可更容易、快速地开发应用程序,因此运行速度比正常的 Rails ...
Rails管理员状态机 主存储库已移至gitlab,所有新代码将在其中: 从rails_admin正确管理状态 允许从Rails Admin轻松地将state_machine事件发送到模型,包括对ActiveRecord \ Mongoid和自定义状态字段名称的支持以及...
:dog_face: MiAudota :cat_face: 该应用程序显示可从用户最近的庇护所获取的动物,并允许将其应用到收养过程中,从而完成一份调查表,... Ruby on Rails API; PostgreSQL; Heroku。执照版权所有:copyright:2019, 。
允许您使用为Rails应用程序的前端供电。 是将前端工具像Ruby一样进行编程,纯属喜悦! :smiling_face_with_heart-eyes: 或在运行的检查。 产品特点 :high_voltage: :light_bulb: 即时服务器启动 :high_voltage: ...
介绍插件,用于对记录进行排序(使用 gem)安装要启用rails_admin_acts_as_list,请将以下内容添加到您的Gemfile : gem 'rails_admin_acts_as_list'gem 'rails_admin' 重要提示: rails_admin_acts_as_list之前必须...
SEO 和 Ruby On Rails 由的SEO代理制作的示例应用程序,用于将Rails设置为SEO友好。教程您可以在找到教程,或在。安装 git clone git@github....
Rails Admin内容生成器 使用创建内容的简单方法。 预习 示范 要求 依存关系 MiniMagick 支持的ORM ActiveRecord 支持的资产插件 CarrierWave 安装 使用rails <5和TurboLink <5进行测试 将此行添加到您的...
如果没有,请使用第二个基于Docker的命令。 $ sam init --location " gh:customink/lamby-cookiecutter " $ docker run \ --rm \ --interactive \ --volume " ${PWD} :/var/task:delegated " \ amazon/a
《Rails101_by_rails4.0》是一本专注于Rails 4.0.0版本和Ruby 2.0.0版本的自学教程书籍,它定位于中文读者,旨在成为学习Rails框架的参考教材。Rails(Ruby on Rails)是一个采用Ruby语言编写的开源Web应用框架,它...
电子邮件仪表板是一种从应用程序管理外发电子邮件的简便方法。 从创建和发送电子邮件到监视和管理其统计信息,您可以使用Email-Dashboard做真正有用的事情,而不必担心时区浪费。 您可以 :link: 。 :anger_symbol:...
10. **Rails Console和Rails Server**:Rails console允许开发者在命令行环境中交互式地运行Ruby代码,而Rails server则启动应用,使得可以在浏览器中查看和测试应用。 在"For-Rails-Beginners"这个资源中,你可能...
#### 六、添加第二个路由 - **配置**:在`config/routes.rb`文件中添加新的路由规则,例如`get 'new_route' => 'controller#action'`。 - **效果**:这将在应用中增加一个新的URL路径,指向指定控制器的动作。 ###...
image_optim_rails 使用image_optim gem优化rails图像资产。 在文件中可以找到获取二进制文件的选项和说明。安装添加到您的Gemfile : gem 'image_optim_rails' 使用 : gem 'image_optim_rails'gem 'image_optim_...
安装要启用rails_admin_history_rollback ,请将以下内容添加到您的Gemfile确保将其添加到rails_admin之后: gem 'rails_admin'gem 'rails_admin_history_rollback' 不用说,此插件还需要paper_trail gem。...
Rails的服务器定时响应头 带来Ruby on Rails服务器端性能指标 :chart_increasing: 通过server_timing gem访问Chrome的开发者工具(以及其他支持浏览器)。 生产安全:trade_mark:。 指标是从 gem收集的。 不需要帐户...
在Ruby on Rails(Rails)框架中,开发人员经常需要实现各种...通过学习这个实例,开发者可以掌握如何在Rails应用中集成第三方库,处理层级数据,以及创建交互式的前端界面。这对于提升Web应用的用户体验非常有价值。
factory_bot_rails 用简单的定义语法替换了固定装置,支持多种构建策略(保存的实例,未保存的实例,属性哈希和存根对象),并且支持同一类的多个工厂( user , admin_user等),包括工厂继承。 从factory_girl_...
护林员探索Ruby on Rails API的路由和路径| Rails Ranger是之上的薄薄一层,它为您提供了一个自以为是的界面,以查询使用Ruby on Rails构建的API。主要特点遵循Ruby on Rails路由约定的URL构建在前端和API之间交换...
报表生成可能涉及到的数据分析库有Chartkick和Highcharts,它们允许我们在Rails应用中轻松集成交互式图表。Chartkick可以将Ruby数据转换为各种图表类型,如柱状图、饼图和线图,而Highcharts则提供丰富的JavaScript...