elephant

赫本之后 再无女神

谈谈我对“游客参与不合理低价游也将被处理”的看法

本文内容纯属意淫,如违反法律法规请告知删除;本着意淫无罪的方针,作者不对本文承担任何责任。

近日内地游客在港遇袭身亡的事在网上炒的沸沸扬扬,各种看法纷沓而出;国家旅游局却另辟蹊径,捧出了“游客参与不合理低价游也将被处理”的决策;此决策一出,除个别“天赋异禀”人事,大家的评价出奇一致:脑残。 我实在难以理解这个决策,这到底是要保护被宰游客的合法权利,还是要对不甘心被宰的游客进行打击报复?

首先这个不合理低价游怎么判断,游客不是专业人士,怎么能区分定价是否合理?莫非国家旅游局会对各类旅游分门别类地给出“合理价位”?恐怕办不到吧。那么这决策就无异于“到使用地沟油餐厅吃饭将受到处分”一样了。游客无法区分“不合理低价游”,上当受骗就是难免的了;而旅游局的“也将受到处分(一旦被查获,不仅不能获得赔偿,还将受到处理)”将导致游客被宰后不敢举报,打碎牙齿和血吞,导致旅游市场更加混乱。

那么只能有另一个办法了:旅游局只给大型旅行社发牌照,而不在大型旅行社办理的旅游都属于“不合理低价游”。而这只能导致行业垄断或者大部分旅游进入黑市交易,穷人根本无力出游,这是国家旅游局的初衷吗?

其实解决的方法用脚趾头就能想出:规范旅游市场,根据游客反馈对旅行社进行分级、公示,对存在宰客现象的旅行社采取限期整改、吊销执照等处理,提醒游客到正规旅行社办理出游;即使存在零星宰客现象也无伤大雅。而国家旅游局人员智商肯定比我等屁民高,为什么会出台如此脑残政策?看看下一步决策,再看看受益的会是哪些群体,就一目了然了。

Requirejs

js通过script标签的默认加载方式是同步的,即第一个script标签内的js加载完成后,才开始加载第二个,以此类推,直至js文件全部加载完毕。且js的依赖关系必须通过script的顺序才能确保;而在js加载期间,浏览器将停止响应,这大大影响了用户体验,基于此,很多解决js以来和加载的方案出现,require js就是其中之一。

requirejs加载的模块,一般为符合AMD标准的模块,即用define定义,用ruturn返回暴露方法、变量的模块;requirejs也可以加载飞AMD标准的模块,但比较麻烦,这次不涉及。

require加载js主涉及以下方面:

  • script 标签data-main属性声明requirejs加载的入口模块,async=“true”(非ie) 和defer(ie)标签表明异步加载。
  • require.config配置模块对应的路径
  • require声明依赖关系

html demo

1
2
  <script src="js/require.js" defer async="true" data-main="js/main" ></script>
  <!--给出requirejs路径,声明为异步加载,指定入口模块为main.js(可省略.js)-->

main.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
  require.config({
      //声明模块的位置
      paths: {
          "jquery":"libs/jquery"
          "login" : "libs/login"
      }
      //或使用baseUrl指定所有模块的路径
      baseUrl: "js/libs"
  });
  //使用require加载模块,第一个参数为数组,即要加载的模块,将按数组顺序加载;第二个为回调函数,在全部加载完成后执行。
  require(['jquery','login'],function($,Login){
      alert("jquery and login module load success!");
      Login.do_login();
      //some else
 });

符合amd的login module定义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
  //依赖jquery的定义
  define(['jquery'],function($){
     // some definations
    function do_login(){
        $.post('/sessions/create',{uname:$("#uname").val(),
                  password:$("#password").val()},function(data){
          //some 
      });
     return {do_login:do_login};
   }
  });

//不依赖其他模块的定义
define(function(){
  //some definations
  return {xx:xx};
});

