respond_to_missing?

2015年5月05日 10:59

method_missing problem

class StereoPlayer
  def method_missing(method, *args, &block)
    if method.to_s =~ /play_(\w+)/
      puts "Here's #{$1}"
    else
      super
    end
  end
end

p = StereoPlayer.new
# ok:
p.play_some_Beethoven # => "Here's some_Beethoven"
# not very polite:
p.respond_to? :play_some_Beethoven # => false

userespond_to?

class StereoPlayer
  # def method_missing ...
  #   ...
  # end

  def respond_to?(method, *)
    method.to_s =~ /play_(\w+)/ || super
  end
end
p.respond_to? :play_some_Beethoven # => true

This is better, but it still doesn’t make play_some_Beethoven behave exactly like a method. Indeed:

p.method :play_some_Beethoven
# => NameError: undefined method `play_some_Beethoven'
#               for class `StereoPlayer'

Ruby 1.9.2 introduces respond_to_missing? that provides for a clean solution to the problem. Instead of specializing respond_to? one specializes respond_to_missing?. Here’s a full example:

class StereoPlayer
  # def method_missing ...
  #   ...
  # end

  def respond_to_missing?(method, *)
    method =~ /play_(\w+)/ || super
  end
end

p = StereoPlayer.new
p.play_some_Beethoven # => "Here's some_Beethoven"
p.respond_to? :play_some_Beethoven # => true
m = p.method(:play_some_Beethoven) # => #<Method: StereoPlayer#play_some_Beethoven>
# m acts like any other method:
m.call # => "Here's some_Beethoven"
m == p.method(:play_some_Beethoven) # => true
m.name # => :play_some_Beethoven
StereoPlayer.send :define_method, :ludwig, m
p.ludwig # => "Here's some_Beethoven"

继续阅读 »

Rails 4: how to use $(document).ready() with turbo-links

2014年11月14日 14:20

CoffeeScript:

ready = ->

  ...your coffeescript goes here...

$(document).ready(ready)
$(document).on('page:load', ready)

Javascript

var ready;
ready = function() {

  ...your javascript goes here...

};

$(document).ready(ready);
$(document).on('page:load', ready);

继续阅读 »

The 10 Most Underused ActiveRecord::Relation Methods

2013年11月12日 14:26

10. first_or_create with a block

first_or_create is very familiar:

Book.where(:title => 'Tale of Two Cities').first_or_create

Often, though, you want to find a record with certain attributes, or create one with those and additional attributes. To do this succinctly, you can supply a block to first_or_create:

Book.where(:title => 'Tale of Two Cities').first_or_create do |book|
  book.author = 'Charles Dickens'
  book.published_year = 1859
end

9. first_or_initialize

If you don’t want to save the record yet, you can use first_or_initialize:

Book.where(:title => 'Tale of Two Cities').first_or_initialize

继续阅读 »

Using Ruby's Gsub With a Hash

2013年10月18日 17:52

def geekify(string)
  string.gsub(/[leto]/, 'l' => '1', 'e' => '3', 't' => '7', 'o' => '0')
end

geekify('leet') # => '1337'
geekify('noob') # => 'n00b'
def doctorize(string)
  string.gsub(/M(iste)?r/, 'Mister' => 'Doctor', 'Mr' => 'Dr')
end

doctorize('Mister Freeze') # => 'Doctor Freeze'
doctorize('Mr Smith')   # => 'Dr Smith'

继续阅读 »

把全站都改成了page_cache方式了

2013年9月13日 12:28

1.文章时间改成具体的发布时间
2.分页route做了修改
3.nginx配置做了修改,把所有cache的文件都放到了caches里了

# Index HTML Files
if (-f $document_root/cache/$uri/index.html) {
  rewrite (.*) /caches/$1/index.html break;
}

# HTML Files
if (-f $document_root/cache/$uri.html) {
  rewrite (.*) /caches/$1.html break;
}

