一点梳理

Experiment

梳理知识时,用自己习惯的语言把要点重新描述一遍,即便不那么准确全面,通过语言描述这个过程本身已经更充分地调动起大脑处理相关信息,而帮助更好地理解记忆。

每个人的语言习惯、描述方式、知识背景不同,看其他人的解释有时候不那么容易理解。这种情况下自己做一点小试验,把语言/例子/模型转换为自己熟悉的,比较不同代码运行的结果更清晰直接。

Rails

刚开始接触 Rails 时确实如大家所说那样感觉有很多魔法,看代码一般也能理解是什么意思,比如 has_many :posts 很直观,但却不明白基本机理。

后面想到 Rails 是用 Ruby 实现的框架/DSL,很多时候以单纯的 Ruby 代码来理解会清晰一些,除开命名约定,这些魔法多是省略参数外面括号的方法调用,开头是一或多个 symbol 参数,后面是一组可选哈希参数,然后 Rails 在背后处理复杂业务逻辑。

Routes 里 resources :models 是生成对应规则;migration 文件是用 Ruby 代码来设置数据库,migrate 就是执行这些脚本。视图里面的 Helper 方法也是,最终返回给浏览器的是 HTML 代码,这些辅助方法就是生成相应 HTML 代码。

Rails 中 session 是在 sessions table 里创建一串随机字符作为 key,把设置的 sessions 作为值存储进去,再把 key 加密后存储到浏览器 cookies 里。

Routes 用接收到的 HTTP 方法和 URL 查找相匹配的 controller, action,然后把所有参数放进 params 一起送到 controller。

一些术语直译过来不那么容易理解,通过其实际作用来描述更容易理解:

The Asset Pipeline 先是对应预处理器把 SCSS/coffee 文件转编译成对应的 CSS/js 文件,再把这些文件合并、压缩成一个对应格式的大文件返回给浏览器。

ActiveRecord::Relation 是 Active Record 查询界面的一个中间层。使用 where, scope 等进行查询时所有可链接的方法先以某种形式的参数被保存进对应实例化的 Relation,在真正使用具体数据时这些参数被传递给 Arel 生成相应的 SQL 查询,后面把得到的结果实例化为相应对象返回。

Ruby

类方法可以使用其他类方法和类变量,但不能使用实例方法和实例变量;
实例方法可以使用其他实例方法和实例变量,以及类方法和类变量。

public vs protected vs private

三种声明从左到右调用方式越来越严格:

public 方法看到有描述是能被所有人调用,一开始不是很明白具体指什么,后面了解是指能被所有可能的方式调用,能直接被实例对象调用、在类或子类定义里被其他方法以显式或隐式接收者调用。

protected 和 public 相比,不能直接被实例对象调用。

private 则只能在类或子类定义里被其他方法以隐式接收者调用(除赋值方法需要 self 以区分本地变量)。

Block vs Proc vs Lambda

都属于某种形式的闭包/匿名函数,从左往右越来越接近真正的函数。

