出了份 Ruby 面试题,主要是考察对 Ruby 本身 掌握的深度. 给大家看看有什么不妥的地方。
Ruby 基础相关
each
和 map
的区别proc
, lambda
, 和 Proc
的区别alias
的用法,alias
与 alias_method
的区别Ruby 与 Rails 进阶相关
yield self
的用法,写个例子scope
的实现原理ActiveSupport::Concern
模块的用法及源码解读alias_method_chain
的用法及源码解读alias_method_chain is no longer used. http://stackoverflow.com/questions/3689736/rails-3-alias-method-chain-still-used http://piotrsarnacki.com/2010/06/18/rails-internals-railties/
说实话,这种面试题很讨厌。如果论坛有从定向功能可以定向到这里:http://ruby-china.org/topics/13263
从写 Ruby 到现在遇到的面试题大部分都是这几个题目,看着都烦。 如果是我遇到这样的东西,我会觉得出题人一点诚意都没有,随便在网上找了几个题目就来问。
出几个新颖一点的面试题很难么?平时开发遇到的坑都可以成为面试题。
有些问题你自己平时写代码都几乎从来不会用到就不要拿来考别人了,比如 2,3,5
还有一些问题属于小 tip 之类,拿来做面试题没有任何意义。
说实话,如果我去这家公司面试,一大半我都答不上来,或者说无法给出最标准,正确的答案。但是面试中是否能一击即中的回答出问题,我觉得还是面试中的表现更重要吧,自信,乐观,以及给出自己的问题分析,或者告诉对方答案去那里找,如何找到这样。
元编程的还好,Rails 这几个真的不会 求指教。。。
* scope 的实现原理
* ActiveSupport::Concern 模块的用法及源码解读
* alias_method_chain 的用法及源码解读
#17 楼 @neverlandxy_naix 只有面试者清楚了如何用 Ruby 解决问题才能知道要考察被面试者的关键点...
当然,如果你觉得考察扩展魔法糖很重要,就出些此类题目咯。
但我觉得面试重要的还是基础知识和常识,我们高中有个老师出考试题目从来不出难题怪题和原题,但是却能让高水平学生打高分,低水平学生打低分.. 我觉得这是出题的目的。
@lgn21st @neverlandxy_naix 我说的也是好的面试题该是什么样的,和出题者或回答者无关。
这些问题都能 100% 答对的人,未必能写出清晰优雅的代码,我觉得那才是最重要的。网上或书上能查到的东西却是次要的,尽管对这些知识越熟悉越好。 假设有一天,科技发展到知识能够直接上传到大脑里,这些考题就完全没有意义了。
#33 楼 @hooopo #32 楼 @blacktulip 如果有二位这么聪明的头脑,我就不写 code 了
#30 楼 @bhuztez 用 brainfuck 写可以吗?
>++++++++++[<++++++++++>-]<[>+>[-]>++++++++++[<++++++++++>-]<+<<[->>->+<<<]>>>
[-<<<+>>>]<>>+++<<[->+>-[>+>>]>[+[-<+>]>+>>]<<<<<<]>[-<+>]+>[-]>[<<->>[-]]>[-]
<<<[[-]++++++++++[>++++++++++<-]>++.+++.[-]<[-]+++++++++++[>+++++++++++<-]>+..
[-]<[-]<<[-]>>]<>>+++++<<[->+>-[>+>>]>[+[-<+>]>+>>]<<<<<<]>[-<+>]+>[-]>[<<->>[
-]]>[-]<<<[[-]+++++++++[>+++++++++++<-]>-.[-]<[-]+++++++++[>+++++++++++++<-]>.
+++++..[-]<[-]<<[-]>>]<<[[-]>>++++++++++<[->-[>+>>]>[+[-<+>]>+>>]<<<<<]>[-]>>[
>++++++++[<++++++>-]<.[-]]<>++++++++[<++++++>-]<.[-]<<<]>[-]++++++++++.[-]<[-]
<-]
我承认很长,短的就请 B 大来吧
puts "1\n2\nFizz\n4\nBuzz\nFizz\n7\n8\nFizz\nBuzz\n11\nFizz\n13\n14\nFizzBuzz\n16\n17\nFizz\n19\nBuzz\nFizz\n22\n23\nFizz\nBuzz\n26\nFizz\n28\n29\nFizzBuzz\n31\n32\nFizz\n34\nBuzz\nFizz\n37\n38\nFizz\nBuzz\n41\nFizz\n43\n44\nFizzBuzz\n46\n47\nFizz\n49\nBuzz\nFizz\n52\n53\nFizz\nBuzz\n56\nFizz\n58\n59\nFizzBuzz\n61\n62\nFizz\n64\nBuzz\nFizz\n67\n68\nFizz\nBuzz\n71\nFizz\n73\n74\nFizzBuzz\n76\n77\nFizz\n79\nBuzz\nFizz\n82\n83\nFizz\nBuzz\n86\nFizz\n88\n89\nFizzBuzz\n91\n92\nFizz\n94\nBuzz\nFizz\n97\n98\nFizz\nBuzz"
puts DATA.read
__END__
1\n2\nFizz\n4\nBuzz\nFizz\n7\n8\nFizz\nBuzz\n11\nFizz\n13\n14\nFizzBuzz\n16\n17\nFizz\n19\nBuzz\nFizz\n22\n23\nFizz\nBuzz\n26\nFizz\n28\n29\nFizzBuzz\n31\n32\nFizz\n34\nBuzz\nFizz\n37\n38\nFizz\nBuzz\n41\nFizz\n43\n44\nFizzBuzz\n46\n47\nFizz\n49\nBuzz\nFizz\n52\n53\nFizz\nBuzz\n56\nFizz\n58\n59\nFizzBuzz\n61\n62\nFizz\n64\nBuzz\nFizz\n67\n68\nFizz\nBuzz\n71\nFizz\n73\n74\nFizzBuzz\n76\n77\nFizz\n79\nBuzz\nFizz\n82\n83\nFizz\nBuzz\n86\nFizz\n88\n89\nFizzBuzz\n91\n92\nFizz\n94\nBuzz\nFizz\n97\n98\nFizz\nBuzz
抱歉,刚没注意到。。
@blacktulip 这个其实看看 API 就知道的啊
each
只是遍历一遍
map
这个是 alias collect
,会返回一个由block
执行结果组成的数组
无 method
`echo '1\n2\nFizz\n4\nBuzz\nFizz\n7\n8\nFizz\nBuzz\n11\nFizz\n13\n14\nFizzBuzz\n16\n17\nFizz\n19\nBuzz\nFizz\n22\n23\nFizz\nBuzz\n26\nFizz\n28\n29\nFizzBuzz\n31\n32\nFizz\n34\nBuzz\nFizz\n37\n38\nFizz\nBuzz\n41\nFizz\n43\n44\nFizzBuzz\n46\n47\nFizz\n49\nBuzz\nFizz\n52\n53\nFizz\nBuzz\n56\nFizz\n58\n59\nFizzBuzz\n61\n62\nFizz\n64\nBuzz\nFizz\n67\n68\nFizz\nBuzz\n71\nFizz\n73\n74\nFizzBuzz\n76\n77\nFizz\n79\nBuzz\nFizz\n82\n83\nFizz\nBuzz\n86\nFizz\n88\n89\nFizzBuzz\n91\n92\nFizz\n94\nBuzz\nFizz\n97\n98\nFizz\nBuzz' >&2`
原来 map
就是 collect
Example:
select("post", "person_id", Person.all.collect {|p| [ p.name, p.id ] }, {:prompt => 'Select Person'})
could become:
<select name="post[person_id]">
<option value="">Select Person</option>
<option value="1">David</option>
<option value="2">Sam</option>
<option value="3">Tobias</option>
</select>
ActiveSupport::Concern 模块的用法这个问题其实貌似挺简单的:
.... I discourage pulling sets of methods out of a large ActiveRecord class into “concerns”, or modules that are then mixed in to only one model. I once heard someone say:
Any application with an app/concerns directory is concerning.
And I agree. Prefer composition to inheritance. Using mixins like this is akin to “cleaning” a messy room by dumping the clutter into six separate junk drawers and slamming them shut. Sure, it looks cleaner at the surface, but the junk drawers actually make it harder to identify and implement the decompositions and extractions necessary to clarify the domain model.
面试题好不好,社区的同学们各自做一做(不借助任何参考资料)就知道了,如果大家都不会的可能就是不重要的。 先占位,有空写我的答案
占位以后忘了写答案了,刚好这会有空,补一下作业
Ruby 基础相关
map是将block施加与array的每一个成员之上,并将计算结果组织为新的array,each只有前半部分,不会组织成新的array
proc记得不太清楚了,好像是内部能够支持return到外层,lambda比较简单,就是普通的lambda闭包(return不能跨越作用域),它们创建的对象,其class都是Proc
alias是ruby语言关键字,对当前类的method定义别名,alias_method是库增强(好像是active support),参数是symbol
rails中的active support等gem,基本都是辅助增强
ActiveRecord是支持延迟计算的ORM库,mongoid不用解释了
http client: faraday/mechanize,前一个轻一些,后一个使用cookie比较方便
以前用过activescaffold,还有个gem记不清名字了,好像是hpriot,以前用来抓网页,作者应该是_why大神
inheritance_resources/inheritance_resource_views 用来简化开发
statemachine 简化模型类的逻辑代码
railroady,用来生成模型图比较方便
redis_search,华顺写的,用它可以晚一些引入搜索引擎
还有god、pry、各种http app server、各种测试/mock框架
Object -> Module -> Class -> MyClass
另外:
Object.new.class = Class
Class.superclass = Object
Ruby 与 Rails 进阶相关
class Builder
def initialize arguments
# do somthing by init arguments
end
# you can use Builder's method in block
def build
yield self if block_given?
end
end
核心是延迟计算,将where、order、limit子句变为Relation对象,然后在最终调用each/to_a时组装sql
用来简化module编写,普通的module方法是include所在类的实例方法,Concern可以借助一个ClassMethod的内部module,提供类方法增强
详细不记得了,大致是对一个method提供arround类型的aop增强,实现方法应该还是借助了alias机制,将目标method改名,然后用旧名称创建一个新的method,新method调用了改名后的method,并在调用前(or 调用后?)执行chain上的其它方法
#75 楼 @fsword 谢谢你的精彩回复,我刚学 Ruby 的时候就知道你了,taobao 的阿福^_^ 忍不住贴下我自己心中的答案,有什么不对的地方请多多指点。 就说说和 Ruby 基础相关,Rails 的,看过源码加上自己的理解一般都能说上两句...里面涉及的东西太多了。
首先说明一下面试题的背景,项目不用 Rails 而是用 Sinatra, 后期很可能要转为Padrino. 所以对 Ruby 本身的基础知识要求比较严格,很多 gem 包都是直接提供给 Rails 用的,如何把它们拿来用于我们的项目,是一个小小的挑战。
Ruby 基础相关
1. each 与 map 的区别 涉及知识点:Ruby 迭代器的基本知识 为什么要问这个问题,主要是考察 Ruby 迭代器的基本知识点,我看过一些代码,比如下面这个:
def get_all_people_name
arr = []
@peoples.each do |p|
arr << p.name
end
arr
end
# 完全可以用一行代码搞定
@peoples.map &:name
其实我更想问的是,如何用 each
写一个类似 map
的方法
module Kernel
def my_map &block
arr = []
each { |i| arr << block.call(i) }
arr
end
end
2. proc, lambda, 和 Proc 的区别 涉及知识点:Ruby 中的闭包 这个题目几乎要被用滥了,但是为什么还要出这个题目呢? 就是想知道你知不知道闭包这个东西... 认真学过 Ruby 闭包的同学闭着眼都能说出一两句,如果你接触过 Ruby1.8 中的闭包,也会知道 proc(), lambda() 与 Proc.new() 与现在 Ruby 版本之间的不同。
并且,我可以继续和你讨论下有关闭包及相关作用域的问题...
3. alias 的用法,alias 与 alias_method 的区别 涉及知识点:Ruby 中的关键字 - alias, Module 中的方法 - alias_method. 用过 alias 和 alias_method 就可以发现它们之间用法的区别。
然后我会顺便问问你,为什么要写这个 alias...
另外有个隐晦的地方,alias_method 是有返回值的...当然,it is a joke.
static VALUE
rb_mod_alias_method(VALUE mod, VALUE newname, VALUE oldname)
{
rb_alias(mod, rb_to_id(newname), rb_to_id(oldname));
return mod;
}
4. 用过那些 gem, 简单的说一说各自的用途 这个用于聊一聊相关的 gem 及相关项目经验。
5. 画个图,体现一下 Ruby 的对象体系 涉及知识点:Ruby 对象体系 不多说了,直接看代码和图,不了解 Ruby 对象体系,就不会明白这个方法为什么要写在 Object 类里面
class Object
# activesupport/lib/active_support/core_ext/object/try.rb
def try(*a, &b)
if a.empty? && block_given?
yield self
else
__send__(*a, &b)
end
end
end
#78 楼 @blacktulip 这确实是这张图的一个大 bug 啊.... 难道真要在每一个 class 上面都画上一个 eigenclass, 然后 eigenclass 的关系用虚线表示,其走向跟实线一样?
#80 楼 @blacktulip 改天再画一张,eigenclass 直接塞到 class 里面去 这张图是当时在 windows 下用 word 画的,真蛋疼