subl
……,话说我原文里有写,LZ 你不认真!哈哈
从汉语看,用户
:个体,用户列表
:群体,两个词里的 用户
虽然看起来一样,但是暗示的数量不同且无歧义,这是 OK 的。但是从英语看 user
和 user_list
,两者的 user
虽然一样,却无法暗示数量有差别,你可以说 user_list
是 N 个用户组成的列表,也可以认为是一个用户的列表,虽然前者更常见,但仍然有歧义。REST 虽然并没有强制规定复数资源一定要用名词的复数形式,但是 REST 提倡资源的表述应当准确,消除歧义。也许在多数应用里这样的变化不至于让人摸不着头脑,但是谁敢保证所有的业务场景用后缀 _list
都不会产生歧义?一旦产生歧义怎么办?改用复数形式?改后缀?那么所谓的“一致性”又如何体现?Rails 在设计之初约定了使用名词的复数形式,这是英语天然的特性(名词皆有复数形式),且符合 REST 用名词指代资源的倡导,所以这是自然而然的事情。
Rails 的理念是“约定重于配置”,而不是“只有约定没有配置”。如果你的应用程序在设计时可以确定新的约定不会引起歧义,那么你可以重新配置。正是 Ruby 语言和 Rails 框架的灵活性才得以让二者得兼,因此完全没有必要抱怨默认的约定不符合你的“口味”,更何况这个“口味”的根源在于英语不过关……
如果线上的 file 不是通用的,也就是说拉到本地之后会根据不同的环境做不同的配置,那么线上的文件就只是一个范例或是模板。因此,它应该和实际运行时的文件区分开来,比如说重命名为 file.example
。之后在客户端拉取代码后,自己复制一份重命名,然后用 .gitignore
忽略掉。
如果出现已经 commit 过的文件无法被忽略,那么需要执行:
$ git rm <FILENAME>
之后提交推送,此后 .gitignore
才会对此文件生效。原因是 .gitignore
只会对没有被 git 记录过的文件生效,也就是 untracked file。
既然要完全剥离开,为什么还非要放在 Rails 的项目路径下?单独做一个不就好了?
真是个人口味不同,我是喜欢能简则简,凡是使用频度很低的,能用快捷键代替的东西坚决不出现在顶栏。
yield
最好不翻译,如果想要用中文理解它的话,“产出”,“生成”,“萃取”……结合一下这些词,想象一下就好。
与原作者有同感,现在不怎么喜欢 CoffeeScript 了,不过不介意阅读或是参与使用 CoffeeScript 的项目,只是更喜欢写 JavaScript 而已。
一般来说,团队开发应当使用一种项目管理工具,比如说 Github 的 Issue 功能就足够。每做一件事情(事情的粒度酌情而定,也不一定非得是一个功能,符合团队的惯例即可)创建一个 Issue,每一个 Issue 对应一个 Commit。这叫:有因(问题)有果(提交)。
当然,我们处理某个 Issue 的过程中不一定只能做一次提交,关键是 Push 之前要做整理。用 Git 的好处之一就是在 Push 前,一切都是好修改、好整理的,不会影响中心代码库。
所以你可以把针对某个 Issue 的处理分解成一条一条小的 Commit,但是不要每次 Commit 之后立即提交,而是等到整个 Issue 处理完毕之后再整理和 Push。
至于整理,这是一个大话题,可用的办法和策略相当多。比如你可以用分支合并产生一条完整的 Commit;也可以用 Interactive Rebase 进行高可控性的细致调整(如果你没用分支的话),等等。更具体的,就需要你系统的学习 Git 的方方面面了。
顺便一提:无论是分支合并还是交互 Rebase 或是其他什么方式,产生的最终记录应当详细规范的填写 Commit Message,具体怎么写看团队规范,没有团队规范就定一个。比较通行的惯例是:第一行简要概述(或者写 Issue 的 ID + 标题),之后空一行后面写过程概要(用列表方式),或者是详细说明(用段落方式)。如果说提交前有什么注意事项,这一条是最重要的。
这个配图原本是一个讽刺来着
Ctrl +[ 谁用谁知道
#8 楼 @moliliang 找一个半天的时间,和你们同事当中用 Git 最好的那位结对一下,告诉他你主要是来学习什么的,你的主要问题有哪些。
不错,可惜在北京,若是上海的话就去了,遗憾一个
#2 楼 @cassiuschen 查一下 document.ready 事件就知道了,基本等价于 window.load,更健壮一些。
为什么 $back
和 $backword
放在 $(document).ready
外面?
https://github.com/twbs/bootstrap-sass
顺便一提,一年前还是菜鸟的时候曾在 anjlab 和 thomas mcDonald 这俩版本的 bootstrap-sass 中逡巡好久,后来还是选择了后者。时至今日,摇身一变成了 Official Version 了,暗赞自己的选择有眼光……
楼主你别没事找事给自己虐心了好不?宣传上有说 “连续看视频八九个小时” 么?你以为显卡满负荷工作是不费电的呀?
如果你真的对电量这事这么上心,倒不如去官网看看如何正确使用 Apple 设备的电池吧。
至于第一个问题,我只能告诉你:正常!你认为流水线下来的机器都不带通电自检就会直接装箱上架的吗?如果你不放心直接打 400 去问好了,不行就 12315 质检。买个电脑看把自己闹腾的……
#2 楼 @assyer 真相:http://images.apple.com/media/us/ipad-air/2013/0be12b9f-265c-474c-a0cc-d3c4c304c031/overview/desktop/story/story.mp4
用 JS 控制,重点 window.requestAnimationFrame
先说属性与方法,前不久我写 理解 JavaScript 的时候刚好谈过这个问题。对象中的属性与方法一直以来让很多初学者混淆不清,其根源在于翻译。为什么这么说呢?英文书籍里当谈到对象的属性时,会出现两种情况:
Attribute:特指用来保存 数据 的属性(如 Ruby 中的实例变量)而不是 行为(如 Ruby 中的方法);
Property:这是一种统称,无论是用来表示 数据 的 Attribute,还是用来表示 行为 的 Method,它们都是对象的 Property;
在英文里这样表述毫无问题,当读者看到 Property 时,就明白这是在泛指对象的属性(包括数据和行为);而看到 Attribute 时,就知道这是在特指保存数据的属性(比如对象的实例变量)。然而在大多数中文书籍里都没有解释过这个区别,而是一概用 属性 一词带过。
这个问题我关注好久了,也发现一些译者在探讨这个问题的解决办法,遗憾地是目前还没找到什么行之有效的替代方案。我想这也是很多人极力建议阅读英文原本的重要理由之一吧?
Property 一词有“财产”的意思,可以引申为“归属物”,所以你说 Method(方法)是一个 Property(属性)是毫无问题的(反过来说某个 Property 是 Method 也(可能)是对的);但是 Attribute 一词则强调的是“特质、特征”的含义,方法是“行为、动作”,所以说 Method 是一个 Attribute 就不太恰当了(反之亦然)。
然后来说说虚拟属性。
一般而言,我们创建对象的时候会通过构造函数把对象的 Attributes 通过参数传递进去,这样对象实例化时就会拥有属于自己的 Attributes 了。像 Rails 则直接把 Model 的 Attributes 定义和数据实体的字段(fields)关联起来,对象即是(数据库里的)数据,数据也是对象。
然而在现实中我们会遇到一些特殊情况,比如说对象的某一个 Attribute 是需要通过组合、转换、处理其他的 Attribute(s) 来得到,这样的话直接通过变量传参进来就不合适了。
例如你要创建一个 长方形 对象,需要它有三个属性:长
,宽
,面积
,长
和宽
好办,创建时传参进来,面积
呢?它不好直接传参,它看起来也不是一个方法,它的值取决于实例化时传入的另外两个参数,于是我们可以自己定义面积
属性的 getter/setter 方法,之后就可以把它当成 Attribute 来使用了(事实上,它就是一个 Attribute)。
我记得镐头书好像有一个点唱机的例子,一首歌播放的长度在实例化的时候传入的参数是秒,但是需要显示成分钟,于是就创造了一个虚拟属性:duration_in_min
。这也是一样的道理。
虚拟属性也有被称作 Computed Property 的(Ember.js 就这么叫的吧,我不确定是不是完全一样,印象中是的)。计算后属性这个词虽然拗口,但我觉得还是比较形象的。
最后我用 JavaScript 来举例和 Ruby 对比一下:
function Person(firstName, lastName) {
this.firstName = firstName; // 定义 Attribute
this.lastName = lastName; // 也是定义 Attribute
this._fullName(); // 初始化 Virtual Attribute
};
// 定义方法
Person.prototype.greeting = function (words) {
console.log([this.fullName, 'says:', words].join(' ')); // 使用了虚拟属性
};
// 定义虚拟属性
Person.prototype._fullName = function () {
this.fullName = [this.firstName, this.lastName].join(' ');
};
注:本例并非 JavaScript 的最佳实践,
_fullName
方法用来生成虚拟属性,不应该直接通过原型暴露给实例对象。在现实中一般会采用某种模块模式,使用闭包把这个私有方法隐藏起来,只向外提供fullName
虚拟属性本身。
在 Ruby 当中,这个问题可以简单地使用private
把私有方法隐藏起来,但是 JavaScript 比较麻烦且写起来占版面,加之与本楼问题无关,所以本例中做简化处理了。
另外,本例中fullName
的求值相当简单,完全没有必要定义_fullName
来实现,这里只是为了呼应上文提到的 getter/setter 而写的示例而已,略显“脱裤子放屁”……实际上,上例可以简化为:
function Person(firstName, lastName) {
this.firstName = firstName; // 定义 Attribute
this.lastName = lastName; // 也是定义 Attribute
this.fullName = [firstName, lastName].join(' '); // 初始化 Virtual Attribute
};
// 定义方法
Person.prototype.greeting = function (words) {
console.log([this.fullName, 'says:', words].join(' ')); // 使用了虚拟属性
};
有木有一不小心给自己挖坑往里跳的赶脚……