理解 Ruby 闭包

Ruby 有4种闭包类型,blocks、procs、lambdas 和 method objects。

Ruby 处理闭包有两种形态:一是 snippets 型,包括 blocks 和 procs,其中 blocks 只是书写简化但受到一些限制的 procs;二是 methods 型,包括 lambdas 和 method objects,前者匿名后者具名。

# 示例1
class Array
  def iterate!
    self.each_with_index do |n, i|
      self[i] = yield(n)
    end
  end
end

[1, 2, 3, 4].iterate! { |n| n ** 2 }
=> [1, 4, 9, 16]
# 示例2
class Array
  def iterate!(&code)
    self.each_with_index do |n, i|
      self[i] = code.call(n)
    end
  end
end

[1, 2, 3, 4].iterate! { |n| n ** 2 }
=> [1, 4, 9, 16]
Reading more...

ActiveRecord 中 joins、includes、preload、eager_load 的区别

joins

joins 的使用场合

过滤结果,而不是访问关联表的记录。

Post.joins(:comments).where(comments: {user_id: 1}).map { |post| post.title }
=> SELECT "posts".* FROM "posts" INNER JOIN "comments" ON "comments"."post_id" = "posts"."id" WHERE "comments"."user_id" = ?  [["user_id", 1]]

joins 能阻止 N + 1 查询吗?

不。joins 不加载关联表的记录到内存,如果访问关联表的记录将触发 N + 1 查询。

Post.joins(:comments).where(comments: {user_id: 1}).map { |post| post.comments.size }
=> SELECT "posts".* FROM "posts" INNER JOIN "comments" ON "comments"."post_id" = "posts"."id" WHERE "comments"."user_id" = ?  [["user_id", 1]]
   SELECT COUNT(*) FROM "comments" WHERE "comments"."post_id" = ?  [["post_id", 1]]
   SELECT COUNT(*) FROM "comments" WHERE "comments"."post_id" = ?  [["post_id", 2]]
   SELECT COUNT(*) FROM "comments" WHERE "comments"."post_id" = ?  [["post_id", 3]]
   SELECT COUNT(*) FROM "comments" WHERE "comments"."post_id" = ?  [["post_id", 4]]
Reading more...

Rails 路由中 Scope 和 Namespace 的区别

Scope

scope 'url_path_prefix', module: 'module_prefix', as: 'named_route_prefix' do
  resources :posts
end

举例:

scope 'foo', module: 'bar', as: 'baz' do
  resources :posts
end
$ rake routes
       Prefix Verb   URI Pattern                   Controller#Action
    baz_posts GET    /foo/posts(.:format)          bar/posts#index
              POST   /foo/posts(.:format)          bar/posts#create
 new_baz_post GET    /foo/posts/new(.:format)      bar/posts#new
edit_baz_post GET    /foo/posts/:id/edit(.:format) bar/posts#edit
     baz_post GET    /foo/posts/:id(.:format)      bar/posts#show
              PATCH  /foo/posts/:id(.:format)      bar/posts#update
              PUT    /foo/posts/:id(.:format)      bar/posts#update
              DELETE /foo/posts/:id(.:format)      bar/posts#destroy
Reading more...

Ruby 中 Private 和 Protected 方法的区别

Ruby 中 Private 和 Protected 方法的区别是一个小知识点,总结归纳一下。

class Father
  def method_a
    puts self.method_private
  end

  def method_b
    puts method_private
  end

  def method_c
    puts self.method_protected
  end

  def method_d
    puts method_protected
  end

  private
  def method_private
    puts "I am method PRIVATE in #{self.class}"
  end

  protected
  def method_protected
    puts "I am method PROTECTED in #{self.class}"
  end
end

class Son < Father
  def son_method_private
    method_private
  end

  def son_method_protected
    method_protected
  end
end

father = Father.new
son = Son.new
Reading more...

Debian 桌面环境使用备忘

最近又使用 Debian 作为桌面环境了,一些问题的解决方法记录下作为备忘。

将 Home 目录下的中文目录改为英文

修改 ~/.config/user-dirs.dirs,将

XDG_DESKTOP_DIR="$HOME/桌面"
XDG_DOWNLOAD_DIR="$HOME/下载"
XDG_TEMPLATES_DIR="$HOME/模板"
XDG_PUBLICSHARE_DIR="$HOME/公共"
XDG_DOCUMENTS_DIR="$HOME/文档"
XDG_MUSIC_DIR="$HOME/音乐"
XDG_PICTURES_DIR="$HOME/图片"
XDG_VIDEOS_DIR="$HOME/视频"

改为

XDG_DESKTOP_DIR="$HOME/Desktop"
XDG_DOWNLOAD_DIR="$HOME/Downloads"
XDG_TEMPLATES_DIR="$HOME/Templates"
XDG_PUBLICSHARE_DIR="$HOME/Public"
XDG_DOCUMENTS_DIR="$HOME/Documents"
XDG_MUSIC_DIR="$HOME/Music"
XDG_PICTURES_DIR="$HOME/Pictures"
XDG_VIDEOS_DIR="$HOME/Videos"

将 Home 目录下各个中文目录的名称修改成配置文件里对应的名称,重启系统。

Reading more...