- 浏览: 2690673 次
- 性别:
- 来自: 北京
-
文章分类
最新评论
-
80后的童年2:
深入浅出MongoDB应用实战开发网盘地址:https://p ...
MongoDB入门教程 -
shliujing:
楼主在不是精通java和php的前提下,请不要妄下结论。
PHP、CakePHP哪凉快哪呆着去 -
安静听歌:
希望可以一给一点点注释
MySQL存储过程之代码块、条件控制、迭代 -
qq287767957:
PHP是全宇宙最强的语言!
PHP、CakePHP哪凉快哪呆着去 -
rryymmoK:
深入浅出MongoDB应用实战开发百度网盘下载:链接:http ...
MongoDB入门教程
深入了解一下ActionController的Resources--RESTful Rails
1,ActionController的resources用来实现REST api,一个单独的resource基于HTTP verb(method)有不同的行为(action),如:
2,对于map.resources :messages将生成如下named routes和helpers:
3,由于浏览器不支持PUT和DELETE,我们需要添加:method参数,如:
4,resources方法有一些参数:
:controller -- specify the controller name for the routes.
:singular -- specify the singular name used in the member routes.
:path_prefix -- set a prefix to the routes with required route variables.
对于如下routes:
我们可以使用嵌套写法:
使用的时候多加一个:article_id参数即可:
:name_prefix -- define a prefix for all generated routes, usually ending in an underscore.
使用前缀来避免named routes名字冲突:
:collection -- add named routes for other actions that operate on the collection.
比如对于如下route:
生成的named route为rss_messages,生成的helper方法为rss_messages_path,url则为/messages;rss
该参数形式为#{action} => #{method}的hash,method为:get/:post/:put/:delete/:any,如果method无所谓则可以使用:any
:member -- same as :collection, but for actions that operate on a specific member.
即:collection参数为对多个对象操作的方法,:member参数则为对单个对象操作的方法
:new -- same as :collection, but for actions that operate on the new resource action.
5,map.resource的参数以及用法与map.resources差不多,只是map.resource为一个单独的resource生成named routes
源码全在resources.rb文件里,Rails经常这样弄的一个文件几百行甚至上千行代码,可读性很不好,不过倒也不错,不用到处找关联的文件
Resources模块定义了Resource类和SingletonResource类,前者表示多个资源,后者则表示单个资源
resources方法和resource方法分别调用map_resource方法和map_singleton_resource方法
map_resource和map_singleton_resource方法分别用Resource和SingletonResource类初始化对象
最后分别调用map.named_route和map.connect来生成各自的routes
注意resources和resource方法对生成的routes作了HTTP method上的限制,如果我们在request时提供的method参数有误则会抛出RoutingError异常
这样看来,resources只不过是为我们生成了一些named routes而已,简化了我们的工作,提高了效率
我们在看源码时带着问题去看,就会非常有收获
不好意思,偶昨天写得匆忙,没有把错误写上来,测试代码如下:
routes.rb和你前面贴的一样:
第一个测试不带query string的没有问题,第二个测试报错是:
You have a nil object when you didn't expect it!
The error occurred while evaluating nil.to_sym
不过偶后来发现这个问题和resource无关,是偶不知道named route产生的_path/_url方法如何接受query string,很好奇你的代码怎么可以运行通过
===编辑分隔线===
发现你的代码不同点了,你是用_path(:id => xxx, :page => xxx)这种方式,测试代码改成:
path = forum_path(:id => forums(:forum_1), :page => 1) 就可以通过了,偶再去看看文档或者源代码哪里有涉及到这2种方式的不同说明...
1,ActionController的resources用来实现REST api,一个单独的resource基于HTTP verb(method)有不同的行为(action),如:
map.resources :messages class MessagesController < ActionController::Base # GET messages_url def index # return all messages end # GET new_message_url def new # return an HTML form for describing a new message end # POST message_url def create # create a new message end # GET message_url(:id => 1) def show # find and return a specific message end # GET edit_message_url(:id => 1) def edit # return an HTML form for editing a specific message end # PUT message_url(:id => 1) def update # find and update a specific message end # DELETE message_url(:id => 1) def destroy # delete a specific message end end
2,对于map.resources :messages将生成如下named routes和helpers:
Named Routes Helpers messages messages_url, hash_for_messages_url, messages_path, hash_for_messages_path message message_url(id), hash_for_message_url(id), message_path(id), hash_for_message_path(id) new_message new_message_url, hash_for_new_message_url, new_message_path, hash_for_new_message_path edit_message edit_message_url(id), hash_for_edit_message_url(id), edit_message_path(id), hash_for_edit_message_path(id)
3,由于浏览器不支持PUT和DELETE,我们需要添加:method参数,如:
<% form_for :message, @message, :url => message_path(@message), :html => {:method => :put} do |f| %>
4,resources方法有一些参数:
:controller -- specify the controller name for the routes.
:singular -- specify the singular name used in the member routes.
:path_prefix -- set a prefix to the routes with required route variables.
对于如下routes:
map.resources :articles map.resources :comments, :path_prefix => '/articles/:article_id'
我们可以使用嵌套写法:
map.resources :articles do |article| article.resources :comments end
使用的时候多加一个:article_id参数即可:
comment_url(@article, @comment) comment_url(:article_id => @article, :id => @comment)
:name_prefix -- define a prefix for all generated routes, usually ending in an underscore.
使用前缀来避免named routes名字冲突:
map.resources :tags, :path_prefix => '/books/:book_id', :name_prefix => 'book_' map.resources :tags, :path_prefix => '/toys/:toy_id', :name_prefix => 'toy_'
:collection -- add named routes for other actions that operate on the collection.
比如对于如下route:
map.resources :messages, :collection => { :rss => :get }
生成的named route为rss_messages,生成的helper方法为rss_messages_path,url则为/messages;rss
该参数形式为#{action} => #{method}的hash,method为:get/:post/:put/:delete/:any,如果method无所谓则可以使用:any
:member -- same as :collection, but for actions that operate on a specific member.
即:collection参数为对多个对象操作的方法,:member参数则为对单个对象操作的方法
:new -- same as :collection, but for actions that operate on the new resource action.
5,map.resource的参数以及用法与map.resources差不多,只是map.resource为一个单独的resource生成named routes
源码全在resources.rb文件里,Rails经常这样弄的一个文件几百行甚至上千行代码,可读性很不好,不过倒也不错,不用到处找关联的文件
module ActionController module Resources class Resource attr_reader :collection_methods, :member_methods, :new_methods attr_reader :path_prefix, :name_prefix attr_reader :plural, :singular attr_reader :options def initialize(entities, options) @plural = entities @singular = options[:singular] || plural.to_s.singularize @options = options arrange_actions add_default_actions set_prefixes end def controller @controller ||= (options[:controller] || plural).to_s end def path @path ||= "#{path_prefix}/#{plural}" end def new_path @new_path ||= "#{path}/new" end def member_path @member_path ||= "#{path}/:id" end def nesting_path_prefix @nesting_path_prefix ||= "#{path}/:#{singular}_id" end end class SingletonResource < Resource alias_method :member_path, :path alias_method :nesting_path_prefix, :path end def resources(*entities, &block) options = entities.last.is_a?(Hash) ? entities.pop : { } entities.each { |entity| map_resource entity, options.dup, &block } end def resource(*entities, &block) options = entities.last.is_a?(Hash) ? entities.pop : { } entities.each { |entity| map_singleton_resource entity, options.dup, &block } end private def map_resource(entities, options = {}, &block) resource = Resource.new(entities, options) with_options :controller => resource.controller do |map| map_collection_actions(map, resource) map_default_collection_actions(map, resource) map_new_actions(map, resource) map_member_actions(map, resource) if block_given? with_options(:path_prefix => resource.nesting_path_prefix, &block) end end end def map_singleton_resource(entities, options = {}, &block) resource = SingletonResource.new(entities, options) with_options :controller => resource.controller do |map| map_collection_actions(map, resource) map_default_singleton_actions(map, resource) map_new_actions(map, resource) map_member_actions(map, resource) if block_given? with_options(:path_prefix => resource.nesting_path_prefix, &block) end end end def map_collection_actions(map, resource) resource.collection_methods.each do |method, actions| actions.each do |action| action_options = action_options_for(action, resource, method) map.named_route("#{resource.name_prefix}#{action}_#{resource.plural}", "#{resource.path};#{action}", action_options) map.named_route("formatted_#{resource.name_prefix}#{action}_#{resource.plural}", "#{resource.path}.:format;#{action}", action_options) end end end def map_default_collection_actions(map, resource) index_action_options = action_options_for("index", resource) map.named_route("#{resource.name_prefix}#{resource.plural}", resource.path, index_action_options) map.named_route("formatted_#{resource.name_prefix}#{resource.plural}", "#{resource.path}.:format", index_action_options) create_action_options = action_options_for("create", resource) map.connect(resource.path, create_action_options) map.connect("#{resource.path}.:format", create_action_options) end def map_default_singleton_actions(map, resource) create_action_options = action_options_for("create", resource) map.connect(resource.path, create_action_options) map.connect("#{resource.path}.:format", create_action_options) end def map_new_actions(map, resource) resource.new_methods.each do |method, actions| actions.each do |action| action_options = action_options_for(action, resource, method) if action == :new map.named_route("#{resource.name_prefix}new_#{resource.singular}", resource.new_path, action_options) map.named_route("formatted_#{resource.name_prefix}new_#{resource.singular}", "#{resource.new_path}.:format", action_options) else map.named_route("#{resource.name_prefix}#{action}_new_#{resource.singular}", "#{resource.new_path};#{action}", action_options) map.named_route("formatted_#{resource.name_prefix}#{action}_new_#{resource.singular}", "#{resource.new_path}.:format;#{action}", action_options) end end end end def map_member_actions(map, resource) resource.member_methods.each do |method, actions| actions.each do |action| action_options = action_options_for(action, resource, method) map.named_route("#{resource.name_prefix}#{action}_#{resource.singular}", "#{resource.member_path};#{action}", action_options) map.named_route("formatted_#{resource.name_prefix}#{action}_#{resource.singular}", "#{resource.member_path}.:format;#{action}",action_options) end end show_action_options = action_options_for("show", resource) map.named_route("#{resource.name_prefix}#{resource.singular}", resource.member_path, show_action_options) map.named_route("formatted_#{resource.name_prefix}#{resource.singular}", "#{resource.member_path}.:format", show_action_options) update_action_options = action_options_for("update", resource) map.connect(resource.member_path, update_action_options) map.connect("#{resource.member_path}.:format", update_action_options) destroy_action_options = action_options_for("destroy", resource) map.connect(resource.member_path, destroy_action_options) map.connect("#{resource.member_path}.:format", destroy_action_options) end def conditions_for(method) { :conditions => method == :any ? {} : { :method => method } } end def action_options_for(action, resource, method = nil) default_options = { :action => action.to_s } require_id = resource.kind_of?(SingletonResource) ? {} : { :requirements => { :id => Regexp.new("[^#{Routing::SEPARATORS.join}]+") } } case default_options[:action] when "index", "new" : default_options.merge(conditions_for(method || :get)) when "create" : default_options.merge(conditions_for(method || :post)) when "show", "edit" : default_options.merge(conditions_for(method || :get)).merge(require_id) when "update" : default_options.merge(conditions_for(method || :put)).merge(require_id) when "destroy" : default_options.merge(conditions_for(method || :delete)).merge(require_id) else default_options.merge(conditions_for(method)) end end end end ActionController::Routing::RouteSet::Mapper.send :include, ActionController::Resources
Resources模块定义了Resource类和SingletonResource类,前者表示多个资源,后者则表示单个资源
resources方法和resource方法分别调用map_resource方法和map_singleton_resource方法
map_resource和map_singleton_resource方法分别用Resource和SingletonResource类初始化对象
最后分别调用map.named_route和map.connect来生成各自的routes
注意resources和resource方法对生成的routes作了HTTP method上的限制,如果我们在request时提供的method参数有误则会抛出RoutingError异常
这样看来,resources只不过是为我们生成了一些named routes而已,简化了我们的工作,提高了效率
我们在看源码时带着问题去看,就会非常有收获
评论
5 楼
Readonly
2007-07-11
hideto 写道
不知道你报什么错,能具体描述一下么?
不好意思,偶昨天写得匆忙,没有把错误写上来,测试代码如下:
require File.dirname(__FILE__) + '/../test_helper' require 'forums_controller' class ForumsController; def rescue_action(e) raise e end; end class ForumsControllerTest < Test::Unit::TestCase fixtures :forums def setup @controller = ForumsController.new @request = ActionController::TestRequest.new @response = ActionController::TestResponse.new end def test_named_route_path get :index path = forum_path(forums(:forum_1)) assert_equal "/forums/1", path end def test_named_route_path_with_query_string get :index path = forum_path(forums(:forum_1), :page => 1) assert_equal "/forums/1?page=1", path end end
routes.rb和你前面贴的一样:
map.resources :forums do |forum| forum.resources :topics do |topic| topic.resources :posts end end
第一个测试不带query string的没有问题,第二个测试报错是:
引用
You have a nil object when you didn't expect it!
The error occurred while evaluating nil.to_sym
不过偶后来发现这个问题和resource无关,是偶不知道named route产生的_path/_url方法如何接受query string,很好奇你的代码怎么可以运行通过
===编辑分隔线===
发现你的代码不同点了,你是用_path(:id => xxx, :page => xxx)这种方式,测试代码改成:
path = forum_path(:id => forums(:forum_1), :page => 1) 就可以通过了,偶再去看看文档或者源代码哪里有涉及到这2种方式的不同说明...
4 楼
hideto
2007-07-11
不知道你报什么错,能具体描述一下么?
3 楼
hideto
2007-07-11
对于嵌套资源:
在_url/_path方法中直接加query参数即可,比如:page参数会作为link_to方法的options参数,比如:
或
关键是controller里处理:page参数:
:page参数会被paginate方法自动捕获:
map.resources :forums do |forum| forum.resources :topics do |topic| topic.resources :posts end end
在_url/_path方法中直接加query参数即可,比如:page参数会作为link_to方法的options参数,比如:
<% link_to "page 2", topic_url(@forum, @topic, :page => 2) %>
或
<% for topic in @topics %> <%= link_to "First Page", topic_path(:forum_id => @forum, :id => topic, :page = topic.first_page) %> <%= pagination_links topic.post_pages, :window_size => 10, :link_to_current_page => true %> <%= link_to "Last Page", topic_path(:forum_id => @forum, :id => topic, :page = topic.last_page) %> <% end %>
关键是controller里处理:page参数:
post_pages, posts = paginate(:posts, :per_page => 5, :order => 'posts.created_at', :conditions => ['posts.topic_id = ?', topic.id]) topic.post_pages = post_pages
:page参数会被paginate方法自动捕获:
def paginator_and_collection_for(collection_id, options) klass = options[:class_name].constantize page = params[options[:parameter]] count = count_collection_for_pagination(klass, options) paginator = Paginator.new(self, count, options[:per_page], page) collection = find_collection_for_pagination(klass, options, paginator) return paginator, collection end
2 楼
Readonly
2007-07-10
采用resource定义产生的named routes,如果想要在后面加上额外的query string,要怎么写?
以论坛的主题贴作为嵌套资源举例子:
偶想在产生的url基础上,多加一个值,比如说分页:
/forum/1/topic/1?page=2
偶试了下这样的代码会报错:
看它的源代码和文档好像也没有牵涉到query string
以论坛的主题贴作为嵌套资源举例子:
topic_url(@forum, @topic)
偶想在产生的url基础上,多加一个值,比如说分页:
/forum/1/topic/1?page=2
偶试了下这样的代码会报错:
link_to "page 2", topic_url(@forum, @topic, :page => 2)
看它的源代码和文档好像也没有牵涉到query string
1 楼
sina2009
2007-06-27
学习了
发表评论
-
用了TextMate才知道什么叫神级Editor
2011-03-09 04:51 58020一直用Eclipse作为开发Ruby和Java项目的IDE,但 ... -
Ruby使用OAuth登录新浪微博和豆瓣
2011-01-09 12:49 4495首先需要安装oauth这个gem包 gem install ... -
使用Passenger+nginx部署Rails
2010-12-28 15:12 50551. Install Passender gem instal ... -
markItUp+rdiscount搭建Rails下可视化Markdown编辑器
2010-12-21 17:48 5491markItUp是基于jQuery的可视化编辑器,支持Html ... -
Rails3 and MongoDB Quick Guide
2010-12-10 14:13 2773Install MongoDB Download: http: ... -
基于ruby-protobuf的rpc示例
2009-08-11 11:51 41671, 安装ruby-protobuf gem instal ... -
Ruby导出xls和csv的utf-8问题的解决
2009-02-04 15:05 6878数据库数据为utf-8格式,包括中文和拉丁文等等 导出文件xl ... -
URL/HTML/JavaScript的encode/escape
2009-01-04 13:03 9373最近经常被URL、HTML、JavaScript的encode ... -
各种排序的Ruby实现
2008-11-27 14:51 4020Θ(n^2) 1, Bubble sort def bu ... -
12月5日北京RoR活动!
2008-11-26 18:38 3029又是一年过去了,Rails在国内的发展势态良好,很多使用RoR ... -
Rails程序开发的最大问题是代码规范
2008-08-28 11:56 5657使用Rails开发大型复杂B2B应用一年了,这个项目目前开发人 ... -
Web开发大全:ROR版——推荐序
2008-07-09 00:39 2438来自http://www.beyondrails.com/bl ... -
深入ActionMailer,使用Sendmail发邮件
2008-07-03 11:41 3408来自: http://www.beyondrails.com/ ... -
Rails里如何结合ExceptionNotification配置gmail账户发邮件
2008-06-19 19:56 31241,安装ExceptionNotification rub ... -
使用coderay和railscasts样式进行代码高亮
2008-06-17 00:16 2414CodeRay是一个语法高亮的Ruby库,效率很不错。 Cod ... -
Capistrano试用
2008-06-16 19:05 19741,客户端机器安装Capistrano gem insta ... -
lighttpd真垃圾啊
2008-06-04 18:38 2562使用lighttpd+fcgi跑Rails程序,文件上传会si ... -
将gem变成plugin
2008-06-04 11:27 1826有什么样的需求就有什么样的对策 当vhost上的帐号没有ge ... -
在Rails里使用ReCaptcha添加验证码
2008-06-03 15:51 42891,去http://recaptcha.net/sign up ... -
Rails里给文件上传添加progress_bar
2008-05-27 17:00 2113文件上传很慢时,UI没有什么用户提示,这样让人很费解,所以我们 ...
相关推荐
Rails::API 移除了 ActionView 和其他一些渲染功能,不关心Web前端的开发者可更容易、快速地开发应用程序,因此运行速度比正常的 Rails 应用程序要快。 Rails::API 可以用来创建只提供API服务(API-Only)的 Rails ...
Rails以其简洁优雅的语法、高效的开发速度以及良好的社区支持而闻名,这使得它成为构建现代API的理想选择之一。 ### 一、什么是RESTful API REST(Representational State Transfer)是一种软件架构风格,用于定义...
1. Rails 3.0: Rails 3是重大升级,引入了ActionController::Metal,这是一个轻量级的控制器,用于提高性能。同时,它引入了多路由引擎支持,如Rack中间件,使得与其他Web服务器的集成更加容易。此外,ActiveRecord...
使用 Rails 4 的简单聊天应用程序 - ActionController::Live 应用组件: 1 . 使用 Rails 4 ActionController::Live 的聊天应用程序 2 . 基本 LDAP 身份验证 3 . Redis 服务器集成 4 . 彪马服务器 1 . Rails 4 ...
在Ruby on Rails(Rails)框架中,开发人员经常需要实现各种用户交互功能,例如三级联动选择,这在处理如中国省市区这样的地理数据时尤其常见。这篇博客文章“Rails中应用Ext.tree:以中国的省市地区三级联动选择为...
《Rails Exporter 源码解析》 Rails Exporter 是一个用于 Rails 应用程序的开源工具,主要用于数据导出功能。源码分析将帮助我们深入理解其内部工作原理,以便更好地利用它来优化我们的应用。 一、Rails 框架基础 ...
这个Rails项目提供了学习和研究Web开发的机会,特别是对于Ruby on Rails新手,可以通过阅读和理解源代码来提升技能,了解实际应用中Rails的用法。同时,对于有经验的开发者,这个项目也可以作为一个起点,进行二次...
Ruby on Rails,简称Rails,是基于Ruby语言的开源Web应用框架,它遵循MVC(Model-View-Controller)架构模式,旨在使开发过程更加简洁高效。这个“ruby on rails 教程源码”很可能是为了辅助学习者深入理解Rails的...
《Rails 3 in Action》是2011年由Ryan Bigg撰写的一本关于Ruby on Rails框架的权威指南,专门针对当时最新的Rails 3.1版本进行了深入解析。这本书旨在帮助开发者充分利用Rails 3.1的强大功能,提升Web应用开发的效率...
Rails :: Controller :: Testing 这个gem将assigns给控制器测试的内容以及assert_template带回assigns控制器和集成测试的内容。 这些方法已中。 安装 将此行添加到您的应用程序的Gemfile中: gem 'rails-...
本书源码 博文链接:https://msnvip.iteye.com/blog/139752
《深入解析bhl_rails_solr源码》 在当今的Web开发领域,Rails框架以其高效、简洁的设计理念,深受开发者喜爱。同时,Solr作为一款强大的全文搜索引擎,被广泛应用于各类复杂的数据检索场景。当这两者结合时,便诞生...
Rails的许多特性,如ActiveRecord(ORM)、ActiveModel、ActionController和ActionView,都是为了支持这种分层架构。 压缩包中的`seanatnci-rails_space-53c56b4`可能是一个具体的Rails项目仓库,包含以下关键组成...
标题中的“Web开发敏捷之道--应用Rails进行敏捷Web开发 之 Depot代码”表明这是一个关于使用Ruby on Rails框架进行敏捷Web开发的示例项目,名为Depot。Ruby on Rails(简称Rails)是一个开源的Web应用程序框架,它...
首先,Rails 2.1.0 引入了ActionController::Resources的概念,这是对RESTful(Representational State Transfer)架构风格的强化支持。REST是一种网络应用程序的设计风格和开发方式,基于HTTP协议,强调资源的管理...
2. **ActionController**:负责处理HTTP请求,并将数据转发给相应的模型和视图。它管理着应用的业务逻辑和控制流程。 3. **ActionView**:负责生成HTML或其他类型的响应,通常与模板系统一起工作,将数据以用户友好...
通过研究这个源码,你可以深入理解Rails的工作原理,学习如何设计和实现社区网站的核心功能,如用户注册、论坛讨论、个人资料管理等。同时,这也是一个绝佳的机会去实践敏捷开发和TDD(测试驱动开发)原则,提升你的...
为了帮助读者更好地理解和应用所学知识,**Rails 4 in Action, 第二版** 包含了一系列案例研究和实战项目,例如: - **电子商务网站开发**:从零开始构建一个完整的电子商务平台,涵盖商品管理、订单处理等功能。 -...
Ruby on Rails,简称Rails,是一种基于Ruby语言的开源Web应用程序框架,它遵循MVC(Model-View-Controller)架构模式,旨在使Web开发过程更加高效、简洁。本篇将通过一个入门实例,深入探讨Rails的基本概念和核心...