rails没有应用js加载器,一方面是新版本的rails的asset pipe会将所有的js文件打包为一个js文件,没有多个js加载的状态,另一方面turbolink使用褒贬参半的所谓pjax技术,默认链接改为ajax方式,只获取html的bod部分,head部分不变动,使js的加载只在第一次打开网站时进行。

转载请注明出处:http://me.angry-arthas.com/blog/2015/09/14/requirejs/

Angularjs浅尝1

AngularJS是为了克服HTML在构建应用上的不足而设计的。通常,我们是通过以下技术来解决静态网页技术在构建动态应用上的不足:

  • 类库 - 类库是一些函数的集合,它能帮助你写WEB应用。起主导作用的是你的代码,由你来决定何时使用类库。类库有:jQuery等
  • 框架 - 框架是一种特殊的、已经实现了的WEB应用,你只需要对它填充具体的业务逻辑。这里框架是起主导作用的,由它来根据具体的应用逻辑来调用你的代码。框架有:knockout、sproutcore等。

AngularJS使用了不同的方法,它尝试去补足HTML本身在构建应用方面的缺陷。AngularJS通过使用我们称为标识符(directives)的结构,让浏览器能够识别新的语法。例如:

  • 使用双大括号语法进行数据绑定;
  • 使用DOM控制结构来实现迭代或者隐藏DOM片段;
  • 支持表单和表单的验证;
  • 能将逻辑代码关联到相关的DOM元素上;
  • 能将HTML分组成可重用的组件。

Demo

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<!doctype html>
<html ng-app="index">
  <head>
    <title>angularjs test</title>
    <script src = "/javascripts/angular-1.0.1.min.js"></script>
    <script src = "/javascripts/controller.js"></script>
  </head>
  <body ng-controller="IndexCtrl" >
    <ul>
      <li ng-repeat="contact in contacts">
        name:,age:,hometown:,
      </li>
    </ul>
    name:<input type="text" ng-model="new_contact.name" />
    age:<input type="text" ng-model ="new_contact.age" />
    hometown:<input type="text" ng-model = "new_contact.hometown" />
    <button ng-click="add_contact()">新增</button>
  </body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
angular.module('index',[]).controller('IndexCtrl',function($scope){
  $scope.contacts = [{
      name:'陈冠希,
      age:20,
      hometown:'hk
    },{
      name:'张柏芝,
      age:22,
      hometown:'hk'}];
  $scope.reset_contact = function(){
    $scope.new_contact = {
      name:'',
      age:'',
      hometown:''
    };};
  $scope.add_contact = function(){
    $scope.contacts.push($scope.new_contact);
    $scope.reset_contact();
  };});

ng-app表明angularjs将对其标签声明内的dom进行处理,index名字是作用域名,表明属于index作用域。angular.module(‘index’,[]).controller表明在index作用域内定义controller,同理ng-controller表明其内的变量属于IndexCtrl。 ng-model声明此标检绑定在new_contact变量,angularjs控制其值随变量而改变。ng-click声明由add_contact处理点击。在li标签里面的ng-repeat=“contact in contacts"语句是一个AngularJS迭代器。这个迭代器告诉AngularJS用第一个li标签作为模板为列表中的每一个联系人创建一个li元素。由此当点击新增按钮时将输入框内所代表的model添加到contacts内,并将add_contact变量置空,而页面的显示由angularjs自动完成。 angularjs只对ng-app内的dom起作用,因此可以在任何页面使用angularjs而不破坏ng-app外的所有dom,js。 angularjs与restful后端交互非常方便,使用ngResource组件,声明好CRUD的路径、http veb,就可方便调用save,update与后端交互。 Demo

1
2
3
4
5
6
app=angular.module("index",["ngResource"])
app.factory "Contact",($resource) ->
$resource("/contacts/:id.json",{id:"@id"},{update:{method:"put"}})
$scope.contacts = Contact.query # /contacts
Contact.save $scope.new_contact #create
contact.$update #更新

