今天在rails中使用 returning 的时候 log 打出warning:
Object#returning has been deprecated in favor of Object#tap
环境是 ruby 1.9.2 + rails 3.0.3
从warn上看是returning不建议使用,建议使用tap方法,那么tap方法和returning方法有什么不同
Object#tap 方法是 ruby1.8.7 以后加入的,Object#returning 方法是 rails添加的
rails 3.0.3 returning 源码:here
rails 2.3.5 returning源码:
class Object
# Returns +value+ after yielding +value+ to the block. This simplifies the
# process of constructing an object, performing work on the object, and then
# returning the object from a method. It is a Ruby-ized realization of the K
# combinator, courtesy of Mikael Brockman.
#
# ==== Examples
#
# # Without returning
# def foo
# values = []
# values << "bar"
# values << "baz"
# return values
# end
#
# foo # => ['bar', 'baz']
#
# # returning with a local variable
# def foo
# returning values = [] do
# values << 'bar'
# values << 'baz'
# end
# end
#
# foo # => ['bar', 'baz']
#
# # returning with a block argument
# def foo
# returning [] do |values|
# values << 'bar'
# values << 'baz'
# end
# end
#
# foo # => ['bar', 'baz']
def returning(value)
yield(value)
value
end
# Yields <code>x</code> to the block, and then returns <code>x</code>.
# The primary purpose of this method is to "tap into" a method chain,
# in order to perform operations on intermediate results within the chain.
#
# (1..10).tap { |x| puts "original: #{x.inspect}" }.to_a.
# tap { |x| puts "array: #{x.inspect}" }.
# select { |x| x%2 == 0 }.
# tap { |x| puts "evens: #{x.inspect}" }.
# map { |x| x*x }.
# tap { |x| puts "squares: #{x.inspect}" }
def tap
yield self
self
end unless Object.respond_to?(:tap)
# An elegant way to factor duplication out of options passed to a series of
# method calls. Each method called in the block, with the block variable as
# the receiver, will have its options merged with the default +options+ hash
# provided. Each method called on the block variable must take an options
# hash as its final argument.
#
# with_options :order => 'created_at', :class_name => 'Comment' do |post|
# post.has_many :comments, :conditions => ['approved = ?', true], :dependent => :delete_all
# post.has_many :unapproved_comments, :conditions => ['approved = ?', false]
# post.has_many :all_comments
# end
#
# Can also be used with an explicit receiver:
#
# map.with_options :controller => "people" do |people|
# people.connect "/people", :action => "index"
# people.connect "/people/:id", :action => "show"
# end
#
def with_options(options)
yield ActiveSupport::OptionMerger.new(self, options)
end
# A duck-type assistant method. For example, Active Support extends Date
# to define an acts_like_date? method, and extends Time to define
# acts_like_time?. As a result, we can do "x.acts_like?(:time)" and
# "x.acts_like?(:date)" to do duck-type-safe comparisons, since classes that
# we want to act like Time simply need to define an acts_like_time? method.
def acts_like?(duck)
respond_to? "acts_like_#{duck}?"
end
end
可以看到 tap 方法也封装了,为了防止 ruby版本过低 没有tap方法就 添加Object#tap 方法,tap 和 returning本质是一样的,函数体都是调用block闭包,只不过returning需要传递一个参数给闭包,最后返回的就是这个参数,而 tap直接操作self指针,最后返回的也就是self
另外最新rails源码(>rails3.0.3)已经没有 returning方法了,所以以后最好都用tap方法
DEMO1:
require "rubygems" require "active_support" # Object#tap 是>ruby1.8.7 有的 # Object#returning 是Rails 封装的方法, rails3.X 已经不建议使用 # Object#tap 可以支持链式(chain)操作 (1..10).tap { |x| puts "original: #{x.inspect}" }.to_a.tap { |x| puts "array: #{x.inspect}" }.select {|x| x%2==0}.tap { |x| puts "evens: #{x.inspect}" }.map {|x| x*x}.tap { |x| puts "squares: #{x.inspect}" } def object_tap {}.tap do |h| # => Hash.new.tap h[:a] = 1 h[:b] =2 end end p object_tap # {:b=>2, :a=>1} def object_returning returning Hash.new do |h| # 注意这里不能用 {} , 放在 returning 方法后面 当作成 block闭包了 h[:a] = 1 h[:b] = 2 end end p object_returning # {:b=>2, :a=>1}
DEMO2:
require "rubygems" require "active_support" class Hash def shift_value_tap_self self.tap do |h| h.each { |k,v| v.shift if v.is_a?(Array) } end end def shift_value_tap {}.tap do |h| self.each { |k,v| v.is_a?(Array) ? h[k] = v.shift : h[k] = v } end end def shift_value_returning returning Hash.new do |h| self.each { |k,v| v.is_a?(Array) ? h[k] = v.shift : h[k] = v } end end def shift_value_returning_self returning self do |h| h.each { |k,v| v.shift if v.is_a?(Array) } end end end hsh = {"a"=>[1,2,3],"b"=>["g","f","w"],"c"=>"fuck_china"} hsh1 = {"a"=>[1,2,3],"b"=>["g","f","w"],"c"=>"fuck_china"} hsh2 = {"a"=>[1,2,3],"b"=>["g","f","w"],"c"=>"fuck_china"} hsh3 = {"a"=>[1,2,3],"b"=>["g","f","w"],"c"=>"fuck_china"} p hsh.shift_value_tap # {"a"=>1, "b"=>"g", "c"=>"fuck_china"} p hsh1.shift_value_returning # {"a"=>1, "b"=>"g", "c"=>"fuck_china"} p hsh2.shift_value_tap_self # {"a"=>[2, 3], "b"=>["f", "w"], "c"=>"fuck_china"} p hsh3.shift_value_returning_self # {"a"=>[2, 3], "b"=>["f", "w"], "c"=>"fuck_china"}
SEE:
http://blog.rubybestpractices.com/posts/gregory/011-tap-that-hash.html
http://www.simonecarletti.com/blog/2010/09/rails-3-beware-the-tap-pattern/
http://fuliang.javaeye.com/blog/857163
环境 : ruby 1.9.2 + ruby 1.8.7
ruby 1.8 时代 char to ascill 一般这么做:
"a"[0] # 97 ?a # 97
但是 1.9 时代 该方法 不可以了,输出如下:
"a"[0] # a ?a # a
后来 我用了 一个 变态的 方法:
"a".bytes.to_a.first # 97
1.9 时代 应该使用ord 函数
"a".ord # 97 "a"[0].ord # 97 ?a.ord # 97
ascill to char 通用:
97.chr # "a"
但是 ord 函数 1.8 环境下 同样可以使用;
看下 ord 函数的源码(built in 方法,内部看不到ruby代码):
# int.ord => int # # # Returns the int itself. # # ?a.ord #=> 97 # # This method is intended for compatibility to # character constant in Ruby 1.9. # For example, ?a.ord returns 97 both in 1.8 and 1.9. # # def ord # This is just a stub for a builtin Ruby method. # See the top of this file for more info. end
see:
http://stackoverflow.com/questions/1270209/getting-an-ascii-character-code-in-ruby-fails
最终环境:ubuntu10.10 + ruby 1.8.7 + ruby 1.9.2 + rails 2.3.5 + rails 3.0.3
新的项目,使用最新的ruby1.9.2 + rails3.X开发,所以 环境必须重新搭建 ,但是又要能使之前的rails2.X项目跑起来,所以,就用到了rvm来控制,rvm确实不错,一直用部署的capistrano差不多,很方便,rvm的原理是动态的改变系统的path,即ruby的bin目录,来调用不同的ruby版本的,都有自己独立的文件夹,这样管理rails的那些gem也就独立开来了,核心是一个script,有兴趣的可以看下,$HOME/.rvm/scripts/rvm , 这个shell脚本,下面介绍安装过程:
需要用到 git 和 curl
sudo apt-get install git sudo apt-get install curl
注意首先把原来的ruby bin目录从PATH中去掉
安装 rvm
cd ~
bash < <( curl http://rvm.beginrescueend.com/releases/rvm-install-head )
cd .rvm/src/rvm
./install查看 rvm 安装目录
wxianfeng@ubuntu:~/.rvm/gemsets/ruby$ echo $rvm_path /home/wxianfeng/.rvm
~/.bashrc中添加下面代码(PATH之用) 很重要
if [[ -s "$HOME/.rvm/scripts/rvm" ]] ; then source "$HOME/.rvm/scripts/rvm" ; fi
安装 ruby 1.9.2
>rvm notes sudo apt-get install build-essential bison openssl libreadline5 libreadline5-dev curl git zlib1g zlib1g-dev libssl-dev libyaml-dev libsqlite3-0 libsqlite3-dev sqlite3 libxml2-dev autoconf rvm install 1.9.2
查看:
wxianfeng@ubuntu:~$ rvm list rvm rubies ruby-1.9.2-p0 [ i386 ]
设置默认的 ruby 版本(必须设置)
>rvm --default ruby-1.9.2-p0
可以看到 相关信息
wxianfeng@ubuntu:~$ rvm info ruby-1.9.2-p0: system: uname: "Linux ubuntu 2.6.35-22-generic #33-Ubuntu SMP Sun Sep 19 20:34:50 UTC 2010 i686 GNU/Linux" bash: "/bin/bash => GNU bash, version 4.1.5(1)-release (i686-pc-linux-gnu)" zsh: " => not installed" rvm: version: "rvm 1.1.0 by Wayne E. Seguin (wayneeseguin@gmail.com) [http://rvm.beginrescueend.com/]" ruby: interpreter: "ruby" version: "1.9.2p0" date: "2010-08-18" platform: "i686-linux" patchlevel: "2010-08-18 revision 29036" full_version: "ruby 1.9.2p0 (2010-08-18 revision 29036) [i686-linux]" homes: gem: "/home/wxianfeng/.rvm/gems/ruby-1.9.2-p0" ruby: "/home/wxianfeng/.rvm/rubies/ruby-1.9.2-p0" binaries: ruby: "/home/wxianfeng/.rvm/rubies/ruby-1.9.2-p0/bin/ruby" irb: "/home/wxianfeng/.rvm/rubies/ruby-1.9.2-p0/bin/irb" gem: "/home/wxianfeng/.rvm/rubies/ruby-1.9.2-p0/bin/gem" rake: "/home/wxianfeng/.rvm/gems/ruby-1.9.2-p0/bin/rake" environment: PATH: "/home/wxianfeng/.rvm/gems/ruby-1.9.2-p0/bin:/home/wxianfeng/.rvm/gems/ruby-1.9.2-p0@global/bin:/home/wxianfeng/.rvm/rubies/ruby-1.9.2-p0/bin:/home/wxianfeng/.rvm/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/system/mysql/bin:/usr/local/system/jdk1.6.0_22/bin" GEM_HOME: "/home/wxianfeng/.rvm/gems/ruby-1.9.2-p0" GEM_PATH: "/home/wxianfeng/.rvm/gems/ruby-1.9.2-p0:/home/wxianfeng/.rvm/gems/ruby-1.9.2-p0@global" MY_RUBY_HOME: "/home/wxianfeng/.rvm/rubies/ruby-1.9.2-p0" IRBRC: "/home/wxianfeng/.rvm/rubies/ruby-1.9.2-p0/.irbrc" RUBYOPT: "" gemset: ""
这时发现你的PATH已经变了
wxianfeng@ubuntu:~$ echo $PATH /home/wxianfeng/.rvm/gems/ruby-1.9.2-p0/bin:/home/wxianfeng/.rvm/gems/ruby-1.9.2-p0@global/bin:/home/wxianfeng/.rvm/rubies/ruby-1.9.2-p0/bin:/home/wxianfeng/.rvm/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/system/mysql/bin:/usr/local/system/jdk1.6.0_22/bin
wxianfeng@ubuntu:~$ ruby -v ruby 1.9.2p0 (2010-08-18 revision 29036) [i686-linux]
ruby 1.9.2 安装成功
安装rails
wxianfeng@ubuntu:~$ gem install rails --pre --no-ri --no-rdoc /home/wxianfeng/.rvm/rubies/ruby-1.9.2-p0/bin/gem:4: warning: Insecure world writable dir /usr/local/system in PATH, mode 040777 Successfully installed activesupport-3.0.0.rc2 Successfully installed builder-2.1.2 Successfully installed i18n-0.4.2 Successfully installed activemodel-3.0.0.rc2 Successfully installed rack-1.2.1 Successfully installed rack-test-0.5.6 Successfully installed rack-mount-0.6.13 Successfully installed tzinfo-0.3.23 Successfully installed abstract-1.0.0 Successfully installed erubis-2.6.6 Successfully installed actionpack-3.0.0.rc2 Successfully installed arel-1.0.0.rc1 Successfully installed activerecord-3.0.0.rc2 Successfully installed activeresource-3.0.0.rc2 Successfully installed mime-types-1.16 Successfully installed polyglot-0.3.1 Successfully installed treetop-1.4.9 Successfully installed mail-2.2.10 Successfully installed actionmailer-3.0.0.rc2 Successfully installed thor-0.14.6 Successfully installed railties-3.0.0.rc2 Successfully installed bundler-1.0.0.rc.6 Successfully installed rails-3.0.0.rc2 23 gems installed
有提示我path中有777权限目录,看着不顺眼,解决掉:
sudo chmod go-w /usr/local/system发现安装上的是 3.0.0.rc2 不是我想要的,目前最新版是 3.0.3
咋办,用shell脚本全部remove掉
shell:
#!/bin/bash for i in `gem list` do gem uninstall $i done
最后发现rake无法uninstall掉,好那就进入目录把rake delete掉
wxianfeng@ubuntu:~$ gem list -d rake /home/wxianfeng/.rvm/rubies/ruby-1.9.2-p0/bin/gem:4: warning: Insecure world writable dir /usr/local/system in PATH, mode 040777 *** LOCAL GEMS *** rake (0.8.7) Author: Jim Weirich Rubyforge: http://rubyforge.org/projects/rake Homepage: http://rake.rubyforge.org Installed at: /home/wxianfeng/.rvm/gems/ruby-1.9.2-p0@global Ruby based make-like utility. >cd /home/wxianfeng/.rvm/gems/ruby-1.9.2-p0@global wxianfeng@ubuntu:~/.rvm/gems/ruby-1.9.2-p0@global$ ll total 28 drwxr-xr-x 7 wxianfeng wxianfeng 4096 2010-11-23 14:14 ./ drwxr-xr-x 5 wxianfeng wxianfeng 4096 2010-11-23 14:14 ../ drwxr-xr-x 2 wxianfeng wxianfeng 4096 2010-11-23 15:21 bin/ drwxr-xr-x 2 wxianfeng wxianfeng 4096 2010-11-23 15:22 cache/ drwxr-xr-x 2 wxianfeng wxianfeng 4096 2010-11-23 15:22 doc/ drwxr-xr-x 2 wxianfeng wxianfeng 4096 2010-11-23 15:20 gems/ drwxr-xr-x 2 wxianfeng wxianfeng 4096 2010-11-23 15:21 specifications/
把bin cache doc gems specifications 下和rake相关的信息全部remove掉
重新安装成功 rails 3.0.3
wxianfeng@ubuntu:~$ gem install rails -v=3.0.3 --no-ri --no-rdoc /home/wxianfeng/.rvm/rubies/ruby-1.9.2-p0/bin/gem:4: warning: Insecure world writable dir /usr/local/system in PATH, mode 040777 Successfully installed activesupport-3.0.3 Successfully installed builder-2.1.2 Successfully installed i18n-0.4.2 Successfully installed activemodel-3.0.3 Successfully installed rack-1.2.1 Successfully installed rack-test-0.5.6 Successfully installed rack-mount-0.6.13 Successfully installed tzinfo-0.3.23 Successfully installed abstract-1.0.0 Successfully installed erubis-2.6.6 Successfully installed actionpack-3.0.3 Successfully installed arel-2.0.4 Successfully installed activerecord-3.0.3 Successfully installed activeresource-3.0.3 Successfully installed mime-types-1.16 Successfully installed polyglot-0.3.1 Successfully installed treetop-1.4.9 Successfully installed mail-2.2.10 Successfully installed actionmailer-3.0.3 Successfully installed rake-0.8.7 Successfully installed thor-0.14.6 Successfully installed railties-3.0.3 Successfully installed bundler-1.0.7 Successfully installed rails-3.0.3 24 gems installed
wxianfeng@ubuntu:~$ rails -v Rails 3.0.3
安装 ruby 1.8.7
>rvm install 1.8.7
切换到 1.8.7
wxianfeng@ubuntu:~/.rvm/gemsets/ruby$ rvm 1.8.7
wxianfeng@ubuntu:~/.rvm/gemsets/ruby$ gem list /home/wxianfeng/.rvm/rubies/ruby-1.8.7-p302/bin/gem:4: warning: Insecure world writable dir /usr/local/system in PATH, mode 040777 *** LOCAL GEMS *** rake (0.8.7)
悲剧的发现 其实 默认rake是安装上的,之前我还把它 给干掉 重新安装了
安装 rails 2.3.5
>gem install rails -v=2.3.5 --no-ri --no-rdoc
以后切换的话 就用 rvm —default 1.8.7 或者 rvm —default 1.9.2 切换默认的ruby版本,可以使用 rvm 1.8.7 切换当前终端版本到1.8.7 , 也就是可以同时开ruby 1.8.7 , ruby 1.9.2 的项目了
安装之前ruby 1.8.7 + rails 2.3.5 项目的 所有gems (注意把ruby版本切到1.8.7), 如果已经安装了,就不安装:
shell:
#!/bin/bash # 安装所有的gems,如果已经安装了就不安装 cd /usr/local/system/ruby/lib/ruby/gems/1.8/cache for i in `ls`;do gem=`echo $i | awk -F'-' '{print $1}'` version=`echo $i | grep -o "\-[0-9].*" | sed 's/^-//;s/.gem//'` is_gem_exist=`gem list $gem -v=$version` if [ -z "$is_gem_exist" ]; then # 注意[] 内部两边留空格 `gem install $i` else echo "$i have installed" fi done
这样,之前ruby 1.8.7+rails2.3.4的项目 和现在的 ruby 1.9.2 + rails 3.0.3 都兼容了…oh…YEAR
问题: netbeans 配置使用 ruby 1.8.7 + rails 2.3.5 OR ruby 1.9.2 + rails 3.0.3 ?
更改netbeans 的ruby path ,选择 autodetect 会把ruby的bin全部找出来,但是注意gem path 有可能错误,通过 rvm info 看下 gem 的位置,然后手动更改即可~!
SEE:
http://thoughtrails.com/episodes/1-installing-rails-3-on-ubuntu-10-04-lucid-lynx-with-rvm
http://rvm.beginrescueend.com/rvm/install/
不幸,宿舍的电脑又挂掉了,这次装了个win 7,win 7 果然气质不凡,概念版的QQ很炫的说,不过跑起来有点卡,还是XP下的qq跑得流畅,郁闷的是qq2010,安装上运行不起来,抱错,这不是必win 7 用概念版的吗~!..切入正题:
最终环境:win 7 + ruby 1.9.2 + rails 3.0.0.rc2 + mysql 5.1
目前rails3的demo跑起来了,由于以前的项目都是跑在2.x系列的,所以以后还要折腾………….
1,安装 ruby 1.9.2 and install
http://rubyforge.org/frs/download.php/72170/rubyinstaller-1.9.2-p0.exe
注意安装上ruby 1.9.2 就不需要再安装rubygems了,这个和以前ruby 1.8.X 的有区别,ruby 1.9.2 已经自带rubygems了,可以>gem -v 查看
2,安装rails
F:\>gem install rails --pre --no-ri --no-rdoc ERROR: Error installing rails: activemodel requires builder (~> 2.1.2, runtime)
接下来你只需要运行gem install rails —pre —no-ri —no-rdoc 即可,缺少什么装什么,一直装到gem install rails —pre —no-ri —no-rdoc 成功即可,例如上面错误,继续安装缺少的依赖的库,如果某个gem安装不上了,去rubygems.org上下载下来手动安装上,再继续,如果加上 —pre 参数安装的不是最新的rails版本,那么把 —pre 参数去掉试试
F:\>gem install builder --no-ri --no-rdoc
为什么要用—no-ri —no-rdoc 参数,因为加上去安装实在是慢,反正装了也不用,还不如不装rdoc!
3,新建rails3 project
>rails new rails3 -d mysql
4,修改database.yml
5,创建数据库
>rake db:create RAILS_ENV=development
6,启动rails3 server
>rails server
你会发现报如下错误:
E:\Rubyproject\rails3>rails server Could not find gem 'mysql2 (>= 0, runtime)' in any of the gem sources. Try running `bundle install`.
发现rails3.0连接mysql的adapter不再是mysql了,是mysql2,这个好办,我们还用之前的mysql但是建议用mysql2,mysql2性能上有很大提高,gem install mysql2 即可
修改项目下Gemfile
gem ‘mysql2’ 改为 gem ‘mysql’
同理修改config下的database.yml mysql2 → mysql
7,ok,你的demo已经可以跑起来了
如果你的mysql还是连不上,可能是libmysql.dll 问题,see: http://wxianfeng.com/2010/06/23/windows-xp-ruby-on-rails-mysql
除此之外,还有一种更简单的方法,安装devkit,但是我没有成功,gem install rails —pre 安装失败,see : http://skim.la/2010/08/21/rails-3-rc-on-windows-using-rubyinstaller-192/
see:
http://skim.la/2010/02/07/rails-3-beta-on-windows-using-rubyinstaller-187-rc2/
http://osdir.com/ml/RubyonRailsTalk/2010-09/msg00480.html