# Catch all
if (-f $document_root/cache/$uri) {
  rewrite (.*) /caches/$1 break;
}

继续阅读 »

Ruby tap method

2013年8月26日 22:32

tap定义

class Object 
  def tap 
    yield self 
    self 
  end 
end

Usage

1
blah.sort.grep( /foo/ ).map { |x| x.blah }
xs = blah.sort.grep( /foo/ )
p xs

# do whatever we had been doing with the original expression
xs.map { |x| x.blah }
blah.sort.grep( /foo/ ).tap { |xs| p xs }.map { |x| x.blah }

继续阅读 »

A Rails API Pattern for Complex Collections

2013年8月26日 22:15

def index
  @recipe_collection = RecipeCollection.from_params(params)
  render json: @recipe_collection.recipes
end
class RecipeCollection
  attr_accessor :featured, :time_filter

  # Handles the logic of sorting params into a collection
  def self.from_params(params)
    RecipeCollection.new.tap do |recipe_collection|
      recipe_collection.time_filter = params[:time_filter]
      recipe_collection.featured = params[:featured]
    end
  end

  # Should return an ActiveRecord relation
  def recipes
    query = Recipe.scoped
    query.featured if featured.present?
    query.filter_by_time(time_filter)
  end

  def time_filter
  valid_time_filters.include?( @time_filter ) ? @time_filter : default_time_filter
  end

  def default_time_filter
    "today"
  end

  def valid_time_filters
    %w[ today yesterday this-week this-year ]
  end
end

继续阅读 »

Incremental Redesign with Rails

2013年7月31日 17:15

重构前

<%- if current_user.redesign_enabled? %>
  <%# new code %>
<%- else %>
  <%# old code %>
<%- end %>

重构后

class ApplicationController < ActionController::Base
  before_filter :add_view_path_for_redesign

  private

  def add_view_path_for_redesign
    if current_user.redesign_enabled?
      prepend_view_path Rails.root.join('app/views/redesign')
    end
  end
end
# original
app/views/users/edit.html.erb
app/views/users/show.html.erb

# redesign
app/views/redesign/users/edit.html.erb
app/views/redesign/users/show.html.erb

继续阅读 »

爬虫抓取问题

2013年6月05日 13:59

前几天把我经常看的一些视频和小说用Nokogiri抓了下,感觉Nokogiri还挺好用。不过刚放上去了一天,服务器的CPU和内存以及IO全部报警,最开始以为是代码写的有问题。逐行查了一遍,发现没问题。后来意识到可能是Whenever的抓取间隔时间太短了,初始设置为2分钟一次,当时写的时候,只抓一个网站,2分钟内完全能抓完,后来又加了几个网站,2分钟就抓不完了,结果就一直堵塞了。后来只能重启服务器,把时间间隔改为1小时抓一次,现在运行OK。

继续阅读 »

whenever执行时一直报错

2013年5月29日 21:35

在rails项目中使用使用whenever时,一直报各种找不到命令,如:zsh: command not found: Gemfile,等等等。。。。。。
查了好多资料,一直没解决,今天在unbuntu上新建了一个空项目能正常使用,于是把笔记本上的项目拷到ubuntu上,还是报错,/usr/bin/env :ruby.exe 找不到指令或文件,最开始没注意到,后来一看,ubuntu上怎么会用到exe?于是网上又查找,把项目中/script/rails文件中的#!/usr/bin/env ruby.exe修改成#!/usr/bin/env ruby,果然好了。原来的项目是在windows下生成的,所以才会有这种问题。真尼玛。
Mac上的项目执行whenever还是报错env: ruby: No such file or directory,不过手动执行脚本可以运行。
于是把/script/rails中的#!/usr/bin/env ruby 改成了 #!/Users/username/.rvm/rubies/ruby-1.9.3-p0/bin/ruby
Mac上也可以运行了。

继续阅读 »