转载请注明出处:me.angry-arthas.com/blog/2015/09/06/angularjsqian-chang-1/

Rake学习2

启动一个rack程序有两种方式

  • 直接使用ruby运行.rb文件,默认在8080启动服务,无日志文件
  • 使用rackup,默认在9292 启动服务,有日志文件,rackup可使用 -o 指定ip, -p 指定端口号
1
2
3
require 'rack'
app = lambda{|env| [200,{},["hello world"]] }
Rack::Server.new.server.run app
1
ruby  xxx.rb

无log输出

1
2
#test.ru
run lambda{|env| [ 200,{},["rackup start"] ]}
1
rackup test.ru

有log输出

rack会在启动时默认加载一些中间件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
 def logging_middleware
        lambda { |server|
          server.server.name =~ /CGI/ || server.options[:quiet] ? nil : [Rack::CommonLogger, $stderr]
        }
      end

        m = Hash.new {|h,k| h[k] = []}
        m["deployment"] = [
          [Rack::ContentLength],
          [Rack::Chunked],
          logging_middleware,
          [Rack::TempfileReaper]
        ]
        m["development"] = [
          [Rack::ContentLength],
          [Rack::Chunked],
          logging_middleware,
          [Rack::ShowExceptions],
          [Rack::Lint],
          [Rack::TempfileReaper]
        ]

        m
      end

包括body长度错误提示访问记录等。

rack有一个Directory的中间件,可以为目录文件生成一个web服务,今天主要研究这个。 使用很简单一句话

1
2
#test.ru
run  Rack::Directory.new "~/"
1
rackup test.ru

这样就会把home目录下的所有文件、文件夹在浏览器中显示 文件页面

rails应用中使用rake middleware即可显示所有的middleware(中间件)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
** **rake middleware
use Rack::Sendfile
use ActionDispatch::Static
use Rack::Lock
use #<ActiveSupport::Cache::Strategy::LocalCache::Middleware:0x007feef1563b90>
use Rack::Runtime
use Rack::MethodOverride
use ActionDispatch::RequestId
use Rails::Rack::Logger
use ActionDispatch::ShowExceptions
use WebConsole::Middleware
use ActionDispatch::DebugExceptions
use ActionDispatch::RemoteIp
use ActionDispatch::Reloader
use ActionDispatch::Callbacks
use ActiveRecord::Migration::CheckPending
use ActiveRecord::ConnectionAdapters::ConnectionManagement
use ActiveRecord::QueryCache
use ActionDispatch::Cookies
use ActionDispatch::Session::CookieStore
use ActionDispatch::Flash
use ActionDispatch::ParamsParser
use Rack::Head
use Rack::ConditionalGet
use Rack::ETag
run Fool::Application.routes

rails使用了rack定义的一些中间件,自定义了一些中间件,其中自定义的routes为rack程序,routes 把rails controller的action变为lambda并作为rack程序运行,在rails console里输入

1
2
2.2.1 :001 > QuestionsController.action(:new)
 => #<Proc:0x007fbe482ee0b0@/Users/killman/.rvm/gems/ruby-2.2.1/gems/actionpack-4.2.1/lib/action_controller/metal.rb:237 (lambda)> 

在config/application.rb可添加、删除、修改中间件

1
2
3
4
5
6
7
8
9
config.middleware.use(new_middleware, args)#:把新中间件添加到列表末尾;
config.middleware.insert_before(existing_middleware,
 new_middleware, args)#:在 existing_middleware
 之前添加新中间件;
config.middleware.insert_after(existing_middleware,
 new_middleware, args)#:在 existing_middleware
 之后添加新中间件;
config.middleware.swap ActionDispatch::ShowExceptions, Lifo::ShowExceptions #替换中间件
config.middleware.delete "Rack::Lock"#删除中间件

中间件的作用:

