在 Rails 应用中,action 的返回的render对象都会套用 layout。这对于普通的 html 请求和 json数据请求都没有问题。html请求需要layout,而 json 数据请求直接 render 数据,不会套用 layout,那么对于普通的 ajax 请求呢?

destroy.js.erb?

对于普通的RJS请求,通常都不需要走layout,那么需要在每一个respond中设置吗?

1
format.js { layout: false }

想要设置所有的rjs请求没有layout,可以把layout设置为一个 Proc。 设置基类的layout

1
layout proc { |c| c.request.xhr? ? false : application }

清理Console

当输出满屏时,想清理一下,在bash里可以用clear,在rails console里,可以用command+k

重新加载rails环境

console环境不会自动加载修改后的文件,怎么办?退出重启?不需要!执行 reload!

搜索历史纪录

执行的command太多,往上可以用 uparrow, 往下可以用downarrow。但是当执行的命令太多时,上下翻历史记录耗费的时间,比直接输入来的更多。其实console有搜索功能,Ctrl+R

1
2
3
4
[1] pry(main)> reload!
Reloading...
=> true
(reverse-i-search)`r': reload!

输入r出来 reload! . 第一个匹配的记录

Tab补全

tab补全,属性bash的应该对这个都不陌生。

上一个命名的结果

执行完一条命令

1
>>Article.first

但其实你还想对这个返回的 article 对象继续操作。在执行一遍?

1
>>article = Article.first

NO! 你可以用, article = ; _保存着上一条命令返回的结果

发起HttpRequest

1
2
3
4
>>app.get /
=> 200
>>app.get /orders
=> 302

Rails沙盒

console可以已沙盒的模式运行,rails console —sandbox

1
2
3
>>User.destroy(1)
>>exit
     (0.1ms) rollback transaction

Rails环境

想要test环境的console,除了RAILS_ENV=test rails c, 更简单的是rails c test

iOS

Core Data是现在iOS中主流的数据存储选择。虽然Core Data的学习对于Mac/iOS开发新手来说,算是学习曲线比较陡的,但是一旦熬过了,使用还是很便利的。

各种介绍文章都会介绍如何设置NSPredicate, 如何设置NSSortDescriptor, 返回NSManagedObject对象。那么如何获得某个属性的最小值,最大值?

对于刚学习Core Data的人想到的第一方法很可能就是设置fetchLimit为1, 然后根据要获取的那个属性进行排序。这也是一种方法,也能完成任务;但是如果要获取这个属性的Sum值呢?

NSExpression

Core Data中有NSExpression来完成Aggregate操作。

首选需要设置你的目标属性, 比如salary

NSExpression *keyPathExpression = [NSExpression expressionForKeyPath:@“salary”];

然后设置想要的聚合操作

1
2
NSExpression *maxSalaryExpression = [NSExpression expressionForFunction:@"max:"
                                                  arguments:@[keyPathExpression]];

再设置NSExpressionDescription

1
2
3
4
NSExpressionDescription *expressionDescription = [[NSExpressionDescription alloc] init];
[expressionDescription setName:@"maxSalary"];
[expressionDescription setExpression:maxSalaryExpression];
[expressionDescription setExpressionResultType:NSDecimalAttributeType];

Objective-c就是以他的verbose闻名的。

1
2
[request setResultType:NSDictionaryResultType];
[request setPropertiesToFetch:[NSArray arrayWithObject:expressionDescription]];

设置request的返回类型是一个Dictionary,这个Dictionary的key就是这个expressionDescription的name, value就是expression的执行结果。

最后再调用executeFetchRequest

1
2
3
4
5
6
NSArray *results = [objectContext executeFetchRequest:request error:&error];
if (!results || [results count] == 0) {
    return NSIntegerMax;
}

NSNumber *maxSalary = (NSNumber *)[[results lastObject] valueForKey:@"maxSalary"];

对于如何执行Sum操作,基本一样。

So,试试NSExpression,别再使用fetchLimit=1 了。

iOS

Mantle, 来自github的一个十分便利的model层框架,它能把数据从JSON转成Objective-c对象,也可能把一个MTLModel对象转成JSON数据。

Mantle的官方说明中, 在基本的情况下,只需要实现一个mapping方法,就能轻松的实现数据的转换

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
 + (NSDictionary *)JSONKeyPathsByPropertyKey {
     return @{
         @"URL": @"url",
         @"HTMLURL": @"html_url",
         @"reporterLogin": @"user.login",
         @"assignee": @"assignee",
         @"updatedAt": @"updated_at"
     };
 }

//转换为NSURL类型
 + (NSValueTransformer *)URLJSONTransformer {
     return [NSValueTransformer valueTransformerForName:MTLURLValueTransformerName];
 }

 + (NSValueTransformer *)HTMLURLJSONTransformer {
     return [NSValueTransformer  valueTransformerForName:MTLURLValueTransformerName];
 }

然后用+[MTLJSONAdapter modelOfClass:fromJSONDictionary:error:]就能解析JSON数据,得到Objective-C对象了。

不过这不是写这篇文章的目的,这篇文章的重点是如何再把这个对象存到Core Data中。

对于持久化,Mantle的官方文档紧紧提到:

Mantle doesn’t automatically persist your objects for you. However, MTLModel does conform to , so model objects can be archived to disk using NSKeyedArchiver. If you need something more powerful, or want to avoid keeping your whole model in memory at once, Core Data may be a better choice.

只说了要想实现Core Data比NSCoding更好用,没说怎么用;但是其实Mantle已经支持把从JSON反序列化得到的对象存到Core Data里了。

实现+ (NSDictionary )managedObjectKeysByPropertyKey + (NSString )managedObjectEntityName 方法,前者负责从对象到数据库字段的mapping,后者说明Core Data中Entity对象的名字

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
 + (NSDictionary *)managedObjectKeysByPropertyKey {
    NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];

    [dictionary setObject:@"name" forKey:@"name"];
    [dictionary setObject:@"address" forKey:@"address"];
    [dictionary setObject:@"days" forKey:@"daysOfWeek"];

    [dictionary setObject:@"startDate" forKey:@"startDate"];
    [dictionary setObject:@"endDate" forKey:@"endDate"];
    [dictionary setObject:@"location" forKey:@"location"];

    // ignore these two properties
    [dictionary setObject:[NSNull null] forKey:@"hoursOfOperation"];
    [dictionary setObject:[NSNull null] forKey:@"datesOfOperation"];

    return dictionary;
}
 + (NSString *)managedObjectEntityName {
    return @“NNStore;
}

然后再先从JSON转到Model对象,再存到core data中

1
2
3
4
5
6
7
8
9
10
11
NSArray *markets = [json valueForKeyPath:@“stores];
[markets enumerateObjectsUsingBlock:^(NSDictionary *obj, NSUInteger idx, BOOL *stop) {
    MFMarketModel *market = [MTLJSONAdapter modelOfClass:[MFMarketModel class]
                                      fromJSONDictionary:obj
                                                   error:NULL];
    NSManagedObject *managedMarket = [MTLManagedObjectAdapter managedObjectFromModel:market
                                                                insertingIntoContext:self.managedObjectContext
                                                                               error:NULL];
}];

[self.managedObjectContext save:nil];

Mantle还支持unique检查,实现+ (NSSet *)propertyKeysForManagedObjectUniquing就可以做到唯一性检查,非常简单。

如果你还没有用过,那就赶紧试试吧。

为什么要更新?用着好好的。新版本可能会修正bug,提高性能;其实最重要的是,作为一个Geek,就是想要用最新版的而已。

How

找到官方文档,Updating Octopress, 按照指示

updating octopress
1
2
3
4
git pull octopress master     # Get the latest Octopress
 bundle install                # Keep gems updated
 rake update_source            # update the template's source
 rake update_style             # update the template's style

才执行第一句,就出错了

error
1
2
fatal: 'octopress' does not appear to be a git repository
fatal: Could not read from remote repository.

什么情况? 找不到名为Octopress的repository! 按照官方的设置,标准的Octopress有两个Branch, 一个Source,一个Master, Source分支上有你的源文件;Master就是最终生成的站点文件。 确实找不到Octopress 仓库,^_^

Add Remote Octopress Reository

git remote add octopress https://github.com/imathis/octopress.git

再执行官方文档给出的ruby语句,这下没问题了。

看看这样的代码?

1
2
3
<% if current_user && current_user.is_admin? %>
 <%= do something %>
<% end%>

而事实上可以写成这样

1
2
3
 <% if current_user.try(:is_admin?) %>
     <%= do something %>
 <% end%>

current_user为nil的时候,try不会抛出异常,而是返回nil

多个try还可以链接调用

current_user.try(:is_admin?).try(:home_address)

传参数和block

1
2
  current_user.try(:is_old_than?, 21)
  current_user.orders.try(:collect) { |p| p.order_id }
mac

能用Macbook Pro或者Retina Macbook Pro的充电器给Macbook Air充电吗?一个功率是45w,一个是85w(13’的是60w),可以还是不可以?

能用给iPad充电的插座给iPhone充电吗?两者输出的电流不一样。可以吗?

今天给一个官方正式的答复,可以!

来自苹果官方的回复

Power adapters for Intel-based Apple notebooks are available in 45W, 60W, and 85W varieties. Although you should always use the proper wattage adapter for your Apple notebook, you can use an adapter of a higher wattage without issue.

For instance If you have a MacBook (13-inch Late 2009) that normally uses a 60W adapter, you can also use an 85W adapter with that computer. You would not use a 45W adapter with that computer; it would not provide enough power for that MacBook. 

Using an adapter of higher wattage than the adapter that came with the computer will not cause the computer to charge more quickly or otherwise operate any differently than using the adapter that came with the computer. The tables further down in this article show the style of connector that initially shipped with each model of MacBook, MacBook Pro, and MacBook Air. 

简而言之,就是可以用功率高的,给功率低的充电,反之则不能!

Sublime Text之所以那么强大,是因为她支持各种各样的插件包,几乎你能想到的她都有。因此把Sublime Text配置到让你觉得舒服的情景是一件比较繁琐的事情,你绝对不会想要配置第二遍。 当然作为一个程序员,想尽一切办法也不干Repeat的事情。

怎么办?同步嘛,用各种同步软件在各个机器上保持同步,比如Dropbox。

在主机上

1
2
3
4
cd ~/Library/Application\ Support/Sublime\ Text\ 3/Packages/
mkdir ~/Dropbox/Sublime
mv User ~/Dropbox/Sublime/
ln -s ~/Dropbox/Sublime/User

在其它机器上

1
2
3
cd ~/Library/Application\ Support/Sublime\ Text\ 3/Packages/
rm -r User
ln -s ~/Dropbox/Sublime/User

这里同步是只有Packages/User/文件夹,而不是整个Packages文件夹。这个文件夹包含了Package Control.sublime-settings文件,这个文件包含了安装的包和配置信息,当在另一个Sublime Text开启时,他会根据这个文件自动检测,安装包含的包,还解决兼容性问题。

Module在Ruby中扮演着至关重要的角色,如果你从是Java或者C#背景转到Ruby来的,一开始你通常会忽视掉Module的重要性。直到你深入学习Ruby,你才会发现Module有多么重要

作为命名空间

作为命名空间这个功能十分好理解,模块嘛! 比如你创建一个Document的类,由于Document这个字非常常见,因此别人也使用它作为类名的概率不低。

如果碰到这种情况,那就苦逼了。由于Ruby对于Class的定义方式,Ruby检测到两处定义同一个Class并不认为有问题,而是把两个类的定义合并(Monkey Patch就是这么实现的)。如果遇到同样的方法或字段,后定义的会覆盖前面的。

用作MixIn

Module可以被用来代替Monkey Patch, 以mixin的方式给类定义增加方法

include module
1
2
3
class Computation
  include Comparable
end

通过Include Comparable这个module,Computation类定义就有了Comparable的各个比较方法,<, <=, >, >=, ==等。 Computation类的实例也就有了这些比较方法。

当把include一个module到一个类定义中时,ruby会把这个module加入到这个类的class chain上,比如

include module: added to class chain
1
2
3
4
5
6
7
8
module A
end

class AClass
  include A
end

AClass.ancestors => [AClass, A, Object, Kernel, BasicObject]

所以,所有AClass的实例都会有Module A中的方法。

除了include, 还有extend

extend module
1
2
3
class Computation
  extend Comparable
end

通过extend来扩展Computation本身(类对象本身),由于Computation类本身也是一个对象,通过extend扩展的方法会增加到这个对象上,而不是Computation作为类定义上,因此Computation本身有<, <=, >, >=, ==这些方法,而Computation的实例对象没有。

不同于include,extend的module不会被加到类的class chain上。

Module还有一些更复杂的使用方法,比如模拟Singleton模式,下回介绍

使用Octopress在Github Pages上建博客,根据Octopress官网的介绍建立好博客后,想在另一台电脑上写文章时,如何设置?

按照官网的介绍再来一遍会把已经发不到Pages上的全部删掉。当然可以把已经有的文章copy下来,再发遍就是了。但是这么个搞法,起初的那台机器就又不行了!肯定会有更好的解决方法

Octopress项目结构

其实整个Octopress项目无非是一个git文件夹,只是他借用了git的branch功能。

整个project的源文件在source的分支上,编译后的_deploy在master分支上,而Pages会读取master分支上的,因此打开username.github.io看到的是和本地预览时看到的一样的,而不是一堆源文件。

完全复制项目

既然是一个git项目,那就可以整个克隆下来,只不过是要克隆两次。首先克隆source分支。

git clone -b source git@github.com:jun1st/jun1st.github.io.git

再克隆master分支,master分支默认的文件夹路径是_deploy

git clone git@github.com:jun1st/jun1st.github.io.git _deploy

就这么简单 PS: 这里的路劲是我的项目的地址,别一起复制了:)

之前解决这个问题的时候,就想写这篇的,又觉得太简单就算了。今天不知道怎么搞的,pro上的项目又乱了,又弄了一次,也就写了,做个记录。