ruby-on-rails – 用Ruby思考

前端之家收集整理的这篇文章主要介绍了ruby-on-rails – 用Ruby思考前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我目前正忙着学习 Ruby和Rails,因为我有基于C语言的背景,所以Ruby的一些概念是新的,有点陌生.对我来说特别具有挑战性的是适应处理常见问题的“Ruby方式”,因此我经常发现自己用Ruby编写C语言,这不是我想要实现的.

想象一下这样的架构:

ActiveRecord::Schema.define(:version => 20111119180638) do
    create_table "bikes",:force => true do |t|
        t.string   "Brand"
        t.string   "model"
        t.text     "description"
    end
end

数据库已包含几种不同的自行车.我的目标是获得数据库中所有品牌的数组.

这是我的代码

class Bike < ActiveRecord::Base
    def Bike.collect_brands
        temp_brands = Bike.find_by_sql("select distinct brand from bikes")
        brands = Array.new
        temp_brands.each do |item|
          brands.push(item.brand)
        end
        brands
    end
end

Ruby大师如何编写代码来实现这一目标?

解决方法

tl; dr:你的整个方法可以用Bike.uniq.pluck(:brand)代替.

功能已经存在(请参阅我的答案结尾),但首先,让我们逐步完成您的代码并使其更具惯用性:

首先,每级缩进使用两个空格,而不是四个,而不是八个,而不是标签.使用两个空格.这不是个人偏好,这是Ruby社区中非常强大的惯例,如果您打算参与,则非常需要.

接下来,在Ruby中几乎没有充分的理由使用这种模式:

brands = Array.new
 temp_brands.each do |item|
   brands.push(item.brand)
 end

当您想通过将一些代码应用于输入数组中的每个值时,将一个数组转换为另一个数组(实际上,一个Enumerable为另一个Enumerable)时,请使用mapcollect(这是同义词):

brands = temp_brands.map { |item| item.brand }

接下来,您可以利用symbol#to_proc使上述代码更清晰:

brands = temp_brands.map &:brand

对于没有经验的人来说这看起来很奇怪,但是一旦你习惯使用map和&:field就会更清楚.一点点经验会使这行代码的意图非常明显:它将品牌方法应用于数组中的每个元素,它完全等同于之前的{| item | item.brand}版本.

现在,您的整个方法可以变得非常简单:

def Bike.collect_brands
  Bike.find_by_sql("select distinct brand from bikes").map &:brand
end

内联选择/不同的sql有点难看,特别是因为ActiveRecord已经让我们select specific fields选择了,并使用uniq使结果不同:

def Bike.collect_brands
  Bike.select(:brand).uniq.map &:brand
end

作为最后的迭代,我们可以使用pluck而不是map来仅从我们感兴趣的结果中提取字段.但是,因为pluck实际上修改生成sql以仅包括提取的字段,所以我们可以省略select (:品牌)部分,我们的代码归结为包含两个链式方法的令人难以置信的短单行:

def Bike.collect_brands
  Bike.uniq.pluck(:brand)
end

请注意,顺序很重要,因为pluck总是返回一个数组,而不是为其他方法链接准备好的ActiveRecord关系. Bike.pluck(:品牌).uniq将从每个记录(从自行车中选择品牌)中选择品牌,然后在Ruby中将阵列减少为独特的项目.可能是非常昂贵的操作.

就是这样,Bike.uniq.pluck(:品牌).作为一名C程序员,你会发现你习惯用小循环做的许多重复性任务实际上已经通过语言本身或支持库来解决.一旦你学会了编写惯用的Ruby和Rails代码,你不写的代码量就会非常令人惊讶.

猜你在找的Ruby相关文章