Rack::Sendfile :设置服务器上的 X-Sendfile 报头。通过 config.action_dispatch.x_sendfile_header  选项设置。 ActionDispatch::Static :用来服务静态资源文件。如果选项 config.serve_static_assets  为 false ,则禁用这个中间件。 Rack::Lock :把 env[“rack.multithread”]  旗标设为 false ,程序放入互斥锁中。 ActiveSupport::Cache::Strategy::LocalCache::Middleware :在内存中保存缓存,非线程安全。 Rack::Runtime :设置 X-Runtime 报头,即执行请求的时长,单位为秒。 Rack::MethodOverride :如果指定了 params[:_method]  参数,会覆盖所用的请求方法。这个中间件实现了 PUT 和 DELETE 方法。 ActionDispatch::RequestId :在响应中设置一个唯一的 X-Request-Id 报头,并启用 ActionDispatch::Request#uuid  方法。 Rails::Rack::Logger :请求开始时提醒日志,请求完成后写入日志。 ActionDispatch::ShowExceptions :补救程序抛出的所有异常,调用处理异常的程序,使用特定的格式显示给用户。 ActionDispatch::DebugExceptions :如果在本地开发,把异常写入日志,并显示一个调试页面。 ActionDispatch::RemoteIp :检查欺骗攻击的 IP。 ActionDispatch::Reloader :提供“准备”和“清理”回调,协助开发环境中的代码重新加载功能。 ActionDispatch::Callbacks :在处理请求之前调用“准备”回调。 ActiveRecord::Migration::CheckPending :检查是否有待运行的迁移,如果有就抛出 ActiveRecord::PendingMigrationError  异常。 ActiveRecord::ConnectionAdapters::ConnectionManagement :请求处理完成后,清理活跃的连接,除非在发起请求的环境中把 rack.test  设为 true 。 ActiveRecord::QueryCache :启用 Active Record 查询缓存。 ActionDispatch::Cookies :设置请求的 cookies。 ActionDispatch::Session::CookieStore :负责把会话存储在 cookies 中。 ActionDispatch::Flash :设置 Flash 消息的键。只有设定了 config.action_controller.session_store  选项时才可用。 ActionDispatch::ParamsParser :把请求中的参数出入 params 。 ActionDispatch::Head :把 HEAD 请求转换成 GET 请求,并处理。 Rack::ConditionalGet :添加对“条件 GET”的支持,如果页面未修改,就不响应。 Rack::ETag :为所有字符串类型的主体添加 ETags 报头。ETags 用来验证缓存。

转载请注明出处:me.angry-arthas.com/blog/2015/09/06/rakexue-xi-2/

Rake学习1

rack是ruby服务器和rack应用程序之间的一个框架,rails,sinatra都是基 于rack构建的,都属于rack应用程序。

rack提供了一个标准的接口,用于与服务器进行交互。标准的rack程序 是一个可以响应call的对象,可以是对象、Proc、lambda甚至是method, 它接收env参数(环境对象),返回一个数组,数组包括:

  • 状态(status),http响应状态码
  • 可以是hash,为http的header信息
  • 拥有each方法的对象,each返回字符串

rack通过中间件来进行扩展,即对原始的rack程序进行装饰, 在原有返回数组的基础上进一步处理,并返回rack对象

简单的rack程序

1
2
3
4
require 'rack'

app = lambda{|env|[200,{},["hello from rack"]]}
Rack::Handler::WEBrick.run app

使用中间件的rack程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
require 'rack'

class Decorator
  def initialize(app)
    @app = app
  end
  def call(env)
    status, headers, body = @app.call(env)
    new_body = "from middleware input <br/>"
    body.each{|str| new_body << str}
    headers['Content-Length'] = new_body.bytesize.to_s
    [status, headers, [new_body]]
  end
end

app = lambda{|env|[200,{},["hello from rack"]]}
Rack::Handler::WEBrick.run Decorator.new(app)

上面使用中间件的方法在使用多个时容易混乱,rack有一个Builder类可以有效管理 使用如下

