RoR指南 学习笔记
第一章
使用Ruby On Rails进行web开发,应该从哪里开始。活跃的Rails教学体系。
web开发,Internet开发软件,HTML,CSS,数据库,版本控制,测试和部署,线性TDD结构。静态页面,动态页面(带有JS操作DOM)。
RoR,MIT协议,web开发DSL,生成HTML,创建数据模型,URI路由,快速跟进web领域的最新技术和框架(REST,Rails和Merb[Yahuda,jQuery] 项目的合并)。
脚手架,scaffold–生成大量复杂且冗余的代码,实际开发中,前辈建议不使用scaffold。易于理解,又能灵活运用。
先测试,后开发。 高级Rails资源: RailsCasts优秀的视频教程。
性能需要在网站中优化,而不是在框架中。网站确实很慢,需要优化,但是优化前需要测量出到底哪里慢,所以度量确实是个非常的重要的事情。
web开发浏览器:Firefox,Safari,Chrome。学习工具需要花费的时间是正常的,工欲善其事,必先利其器。浏览器对web开发的友好性,Firebug这样强大的工具。Ajax调试,console.log。
软件的易用性,安装软件。web应用程序也是的,易用是一个很重要的因素,强大易用。
使用Rspec来测试,app/assets文件夹,asset pipeline组织CSS和JavaScript等资源。Bundler安装程序所需的gem,自动化安装gem包。
MVC:表现和业务逻辑分开,HTML中瘦客户端的需求,显示端全部交由web浏览器处理。
Git 全局忽略,~/.gitignore_global,运用.gitignore忽略文件。git的分级忽略策略。
git remote add origin git@github.com:
/xxx.git git push -u origin master
-u的含义:git set upstream。 Github根据文件的内容描述项目而不是Rails框架,修改Readme.md-描述介绍自己的项目。
git ci -a -m”以后可以考虑使用这个命令”
常用的git 命令,branch, reset, checkout, commit,push ,pull等。
部署:尽早部署,尽快部署。Phusion Passenger(Apache和Nginx的网络服务的模块)。所以,网站的服务器端到底使用的是何种部署方式。
Heroku可以正常运行任意使用Rack中间件的Ruby web程序 ,Rack: web框架和web服务器之间提供了标准的接口。使得编写的web应用程序可以跨web服务器。
heroku gem包,heroku命令(add:keys, open),国外的安装部署等一整套的功能提供工具,使用postgre数据库。
scaffold用来构建好的演示程序。
对象模型+(控制器+视图)== 构成资源 ,资源需要使用复数。
注意:脚手架后面跟着的名字和模型一样,是单数形式,而资源和控制器是复数形式,因此是 User 而不是 Users。单数形式和复数形式在link_to 中的路由辅助方法中作用和行为不同。
Unix程序安装过程:./configure && make && sudo make install ,unix中的进程的智慧。
Rails的MVC的流程要点:控制器是整个应用程序的枢纽
RESTful的路由:index,show,new,create,edit,update,destroy。某些动作映射到相同的地址上,区别在于HTTP请求动作(GET/POST)不同。
REST意味着系统的中的组件会被模型化,变成资源,可被create,read,update和delete。
Active Record,attr_accessible方法,只读,只写,读写。
脚手架(scofford)生成的资源存在一些缺陷:
- 没有数据验证(Validation)
- 没有用户身份验证机制
- 没有测试(CSS),生成的基本测试太粗糙
- 没有布局,没有共用的样式和网站导航
- 限制和数据验证,不同数据模型之间的关联。 用户微博和用户之间的关系:has_many和belongs_to的关联。
使用控制台(Rails应用程序交互的工具)检查模型之间的关系,这就是Rails中程序未开发,程序员已经可以同模型进行交互。 ::区分间隔作用范围,类,方法,块都是作用域的范围。
ActiveRecord::Base是ActiveRecord的基类,和数据库通信(建立连接,提交查询或修改命令,获取数据)。
ActionController::Base–>ApplicationController。
第三章:基本静态页面(大型示例程序)
设置Rails使用RSpec而不是Test::Unit,关于测试用具的使用,可以提高生产力。可以通过如下命令:rails generate rspec:install
运行rspec后,生成了如下的这些文件:
create .rspec #测试配置文件
create spec
create spec/spec_helper.rb
create spec/rails_helper.rb
备注:gem源需要修改为淘宝的源(http://ruby.taobao.org),此外,使用新的端口号启动Rails服务器(-p 5000),避免端口冲突。
静态文件的请求不需要通过Rails,也就是说,不需要通过路由,直接输入就能显示,并且其优先级比路由要高。Rails动作比静态文件定义的URI要强大。
<!DOCTYPE html> 是 HTML5的特色,title标签,body部分。HTML元素的data属性。
创建静态页面的方法:
- 通过static pages
- 通过路由中的pages选项
rails generate controller StaticPages home help –no-test-framework
#–no-test-framework 选项用来禁止生成RSpec测试方法。rails命令行程序不是特别熟。
======================================旁注========================================== 如何撤销操作,可以通过Rails destroy命令,该命令和rails generate命令的作用是相反的。
generate controller|model vs destroy controller|model
迁移操作: rake db:rollback/mirgrate
rake db:migrate VERSION= 0 #回到了迁移前最初的状态
可逆的操作,Rails程序,互操作性
路由的get方法,HTTP动词的实现:GET(可缓存,这一点很重要),POST(浏览器,表单,创建,搜索提交),PUT(更新),DELETE(销毁)。浏览器并未内建put和delete的请求,Web框架模拟URL实现。
Views中默认存在layouts文件夹,layouts负责这个应用程序的布局,应用程序的特定部分可能需要特定的布局。布局的结构: 1. 静态资源标签 2. yield和content_for 3. 局部视图
<%= yield :head %>
这种称之为具名yield,可以通过content_for方法向其插入内容。
3.1 关于测试
直观测试应用程序表现的方法,集成测试(integration test),RSpec request spec–模拟(simulate)用户在浏览器中操作,Capybara自然语言句法(natural-language syntax),测试优先,Rspec运行测试。
所谓的自然语法,其实就是英语语法。
####3.1.1 测试驱动开发
失败的测试-红,通过测试-绿。Red,Green,Refactor。
RSpec 和 Capybara的设计,多用generate命令生成一些测试或本书中的方法,所以代码生成是一个很重要的方面。it…do开头的代码块,其本质就是方法调用。
运行测试命令:
rspec spec/requests/static_pages_spec.rb
结果出现了循环require的错误,说明Gem包安装的不彻底。 结果,还是对RSpec这样的测试技术不太了解,书中描述的和自己安装的有些区别。 重构:测试变绿,尽情重构。
3.1.2 嵌入式Ruby
去掉重复代码,网页动态添加内容的主要模板系统(另一套为haml,模板系统对应模板的处理引擎)。静态页面的代码充满了重复,Don’t Repeat Yourself。
<% %>
和<%= %>
都是会执行其他代码的。content_for不能很好的和asset pipeline(压缩打包web应用程序的资源)中工作。 application.html.erb中的内容:
<!DOCTYPE html>
<html>
<head>
<title>SampleApp</title>
<%= stylesheet_link_tag "application", :media => "all" %>
<%= javascript_include_tag "application" %>
<%= csrf_meta_tags %>
</head>
<body>
<%= yield %> #执行代码块
</body>
</html>
Rspec每次都会加载整个Rails环境,
stylesheet_link_tag,一个很重要的事情就是,Rails提供的诸多的辅助方法,回想之前写代码都不参考API文档的,就这样,也度过了两个月的光景,切为不可。从今天起,每日打开API文档,学习研究文档。
javascript_include_tag,添加对js库的应用。
可以自行编写辅助函数,根据辅助函数的使用范围,将其组织到不同的模块中,各个独立的控制器helper类中,application的helper方法。
第4章 Rails之后的Ruby
Rails控制台学习Ruby,同Rails应用程序交互的命令行,基于irb开发,具有Ruby的全部能力。Ctrl+C结束当前命令,Ctrl+D退出控制台。单双引号创建字符串,双引号的插值操作(#),单引号是真正的字面值。
Ruby中的一切皆对象,对象通过方法调用传递消息。布尔值的相关操作符:&&、 | 、!。Nil是除了false以外,唯一一个布尔值为假的,Ruby非显式返回最后一个语句的值。 |
URI通过路由规则映射到动作上,控制器中的帮助函数可在视图中使用。
Web应用程序一般都是处理字符串(更恰当的说是文本),也需要生成字符串的数据类型。split,join。Range通常用来获取一组数组元素,枚举类型-块(闭包,匿名函数) 。 **表示幂,Hash(作为最后一个参数时,花括号可省),Symbol(Ruby特有的数据类型,易于比较,同符号表有关系),数组。
inspect:自省方法; 特殊函数引入样式表:stylesheet_link_tag。
4.1 Ruby的类
Ruby,其他面向对象编程语言,类组织方法,实例化创建对象。Ruby拥有可以修改内置类的强大功能-开放类。
S.palindrome? #可以响应palindrome方法。JavaScript:内置类原型对象扩展类(prototype.js)。
控制器动作无返回值,动作的目的是渲染网页(render某个具体的页面)。Rails(独特的视角)是用Ruby写的,但其不是Ruby。控制器的继承关系,理解层次(Application以及具体的个定控制器)。
attr_accessor :name, :email #getter和setter方法。使用哈希初始化对象,mass assignment-并行赋值,最大话单行语句的表现里,Rails中很常用。
第5章 布局
Bootstrap框架(web设计框架),自定义样式表,局部视图(partial),Rails路由,asset pipeline,RSpec技术重构,注册。
布局中添加结构,CSS基本样式,局部视图保持布局文件结构清晰。用户界面的统筹安排,网页构思图(mockup)-线框图,草图设计,产品经理的活。
思考:ERb模板和最终生成的HTML的关联。
程序中使用了HTML5,IE浏览器的条件注释,HTML5 shim(JS解释HTML标签,为了能在IE中使用HTML5的标签和属性)。
HTML元素可以指定ID和class,CSS样式使用,class可以多次使用,id只能用一次,可为同一元素指定多个class。无论是ID,还是Class,在css的样式控制中都很重要。
在Application的erb中,很多的样式在Bootstrap中具有特殊的意义。link_to第一个参数是链接文本,第二个参数是链接地址,第三个是可选的Hash表-使用hash参数相当的灵活。
Alt属性内容在图片(img_tag)无法加载时显示,HTML标准必须,Rails默认加上。
Boostrap框架:Boostrap-sass gem包,Boostrap本身使用less动态生成样式表,Rails的asset pipeline默认支持Sass,Boostrap-sass将LESS转换成Sass 格式。Asset pipeline中也可使用LESS(less-rails-bootstrap)。
app/assets/ 目录是asset pipeline中一部分。此外,vendor/assets也是其中的一部分。
问题:在使用boostrap的时候报错了:Sass::SyntaxError in Static_pages#home,说是找不到boostrap,找了一圈,没找到解决方法,重新看了一下,看到说,需要重启一下服务器,于是就重启了一下服务器,发现样式显示了,但和书上有些不同,修改了一下’bootstrap-sass’的版本之后,就一致了。这里,gem包版本的精确控制很重要。
一些与boostrap相关的gem包:
- bootstrap-sass 以及 less-rails-bootstrap,less-rails
- twitter-bootstrap-rails
- Therubyracer # ruby封装的v8 javascript执行引擎
在全局引入样式和JS,需要在application.js和application.css中require相关的文件。
/*...*/
为css规则添加注释,css样式规则可通过id,class和Html标签(a, buttton, input之类)来指定。
5.1 局部视图
在shared目录中存放不同视图共用的局部视图,or 把每个页面都会用到的视图放在layouts目中,在shared中放置辅助的局部视图。这两种方式对运行都无影响。最终生成的html都是一样的。
header和footer都是HTML5 新增的标签。
5.2 Sass和asset pipeline
Asset pipeline可以显著提高CSS,JavaScript和图片等静态资源文件的生成效率。三个需要了解的特性:资源目录,清单文件(manifest),预处理引擎(preproccessor engine)。
Rails 3.1之后,静态文件的三个标准目录:
- app/assets:存放当前应用程序用到的资源文件
- lib/assets:存放开发团队自己开发的代码库用到的资源文件
- vendor/assets:存放第三方代码库用到的资源文件
清单文件告述Rails如何将其合并成一个文件(sprockets只适合CSS和JavaScript,不会处理图片)。Sprockets通过注释加载相应的文件:
- require_tree 会将app/assets/stylesheets目录下所有的CSS文件都引入应用程序样式表。
- require_self 会将application.css这个文件也加载进来。
预处理引擎:sass,coffee,erb。预处理引擎是可以连在一起使用的,比如:foobar.js.erb.coffee,从右向左处理,CoffeeScript处理器会先执行,所以,最后生成的是js文件。
Asset pipeline所有的JS代码集中到一个JavaScript中并执行压缩(zip压缩)。
Sass编写css的语言,scss扩展,多方增强CSS的功能(嵌套,变量和Mixin):
- 嵌套样式:编写果然更加的方便,减少重复出现的标题头。
- 变量:代替重复出现的样式值(颜色等)。LESS中使用@定义变量,Sass使用$定义变量。
Rails习惯使用命名路由(named routes)来指定连接地址,也就是所谓的xxx_path和xxx_url。
页面测试:测试标题,css样式之类。路由测试,通读路由文件。
rails generate controller Users new –no-test-framework #生成控制器
注意:controller之后的名称的单复数与控制器名字有关。模型(model)和脚手架(scoffold)生成器都会自动创建相应的迁移。
安装annotate 包,得到annotate命令,在模型文件中添加注释,说明模型结构,命令格式:annotate –position before #可以获取数据库schema信息。
attr_accessible标明数据库中可访问的属性,默认模型中所有的属性都是可访问的,attr_accessible避免mass assignment漏洞。
通过控制台与模型进行交互,了解Active Record的功能,js的sandbox模式。
第六章 用户模型
为网站的用户创建一个数据模型,以及存储数据的方式。用户注册功能,用户资料页面,保护页面–完整的Rails登录和用户验证的页面。功能完整的验证系统,更好的理解验证系统(比如devise)。
Active Record(关系型数据库交互的Ruby库)将用户和数据库隔离开来。
model和controller生成器彼此独立,scofford生成器貌似可以将其整合起来。New的对象保存在内存中,save将其存到数据库(磁盘对应的文件)中。
Active Record中提供的数据操作的方法:new,create,save,find,update,destroy。这些方法都可以接受{}的参数。数据库的操作也无非提供了增删查改这四类的操作。
find_by_email可能效率不高,这需要通过索引来解决。常见的数据库查询方法:first,last,all。 User.reload.email–重置更改的属性。 更新数据:update_attributes - 更新特定属性。
6.1 数据验证
几种常见的数据验证:存在性-present,长度-length,格式,唯一性-unqiue 。保证测试检测真正的内容。
rails console –sandbox #沙箱化的控制台
save-valid?-errors.full_messages
do…end和 { } 效果等价。正则表达式是一门艺术,http://www.rubular.com/ 在线ruby正则表达式编辑器。^$ 和\A\z的头和尾。Email地址是不区分大小写的。
Vim中,非插入模式中,#(shift+3)某个单词会找出当前文件中所有相同的字符。
仅在模型字段中设置的,唯一性验证不足。
问题:多次提交请求,存在两条Email一样的地址。解决方案:在数据库中为email建立索引。
Rails风格:每次修改数据库结构都使用迁移(rails g migration name生成空的迁移文件,rake db:migrate运行迁移,注意此时打开rails控制台会锁住数据库)。在存入数据库之前,将Email地址转换为全小写的字母形式。回调函数(callback),Active Record对象生命周期, before_save之类。
数据库索引:创建数据库列时,考虑是否需要对数据库做索引。如果不做索引,就要全表扫描(full-table scan)性能压力将会很大。
6.2 安全密码
用户记密码,数据库存加密(bcrypt-ruby)后的密码,获取密码加密对比验证。
添加新的数据库字段:rails generate migration add_password_digest_to_users password_digest:string。
添加password和password_confirmation属性,设置非空,定义authenticate方法,最新的Rails已经集成好了。password_digest字段中存放的是加密后的密码。
authenticate方法,密码不正确会返回false。
##第7章 用户注册 —-
表单,提交用户注册时信息,REST架构。Rails内置debug方法和params变量-哈希数组。
debug(params) if Rails.env.development? #显示在页面之间传递的参数
Rails的三种环境,production,test以及development,可以自己定义新的环境。框架的定义的变量:Rails.xxx(176种方法)。本地服务器和控制台都默认使用的开发环境。
将数据视为资源,可以创建、显示、更新、删除。
REST约定:资源一般是由资源名加唯一标识符表示的。资源对应的路由的名称:
HTTP请求 | URI动作 | 具名路由作用 |
---|---|---|
GET /users | index | users_path 显示所有用户的页面 |
GET /users/1 | show | user_path(user) 显示某个用户的页面 |
GET /users/new | new | new_user_path 创建(注册)新用户的页面 |
POST /users | create | users_path 创建新用户 (表单提交) |
GET /users/1/edit | edit | edit_user_path(user) 编辑 id 为 1 的用户页面 |
PUT /users/1 | update | user_path(user) 更新用户信息 |
DELETE /users/1 | destroy | user_path(user) 删除用户 |
测试使用的gem包:factory_girl-用于清空数据中的数据 , gayabra,rspec。
BCrypt慢加密算法:延长测试运行时间,但是加密效果更好。
添加Gravatar头像, gravatar_for方法。
使用aside添加侧边栏。
rake db:reset 将控制台中的数据删除掉
注意: 将数据库清除掉后,需要重启服务器和控制台,才能真正的看到效果
Rails使用authenticity token来防止cross-site request forgery, CSRF,详细参考http://stackoverflow.com/questions/941594/understand-rails-authenticity-token
form表单,action和method属性。
params Hash中包含了每次请求的信息,对调试的作用非常的巨大。form_for表单中的输入框的命名与提交的params关系密切。
<%= form_for(@user) do |f| %>
<%= f.label :name %>
<%= f.text_field :name %>
<%= f.label :email %>
<%= f.text_field :email %>
<%= f.label :password %>
<%= f.password_field :password %>
<%= f.label :password_confirmation, "Confirmation" %>
<%= f.password_field :password_confirmation %>
<%= f.submit "Create my account", class: "btn btn-large btn-primary" %>
<% end %> > 注意: 这里就是一个与模型关系密切的表单。模型对象保存失败后,errors.full_messages中包含了失败的具体信息。
将错误信息编写成测试。pluralize是ActionView::Helpers::TextHelper中提供的方法。将提供的数字和参数文本正确的单复数化。
Rails 还会自动把有错误的字段包含在class为field_with_errors的div元素中。
redirect_to中可以使用@user,而不必使用user_path,这是Rails的智能之处。
Flash消息-显示欢迎之类的消息。Flash消息的代码加入应用程序的布局,整个网站在需要的时候会显示消息。
登录和退出
登录功能,根据登录状态和当前用户身份定制网站内容,安全机制,
session是两台电脑之间的半永久性连接,可将其视为符合REST架构的资源-CRUD,存在多种失效机制。和模型资源的区别: 模型资源通过数据库持久的存储数据,session则利用cookie(简单文本)存储数据。cookie验证机制。
Sessions控制器
登录和退出由Session控制器中相应动作处理,表单在new动作中处理,登录向create发送POST请求,退出向destroy发送DELETE请求。
rails generate controller Sessions –no-test-framework
注册表单和登录表单的区别: 程序中没有Session模型,没有@user变量,需要提供更多信息。
form_for(:session, url: sessions_path)
表单创建方法: form_for
以及form_tag
, form_for
表单的参数 form_for :person , url: “/xxx” 。:person表示params哈希下的名为person的子哈希,url表示相应的动作。
身份验证的两个方法: 1. Active Record提供的User.find_by_email
2. has_secure_password 提供的 authenticate 方法
登录功能:记住我,登录功能超出传统MVC架构,一些函数需要同时在控制器和视图中使用。Ruby的module功能,打包函数。通常辅助函数只能在视图中使用。
Rails session把id保存在remember token中,cookie, User.find(session[:remember_token])
rails generate migration add_remember_token_to_users
记忆权,足够长的随机字符串。SecureRandom#urlsafe_base64
长度为16, 由 A-Z、a-z、0-9、下划线(_)和连字符(-)组成。
cookies Hash和current_user方法。cookie的元素:cookie指定文本,expires指定cookie失效器。cookies以文本的形式保存在浏览器中。
存在浏览器中的验证和服务器通讯时,会导致会话劫持(Firesheep-Firefox的扩展)。
= 操作符非常能体现Ruby的特性,灵活方便。 |
问题:Routing Error uninitialized constant ApplicationController::SessionHelper
找了半天,以为是自己路由的辅助方法写错了,找了半天。最后在ApplicationController中发现,自己include的类的方法写错了,不是SessionHelper,而是SessionsHelper。此外,这里报的是uninitialized constant,这里其实表明,class定义的就是名为类名的常量。
浏览器本身并不支持发送 PUT 请求,Rails在POST请求中使用隐藏字段伪造PUT请求。Active Record通过new_record? 方法检测用户是新创建还是已存在于数据库中。
Bootstrap为flash[:notice]、flash[:success]和flash[:error]都提供了样式。
附录
这个小小的应用程序中使用了这样的一些Gem包,感觉,太过夸张了,居然依赖了这么多的Gem包:
- rake : make类似的工具
- i18n : 国际化需求
- multi_json 1.10.1
- activesupport, activemodel, actionpack, actionmailer, activerecord, activeresource, rails, railties :这些是Rails的组成部分
- builder : json构建gem包
- erubis : erubis是erb模板处理引擎
- journey : 日志处理??
- rack, rack-cache, rack-test rack-ssl: rack相关的组件。
- hike
- tilt
- sprockets相关的gem: uglifier, therubyracer(libv8), coffee-script(execjs)
- javascript相关的工具: coffee-script-source, execjs, coffee-script, jquery-rails
- mime-types
- polyglot
- treetop
- arel
- tzinfo
- 资源相关gem包: bootstrap-sass, sass, sass-rails, twitter-bootstrap-rails, less, less-rails
- bundler
- mini_portile
- nokogiri :
- xpath : 客户端中用来提取xml中数据的gem包。此时,ActiveRecord的
to_xml()
并不适用时,服务器端可能使用REXML或xml生成器。 - json : ActiveRecord提供的from_json和to_json,依赖HTTP的两个方法: GET和POST。
- rdoc : ruby的文档构建工具
- thor - rails中命令行生成器构建工具
- commonjs
- diff-lcs
- rspec相关: rspec-support, rspec-core, rspec-expectations, rspec-mocks, rspec-rails, capybara
- sqlite3 数据库驱动程序
复杂了,太多东西需要了解,一个简单的东西,搞得这么复杂一点都不好,所以,我的想法是缩小,简化,提高性能。
后来,看到一篇文章说,为毛存在这么多Gem,这就是Ruby社区的不重复造轮子(DRY)原则的体现。所以,品种繁多的gem包变成了一个个需要学习的对象。
傲娇的使用Disqus