20 September 2014

第一章


使用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属性。

创建静态页面的方法:

  1. 通过static pages
  2. 通过路由中的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。

$ rails generate integration_test static_pages
invoke  rspec
create  spec/requests/static_pages_spec.rb

RSpec 和 Capybara的设计,多用generate命令生成一些测试或本书中的方法,所以代码生成是一个很重要的方面。it…do开头的代码块,其本质就是方法调用。

运行测试命令:

rspec spec/requests/static_pages_spec.rb

结果出现了循环require的错误,说明Gem包安装的不彻底。 结果,还是对RSpec这样的测试技术不太了解,书中描述的和自己安装的有些区别。 重构:测试变绿,尽情重构。标签对**搜索引擎优化**很重要。 通过句法验证的页面,静态HTML。

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
  • mail
  • 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