1
2
3
4
5
6
7
8
9
require 'rack'
require 'decorator'

app = Rack::Builder.new{
  use Rack::ContentLength
  use Decorator
  run lambda {|env| [200, {"Content-Type"=>"text/html"}, ["hello world"]]}
}.to_app
Rack::Handler::WEBrick.run app

使用Rack::Builder的map方法,可以创建有路由的rack程序

1
2
3
4
5
6
7
8
9
10
11
require 'rack'
app = Rack::Builder.new {
  map '/hello' do
run lambda {|env| [200, {"Content-Type" => "text/html"}, ["hello"]] } end
map '/world' do
run lambda {|env| [200, {"Content-Type" => "text/html"}, ["world"]] }
end
map '/' do
run lambda {|env| [200, {"Content-Type" => "text/html"}, ["all"]] } end
}.to_app
Rack::Handler::WEBrick.run app, :Port => 3000

由于rails的全栈性,rack中间件很多,在一些高并发但业务简单的网站或api使用时 响应时间过长,在这种情况下可以考虑使用rack或者sinatra。

转载请注明出处:me.angry-arthas.com/blog/2015/09/06/rakexue-xi-1/

Instance_eval,instance_exec,class_eval,class_exec 区别

对于instance_eval和class_eval,在看ruby元编程时以为搞清楚了,但最近发现一种情况,却又让我迷糊了:

class_eval

1
2
3
4
5
6
7
8
9
10
11
12
13
class A
end
A.class_eval
  def a
    puts 'a'
  end
  define_method :b do
    puts 'b'
  end
end
A.new.a # 'a'
A.new.b # 'b'
#a和b都是A的实例方法

instance_eval

1
2
3
4
5
6
7
8
9
10
11
12
13
class A
end
A.instance_eval do
  def a
    puts 'a'
  end
  define_method :b do
    puts 'b'
  end
end
A.new.b # 'b' b为实例方法
A.new.a #  no method error!!!
A.a # ‘a’

为什么在instance_eval中 def 和define_method定义的一个为类方法(类的单件方法) 一个为实例方法呢?

要解释这个问题,首先要有以下概念: ruby在执行时,会一直追踪当前对象(receiver)即self,但也会追踪当前类(current class)。instance_eval和class_eval都会修改self和current class:

  • klass.class_eval 修改self为klass,修改current class为klass
  • obj.instance_eval 修改self为obj,修改current class为obj的eigen_class(singleton_class)。

了解了以上知识,我们知道define_method的接受者为self,class_eval和instance_eval都改变self为调用者本身,所以定义的为实例方法;而对def起作用的是当前类(current class),class_eval修改当前类为调用者本身,所以定义的是类方法,而instance_eval修改当前类为调用者的eigen_class(singleton_class),所以定义的是类方法(类的单件方法)。

另外,class_eval仅类可调用,instance_eval则类和对象都可调用。