被作为参数传递到其他函数,常用来对遍历(#each)的项目进行操作;覆盖默认处理方式(#sort)。

Lambdas 可以使用显式 return, blocs / Procs 只能用隐式 return。

带参数时,Lambdas 会检查参数数目,如果数目不对会报错;blocs / Procs 如果没有提供参数返回 nil,多余的参数则被忽略掉。

Procs 和 Lambdas 为 Proc 类的实例,属于对象而可以赋值给变量,blocks 就只是一段代码。

记笔记的一点体会

Take Notes at Any Time

「随时记录、整理归纳、经常回顾,学以致用」

为什么记笔记?

为什么要记笔记呢?因为不记下来我会忘掉的

要记什么?

一些自己会记录的内容:

重要内容

学过的内容,无论当时记忆多么深刻,也很难一次就完全记住,时间久了很容易渐渐模糊遗忘。特别是一些不会经常用到的内容,再用到时可能已经不能清晰回忆起来,只是隐隐记得几个关键词。

这时候比起再读一遍、再学一遍,直接查阅笔记就方便有效多了。同时笔记也方便随时进行回顾,而加深理解记忆。对于特别重要的内容最好是放在醒目的地方,想办法经常用到。

时常用到

偶尔用到的内容,不要觉得网络上都有,可以很容易搜索到。网络上的内容可能分布在各个地方很零散,如果每次都重复搜索、筛选,消耗的时间精力累积起来还是很可观的。

把用到过的内容记下来并整理组织好,方便用到时直接查阅。如:开发环境配置、git/rails 常用命令、gem 设置,第一次配置完成后,趁印象清晰,把整个流程及注意事项记下来,下次就可以直接按流程操作。

对于待学习的内容,把关键词记下来。特别是一些英语关键词,不然准备进一步搜索了解时可能想不起来,或者拼写不正确。

记录常用英语词汇,容易混淆的,不容易拼写正确的,方便在遗忘时查阅。

待处理任务

需要处理的任务,不记下来的话,一忙起来就容易忘掉。记下来可以避免遗漏、还有努力回想却怎么也想不起来的情况,同时减轻大脑负担,把注意力专注在当下任务上。

灵感

对于一闪而过的想法、灵感,不记下来可能真的就一闪而过再也找不到。

怎么记?

为了不影响学习节奏,一般会把想到的内容先记在一个临时文件里,再抽时间整理归纳。当记录某个主题的文件里内容多起来、变得复杂时,可以再按细分主题拆分,放到相应文件或文件夹,让知识结构更清晰。

要及时对随手记下来的内容进行整理归纳,如果没有及时进行整理,四处散落的笔记就好像一屋子随处可见的杂物,用的时候要费大力气寻找,而整理好后不仅让人赏心悦目,同时可以随手拿来就用。

记录整理笔记本身也帮助更好地理解所学内容。一段时间记录下来,积累是很可观的。

简单说就是:随时记录,及时整理归纳,对重要的内容时常回顾,尽量学以致用。

调试小结

Cute Bug

心态

首先是培养良好的心态,出现任何问题,都不过于慌张,不急着盲目尝试,而是先理清楚所遇到的问题、找到问题原因。

如果花了较多时间仍没解决问题,又已经很疲倦、头脑不清晰,那继续盲目死磕多半也收效甚微。这种情况下较好的处理方式是停下来休息一会儿,喝口水吃点东西、伸展身体放松一下,再接着有策略有方法地死磕。

下面是自己调试 Rails 时常用到的一些基本方法:

重启

  • 重启服务器
    Rails 很多文件里用到 require 加载依赖文件,文件被编辑后不会自动重载,需要重启服务器生效。

  • 重启终端
    有时候需要重启终端才能让文件更改生效; Spring 也只在关闭终端时才自动关闭。

  • 重启电脑
    极少数情况重启终端仍不行,如新安装一个 gem 后不能正常运行安装命令($ bin/rails g gem:install),反复检查没发现其他问题,同时在网络搜索也没发现类似问题。

  • 重启 Heroku 服务器
    Heroku 服务器在每次部署后自动重启,但 migrate 后可能不会立即重启,这时最好手动重启让更改立即生效;没有 migrate 访问网页只是出现 500 错误,不像在开发环境会明确提示需要 migrate。

调试信息

在终端检查错误日志时要把终端窗口显示到足够大,让日志内容以良好格式清晰显示,从而更容易从日志信息中发现错误原因。

  • 在 Rails 日志显示信息

    Rails.logger.info "---------- Start}"
    Rails.logger.info {"Info #{@object.attributes.inspect}"}
    Rails.logger.info "---------- End}"

  • 在网页上显示调试信息

    <%= debug @object %>
    <%= simple_format @object.to_yaml %>
    <%= @object.inspect %>

  • 在网页上使用 console

    <%= console %>, 或者使用 Better Errors

  • Rails Console

    如果网页上不能正常创建、保存对象,可在 Rails Console 里测试是否有问题,或者使用 Pry

编辑文件

  • 确认编辑的是目标文件,注意文件名是否正确、单复数、文件名后缀

    • YML 文件里要用 ERB,而不能直接用 Ruby
    • 默认所有文件后缀已经更改时,容易在 CSS 文件里使用 SCSS / coffee 文件里使用原生 JavaScript 而出现错误
    • 调整样式时确认有选中目标元素、class 名正确,可添加红色边框确认;属性名及对应值正确,属性名之间可能混淆,也有可能错把另一个属性的值添加到目标属性上。
  • 编辑器安装 linter 扩展,检查基本错误

  • 一次只改动一个地方,确认有效无效后再作其他改动

搜索

如果遇到的问题不熟悉,那就要借助搜索引擎的力量。如果能直接找到解决方案可喜可贺,如果找到的信息和遇到的问题不完全相符、内容不完整、内容不是最新,那可以尝试:

  • 查文档
    很多时候查文档更直接有效

  • 搜索对应 gem/工具的 Github Issues
    找到的问题更相关

最后 Rails Guides 是一个好地方: Debugging Rails Applications

Differences among some methods in Ruby/Rails

Difference
Cheat sheet for some basic methods in Ruby/Rails

nil? vs empty? vs blank?

From Act on
nil? Ruby Anything Return true only for nil
empty? Ruby Array/Hash/String Return true when no elements, whitespace string is not empty
blank? Rails Anything Smart version of nil? and empty?, whitespace string is blank
present? Rails Anything Opposite of blank
presence Rails object (object.present?) ? object : nil

Only #nil and #false is considered false in Ruby

size vs length vs count

In Ruby
  • size, alias of length, faster
  • Enumerable#count, slower

String.length, Array / Hash.size

In Rails
  • count counts the number of elements with the SQL command ‘COUNT’, run SQL query everytime
  • length counts loaded objects and return the result
  • size call #length if a collection is loaded , or call #count

each vs select vs map/collect vs inject/reduce

  • each return the original collection,can use each_with_index do |item, index|
  • select return an object contains only items returned true
  • map/collect return an object filled with whatever returned each time
  • inject/reduce which passes whatever was returned by the previous iteration into the block. It ultimately returns whatever the result of the last iteration is. E.g., my_array.inject(0) { |total, item| total + item }

destroy vs delete

  • destroy run callbacks before remove records
  • delete remove object directly

When a record is not found

  • find_by() returns nil
  • find() raise ActiveRecord::RecordNotFound exception

选择程序语言的一点体会

How to Choose

对初学者最重要的是什么?

对我来说是能 学得下去

一门语言再热门,性能再好,但你不喜欢,学不下去,也是没有意义的。

为了能学得下去,初学者选择程序语言时可以考虑的点:

  • 是否感兴趣,最好认同语言背后的理念
  • 对初学者是否友好,学习资源是否丰富
  • 身边是否有人使用,社区成员是否活跃

1、身边有朋友用,跟着学习同样的语言,在关键的地方有人指导,能少走很多弯路。社区活跃,能从中吸收更多有益经验,在遇到困难时更容易获得帮助。

2、对初学者更友好,显然更容易学下去。学习资源丰富,能方便获得优质学习资源,学习更有效。

3、最重要的还是要回到自己这里,兴趣在哪里,更在意什么。学习兴趣浓厚,认同语言背后理念,才能更好面对学习过程中必然出现的阻碍。

不能偷懒只看其他人怎么说,也要自己体验思考。最好看看语言创建者是怎么说的,怎么想的,了解一下背后的故事。比如对 Ruby/Rails 感兴趣,看看 Mats/DHH 在会议上、推特上都讲了什么。

误区

回想自己刚涉足编程选择语言时的一个误区是害怕选错,而为了避免选错而延迟选择;另一个误区是以为会有一种完美的语言,花过多时间在语言间相互比较。

后面意识到很多问题不是只有一个正确答案,也没有完美的语言。

对于 Web 后端语言/框架,其实每一个选择都没有太大问题,都能实现同样的功能,只是实现方式有差异;也各有各的长处,要结合使用场景决定,要看你更在意什么。学好一门语言也可以相对容易转到另一门语言。

The Power of Habit 部分书摘

Brain

The Habit Loop - How Habits Work

大脑结构:越外面的大脑形成时间越近,负责复杂思考;越深/内/靠近脑干,形成越久远,负责无意识行为(呼吸)。基底核负责存储习惯,回顾起模式和作出行动

做一件事,一开始大脑必须全速运转来接收处理信息,做得多了大脑处理起来越来越轻松,决策、记忆相关的大脑结构活动逐渐减弱,到最后达到内化的程度完全无需思考。

大脑在不断寻找方法节省能量,这样带来巨大优势:大脑所需空间更少/头部更小/利于生产(减少母婴死亡率);不必思考基本行为,得以把精力花到更重要的事情上。

主动思考与无意识行为间的切换时机非常重要,如果在错误的时刻切换到无意识模式,可能会错过重要的信息导致严重后果,如未能发现隐藏起来的天敌。

大脑是根据特定信号来判断自动模式/习惯的开始和结束,及用到哪一种习惯,大脑在接受到开始信号前高度活跃-无意识行为减少大脑活动-接受到结束信号再次活跃。

loop: cue - routine - reward, over time more and more automatic
cue - trigger tells your brain to go into automatic mode and which habit to use
routine - can be physical, mental, or emotional
reward - help brain figure out if this loop is worth remembering for the future

习惯需要细微/精确的线索来触发,cue 稍微作出改变就不能引发出习惯。

为了避免再次学习,习惯被编码/刻进大脑,所以习惯一旦建立几乎不会消失,等待着未来某个 cue 的激发。这是一种巨大优势,遗憾的是大脑不能区分好习惯与坏习惯。

How to Create New Habits

  • simple and obvious cue
  • clearly define the rewards

除臭剂广告策略变化:没人渴望无味(除臭),却有很多人渴望香味。

用户需要一些信号/反馈来得知产品在起作用,如很多产品中的泡沫、香味形成渴望/信号,如果没有这些反馈便感觉没有清洁干净,尽管实际上这些泡沫/香味并不增加清洁效果。

How to Change Habits

习惯一旦形成便无法消失,但可使用相同的 cue reward,改变 routine。

新习惯在面临巨大压力时常常会失效,routine 退回到旧习惯。如果有相信自己能做到的信念更可能让新习惯持续(即使面临压力);在团体中更可能保持新习惯,看到其他人能做到,更容易相信自己也能做到。

多数团体只是一群人在一起工作,而不是真正的团队。

Keystone Habits

锻炼/运动给其他方面带来有益改变,学习更高效、感到压力更少,虽然原因不明,但运动是很多人的关键习惯。

small win 一旦达成,便有一股力量出现想要再一次 small win。small wins 多了之后形成 pattern 让人相信更大的 achievements 是可达到的。

癖好

Game

喜欢的游戏

音乐、画面、情节、细节都俱佳,玩游戏时少有看攻略,喜欢慢慢探索游戏

喜欢的动漫

或有趣、或深刻、或震撼

富坚义博

宫崎骏

八木教广

井上雄彦

喜欢的音乐

更在意旋律与节奏,不那么在意歌词;更在意声音里面的情绪,不那么在意演唱技巧

喜欢的电影

主要评判标准为是否打动自己

最近在读

在线课程

Helpful Links

About This Site

作为练习项目,同时也是自己发布文字、展示项目的地方

数据结构、样式都很简单,只是完成度稍微高一些:

  • 响应式排版,页面本身简单,容易实现
  • 文字内容支持 Markdown,基本满足使用
  • 使用 FriendlyId 优化 URL,如有汉字转化为拼音
  • 链接显示方案为灰蓝字体、加下边框

作为练习,使用 Ruby 方法实现登录、退出、基本权限管理;除了 Reboot 没有使用样式框架,直接用 SCSS 调整样式。

网站通过 Heroku 部署,使用 Cloudflare 管理 DNS 及其提供的 HTTPS 服务。