class(instance)_exec与eval基本相似,但有以下不同:

  • _evals既可传递字符串,也可传递块,如123.instance_eval ‘to_s’
  • exec只能传递块、不能传字符串,但exec可以为block传递参数如 Class.instance_exec(‘Self’){|x|p “#{x}:self”}

至此,class_eval,instance_eval,instance_exec,instance_eval概念基本都透彻了。 对于current class有些未说清的(未研究透彻,初步判断current class 对关键字起作用,self对方法调用起作用~),回头研究完单写一篇。

The Rails Way 翻译 第一章

1 Rails 环境与配置

Rails之所以获得很多关注和参与,是因为我不去取悦那些不愿意分享问题的人。生产环境和开发环境的区别对我来说是个大问题,所以我用我所知的最佳方式解决这个问题

–dhh

Rails预制了3种标准运行模式:developments,test以及production。这些基本的模式拥有一些标准的配置比如:连接那个数据库、是否对每个请求重新加载类。如果有必要,创建你自己的运行模式也很简单。

当前的环境由环境变量RAILS_ENV指定,RAILS_ENV对应定义的运行方式并决定加载config/enviroments下定义的配置文件,你可以设置环境变量决定运行方式,或者使用默认的production模式。因为环境配置项决定Rails最重要的表现例如类文件的加载,为了真正了解Rails的运行方式,你应该理解这些环境配置。

在本章,我们以Bundler开始,Bundler是一个管理ruby程序gem依赖的工具。Bundle有一个gem清单,他可以安装清单中的gems,以及这些gems所依赖的gems。之后我们通过研究boot.rb和application.rb以及三个标准模式的配置,理解Rails的启动和请求处理过程。我们也会讲到自定义运行环境的基础知识以及为什么自定义运行环境。

本书不是以最新的Rails进行书写,为了理解本书你最少必须知道如何启动Rails程序以及理解MVC的意义。如果不符合,我建议你先看看Michael Hartl书写的Ruby on Rails Tutorial website一书。

1.1 Bundler

Bundler不是专为Rails设计的技术,但他是管理应用程序gem依赖的优先方式。Rails4依赖并默认会使用Bundler,你不必单独安装bundler这个gem

因为我们觉得你应该使用Bundler,如何不使用Bundler只是作为练习以及为不循常规的人准备。

Bundler最重要的是一次解决配置中所有的gem依赖。这不同于Rubygems和之前Rails使用的一次解决一个(one-at-a-time)的依赖解决方案,我们通过下面的难以修正的问题来说明。

假设你的系统安装了下列版本的rubygem

  • activesupport 4.0.2
  • activesupport 3.2.11
  • activemerchant 1.29.3
  • rails 3.2.11

因为activemerchant 1.29.3依赖 activesupport >= 2.3.14,所以当你用下面的gem 命令加载时

1
gem 'activemerchant', '1.29.3'

这会加载activemerchant,同时加载了最新版本的依赖gem,activesupport 4.0.2 gem,因为他比2.3.14版本高,之后当加载rails时:

1
gem 'rails', '3.2.11'

运行时出现了如下错误

can’t activate activementsupport(=3.2.11,runtime) for[“rails-3.2.11”],already activated activesupport-4.0.2 for [“activemerchant-1.29.3”]

因为activemerchant对activesupport有广泛(broader)依赖,而旧版本的Rails却依赖较窄[narrow]的依赖。Bundler依靠一次评价并获取正确的gem版本来解决这个问题

想了解有关Bundler构思出来的有趣设想请阅读 Yehuda’s blog post on the subject

1.1.1 Gemfile

定位到Rails项目的根目录下,有一个gem的清单文件-Gemfile,该文件基于ruby。Gemfile列出了Rails项目的所有依赖,包括正在使用的Rails版本。Gemfile的语法超级简单:

1
2
gem 'kaminari'
gem 'nokogiri'

把依赖写到指定一个或多个环境名作为符号的块中,就只在指定的运行环境下才加载这些依赖:

1
2
3
4
5
6
7
8
9
10
11
12
13
group :development do
    gem 'pry-rails'
end

group :test do
    gem 'capybara'
    gem 'database_cleaner'
end

group  :development, :test do
    gem 'rspec-rails'
    gem 'factory_girl_rails'
end

如果你从Rails3升级,记住Rails4不再为asset pipeline依赖的包使用assets分组,你需要把移除assets group分组

gem指令第二个参数为可选的,他指定了需要gem的特定版本,忽略该参数会自动获取最新稳定版本的gem,可能不是可用的最新版本,你需要指定确切的版本才能加载特定版本或者预览版。

版本参数的格式你可能已经熟悉

1
2
3
4
gem 'nokogiri', '1.5.6'
gem 'pry-rails', '> 0.2.2'
gem 'decent_exposure', '~> 2.0.1'
gem 'draper', '1.0.0.beta6'

你可以在RubyGems documentation 找到版本字符参数的完整说明

有时候gem有特定的需求才能使用,不同于gem repo中的声明,这此种情况下,require选项很容易地解决

1
gem 'webmock',require:'webmock/rspec'

1.1.1.1 从git库加载gems

到现在为止我们已经学会了从http://rubygems.org 加载gem。我们也可以从源代码库加载特定的gem,只要他的根目录下有.gemspec文件。只需在调用gem时添加:git选项。

1
gem 'carrierwave', git: 'git@github.com:carriverwaveuploader/carrierwave.git'

如果gem的源代码库是在Github上托管并未public,你可以使用:github这个简便选项

1
gem  'carriverwave', github: 'carriverwaveuploader/carrierwave'

也支持二进制或者c扩展的gemspec

1
gem 'nokogiri', git: 'git://github.com/tenderlove/nokugiri.git'

如果gem的源代码库根目录下没有.gemspec文件,你必须指定确定的版本

1
gem 'deep_merge' ,'1.0', git: 'git://github.com/peritor/deep_merge.git'

如果gem源代码库有多个.gemrspec文件,你可以指定使用特定的ref,branch,或者tag:

1
2
3
gem 'rails', git 'git://github.com/rails/rails.git', ref: '4aded'
gem 'rails', git 'git://github.com/rails/rails.git', branch: '3-2-stable'
gem 'rails', git 'git://github.com/rails/rails.git', tag: 'v3.2.11'

1.1.1.2 从文件系统中加载gems

使用 :path选项,你可以使用本地开发中的gem

1
gem 'nokogiri', path: '~/code/nokogiri'

1.1.2 安装gems

每次修改Gemfile,或者更具体地说,如果引入了未安装的依赖,运行bundle来确保Gemfile的所有依赖都可用。

1
2
$ bundle install
#some information

安装指令会在不导致冲突的情况下安装Gemfile下的所有gems至最新版本 你可以使用 –without 选项来不安装指定运行模式下的gems

1
2
$ bundle install --without development test
$ bundle install --without test

1.1.3 gem锁

每次运行 bundle install 或者 bundle update,Bundler计算所有的依赖关系并将结果存在一个名为Gemfile.lock的文件中。从这点看来,Bundler只会加载Gemfile锁定时所指定版本,你知道可以正确运行的gems。

Note Gemfile.lcok文件应该加入版本控制中,以确保每个电脑运行该程序时使用指定的相同版本的gems

为了说明这点的重要性,想象一下在发布时Gemfile.lock丢失。因为依赖关系不存在了,Bundler只能在发布的机器上重新指定Gemfile中的gem版本,这会导致安装你未测试的新版本的gem,导致无法预料的问题。

1.1.4 打包gems

你可以在你的rails应用程序中把vendor/cache下所有的gem打包

1
$ bundle package

在拥有打包的gems的应用中运行 bundle install –local会安装包内的gems,而不会连接rubygems.org或其他gems源。你可以在发布时使用这点来避免外部的依赖、或者你依赖在public代码库不可用的私有gems。

确保gem依赖在非rails脚本中可用

非Rails脚本必须运行过Bundle exec来获得正确的初始运行环境。 $ bundle exec guard Rails 4在生成新项目时会为rails执行环境在bin目录中生成binstubs,binstub是包含了bundle运行上下文执行环境的脚本。这意味着你不用每次执行都要加上bundle exec。binstubs是rails 4的一等公民,应该加入版本控制代码中。 默认情况下,下边的stub在每个rails新项目中都可用: * bin/bundle * bin/rails * bin/rake * bin/spring

从rails 3升级 如果你从rails3升级且在以前使用Bundler生成过binstubs,你必须运行下列命令以升级binstubs

1
2
3
bundle config --delete bin#关闭Bundlers的stub生成器
rake rails:update:bin #使用rails4的新的指令
git add bin #把bin文件加到版本控制中

使用bundle binstubs some-gem-name可以为bundler加入可执行的binstub,示例如下:

1
$ bundle binstubs guard

可在bin目录下创建guard bistub:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/usr/bin/env ruby
#
# This file was generated by Bundle.
#
# The application 'guard' is installed as part of a gem,and this file is here to facilitate(正式) running it
#
require 'pathname'
ENV['BUNDLE_GEMFILE']  ||=
File.expand_path("../../Gemfile", Pathname.new(_FILE_).realpath)

require 'rubygems'
require 'bundler/setup'

load Gem.bin_path('guard','guard')

使用binstubs,bin目录下的脚本可以直接运行

1
$ bin/guard

1.2 rails启动以及应用配置

当你使用rails启动进程(比如运行rails server)以处理请求时,首先执行的是 config/boot.rb的加载,在rails栈的启动中,将会涉及三个文件: * boot.rb Bunlder和加载路径的建立 * application.rb 加载rails的gems,特定运行环境下的gems,配置应用程序 * enviroment.rb 执行所有的安装

1.2.1 application.rb

config/application.rb是rails程序配置的所在,他是在config/enviroment.rb之前唯一被加载的。 让我们一步一步看看创建rails程序的默认配置。顺便说下,改变这些配置文件需要重启程序才能起作用。

对hash进行递归操作

将hash {a:1,b:{c1:2,c2:3,c3:{d1:4,d2:5},e:6}}转化为下面字符串 a = 1 , b_c1 = 2 , b_c2 = 3 , b_c3_d1 = 4 , b_c3_d2 = 5 , b_e = 6

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
hash = {a:1,b:{c1:2,c2:3,c3:{d1:4,d2:5},e:6}}

def unfold(hash,p="")
  arr = []
  hash.each do|k,v|
    if v.instance_of? Hash
      arr += unfold(v,p+k.to_s+"_")
    else
      arr << "#{p}#{k.to_s} = #{v.to_s}"
    end
  end
  arr
end

puts unfold(hash).join " , "

递归操作一般用于将问题复杂度降低,但感觉ruby的栈使递归无法发挥,稍微大点的递归就会导致栈溢出,之前写的递归版本的插入排序,同样的思路在java/java/c#都很好用,但在ruby中就是不行,要么调整栈的大小,但运行缓慢,很多时候总是得换为循环,感觉应该不是算法的问题,不知道什么时候ruby才能解决这个问题


之前写的插入排序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
def insertSort(left=[],arr)
    return left unless (x=arr.pop)
    left.each_with_index do |l,i|
        if l>x
            left.insert i,x
            return insertSort left,arr
        end
    end
    left.push x
    return insertSort left,arr
end
arr=[]
arrE=(1..10000).to_a
10000.times do |t|
    tmp=rand(arrE.count)
    arr.push (arrE.delete_at tmp)
end
puts (insertSort arr)

Constructor && Prototype

每个对象都是个散列表 每个原型都有相关连的函数,每个函数都有相关联的原型

1
2
3
4
var A = function(){};
var p = A.prototype ;
var c = p.constructor;
A==c

函数的对象的constructor就是该函数(未修改prototype)

1
2
3
4
function A() {
}
var a = new A();
a.constructor == A

修改函数的prototype后其对象的constructor为新的prototype的constructor

1
2
3
4
5
6
function A(){};
function B(){};
A.prototype = new B();
console.log((new A()).constructor); //为function B(){}
A.prototype.constructor = A;
console.log((new A()).constructor);//为function A(){}

{}(对象直接量)对象是function Object(){}的对象

Super_method

1
2
3
4
5
6
7
8
9
10
11
class A
  def show
    "a method"
  end
end

class B<A
  def show
    "b method"
  end
end

怎样用类B的对象调用A的show方法?

1
B.new.method(:show).super_memthod.call  #ruby 2.2可用

2.2之前

1
2
3
4
5
6
7
8
9
10
11
12
13
class A
  def show
    "a method"
  end
end

class B<A
  alias_method :super_show ,:show
  def show
    "b method"
  end
end
B.new.super_show