Comments

Ruby链式调用安全符号(&.)

Ruby-2.3.0版本添加安全操作符&, 其实我们之前可能是用try处理这种安全调用,但毕竟try是依赖Rails的ActiveSupport Module,&与try之间还是有些区别的;

使用场景

在代码中我们防止nil对象调用报错,我们一般会使用下面这样的逻辑判断来避免错误

1
2
3
if account && account.owner && account.owner.address
...
end

如果我们includes ActiveSupport我们会这样调用

1
2
3
if account.try(:owner).try(:address)
...
end

使用&符号

account&.owner&.address

其实&与try区别在于&前面方法返回nil就会终止链式调用, try则是检测最后的方法是否存在如果不存在就返回nil

1
2
3
4
5
6
7
8
9
10
11
12
account = Account.new(owner: Object.new)
account.owner.address
# => NoMethodError: undefined method `address' for #<Object:0x00559996b5bde8>

account && account.owner && account.owner.address
# => NoMethodError: undefined method `address' for #<Object:0x00559996b5bde8>`

account.try(:owner).try(:address)
# => nil

account&.owner&.address
# => NoMethodError: undefined method `address' for #<Object:0x00559996b5bde8>`
Comments

使用MySQL存储emoji表情符号

一个emoji是4bytes的存储空间, 如果你的MySQL使用的是utf8编码格式那emoji符号存储将会截断字符因为utf8一个字符只是 3bytes的存储空间

例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
mysql> SET NAMES utf8;
Query OK, 0 rows affected (0,00 sec)

mysql> INSERT INTO messages (message) VALUES ('What a nice emoji😀!');
Query OK, 1 row affected, 1 warning (0,00 sec)

mysql> SHOW WARNINGS;
+---------+------+---------------------------------------------------------------------------+
| Level   | Code | Message                                                                   |
+---------+------+---------------------------------------------------------------------------+
| Warning | 1366 | Incorrect string value: '\xF0\x9F\x98\x80!' for column 'message' at row 1 |
+---------+------+---------------------------------------------------------------------------+
1 row in set (0,00 sec)

mysql> SELECT message FROM messages;
+-------------------+
| message           |
+-------------------+
| What a nice emoji |
+-------------------+
1 row in set (0,00 sec)

使用utf8mb4格式可以存储emoji字符,但是MySQL 5.5.3版本才引进utf8mb4编码格式,所以数据库要更新到这个版本或者更高的, 用utf8mb4之后我们经常会遇到Mysql2::Error: Specified key was too long; max key length is 767 bytes错误,这是因为Innodb的索引长度限制767bytes, (varchar(255) * 4bytes)这个是会超过767bytes

如果你的字段类型长度不能减少,那只能是指定行的格式来解决,在创建表时指定ROW_FORMAT=DYNAMIC参数可以从767bytes限制提升到3072bytes, 这样就是会牺牲一点空间

例如:

1
2
3
4
5
6
7
8
9
10
CREATE TABLE `bookmarks` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `url` varchar(255) COLLATE utf8mb4_bin DEFAULT NULL,
  `title` varchar(255) COLLATE utf8mb4_bin DEFAULT NULL,
  `user_id` int(11) NOT NULL,
  `created_at` datetime NOT NULL,
  `updated_at` datetime NOT NULL,
  `site_info_id` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=25 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin ROW_FORMAT=DYNAMIC

如果使用的是Rails的migration的话就如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class CreateArticles < ActiveRecord::Migration[5.0]
  def change
    create_table :articles, options: 'ROW_FORMAT=DYNAMIC' do |t|
      t.string :title, null: false, limit: 300
      t.datetime :published
      t.string :author
      t.text :description
      t.text :content

      t.timestamps
    end

    add_index :articles, :title, :unique => true
  end
end
Comments

使用Ruby MonitorMixin注意的坑

初次使用MonitorMixin控制同步执行的时候一不小心就踩坑了,当你include的时候如果你的class定义了initialize方法 请调用super否则会报undefined method `lock' for nil:NilClass错。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Number
  attr_accessor :n

  include MonitorMixin

  def initialize(*args)
    @n = 0
    super() # 调用MonitorMixin#initialize
  end

  def increase(x)
    synchronize do
      @n = @n + x
      puts("#{@n}, #{x}")
    end
  end
end
Comments

ember使用express做后台API服务

使用Ember CLI的ember generate server命令创建server,模块会生成server/index.js文件,该服务是基于Express框架

ember generate server

server/index.js默认内容

1
2
3
4
5
6
7
8
9
10
11
12
13
module.exports = function(app) {
  var globSync   = require('glob').sync;
  var mocks      = globSync('./mocks/**/*.js', { cwd: __dirname }).map(require);
  var proxies    = globSync('./proxies/**/*.js', { cwd: __dirname }).map(require);

  // Log proxy requests
  var morgan  = require('morgan');
  app.use(morgan('dev'));

  mocks.forEach(function(route) { route(app); });
  proxies.forEach(function(route) { route(app); });

};

从内容分析可以看出,其实这个服务可以让前端更好的mock API的数据做测试,这样在工作配合上前端不需要等后端API调式 可以使用server模拟数据;

也可以自定义API数据接口

1
2
3
4
5
6
7
8
9
10
11
12
// server/index.js
var bodyParser = require('body-parser');

module.exports = function(app) {

  app.use(bodyParser.json({ type: "application/json" }));

  app.get('/api/items/:item', function(req, res) {
    const item = localdb.find('item', req.params.item);
    res.send({ item: item });
  });
}

运行服务

ember server

我们就可以通过http://localhost:4200/api/items/1API获取数据

Comments

Ember容器注入对象

Ember注入是用来将一个对象注入到一个容器里面去,让容器可以访问对象,容器是指routecontrollerhelper

使用用例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// app/services/session.js
export default Ember.Service.extend({
  isAuthenticated: false
});

// app/initializes/inject-session.js
export function initialize(application) {
  application.inject('route', 'service:session');
}

export default {
  name: 'session',
  initialize: initialize
}


// app/routes/products.js
export default Ember.Route.extend({

  model(){
    this.session
  },
  setupController(controller, model){
    this.session
    ...
  }
});
Comments

Intersection-of-two-arrays

Given two arrays, write a function to compute their intersection.

Example: Given nums1 = [1, 2, 2, 1], nums2 = [2, 2], return [2].

Note: Each element in the result must be unique. The result can be in any order.

# @param {Integer[]} nums1
# @param {Integer[]} nums2
# @return {Integer[]}
def intersection(nums1, nums2)
  nums1 & nums2
end
Comments

Reverse Vowels of a String

Write a function that takes a string as input and reverse only the vowels of a string.

Example 1: Given s = “hello”, return “holle”.

Example 2: Given s = “leetcode”, return “leotcede”.

1
2
3
4
5
6
7
8
9
10
11
12
# @param {String} s
# @return {String}
def reverse_vowels(a)
  tmp = a.length.times.inject([]) do |s, i|
    /(a|e|i|o|u)/i =~ a[i] ? s << i : s
  end
  tmp.length.fdiv(2).ceil.times.each do |i|
    v, b = tmp[i], tmp[tmp.length-1-i]
    a[v], a[b] = a[b], a[v] if v && b
  end
  a
end

Comments

Devise Warden报错401

今天遇到一个特别的问题在项目里面使用devise应用到User与Admin, 因为User是可以用手机号码和Email登录的, 而Admin只能邮件登录,结果User可以正常登录,但是Admin应该也可以正常登录,但是就是报401密码错误,经过翻看源码发现一个很好的工具,找到出现问题的原因

(byebug) Devise::Models.check_fields!(Admin)
*** Devise::Models::MissingAttribute Exception: The following attribute(s) is (are) missing on your model: phone

因为我在devise.rb配置了

config.authentication_keys = [:email, :phone]

所以我要在Admin模型里面指定authentication_keys

devise :database_authenticatable, :registerable,
     :recoverable, :rememberable, :trackable, :validatable,
     :authentication_keys => [:email]
Comments

Ember-cli入门指南

ember-cli是什么?

ember-cli是一个ember.js提供的一个快速开发命令行工具,可以通过命令构建、运行、测试、部署,很方便 前后端分离,而且ember有很丰富的addon生态社区,把重用的东西组件化, 项目开发完成用build命令会输出一个index.html和编译好的js、css文件这个输出就是静态的,我们可以用nginx或node express服务器来展现编译好的静态资源,其实ember-cli的命令行工具设计的跟Rails Command相似,addon就是ruby的gem包可能 是因为ember的开发也是Rails核心贡献开发,所以很多设计思想互通。

命令介绍

//构建项目
$ ember new todo

//运行项目
$ ember s

//生成路由
$ ember generate route products/new

//运行测试
$ ember test

//安装addon
$ ember install <addon-name>

目录结构

app/    => 主要包含了models、controller、minxin、routes、template、index.html、application所有项目相关逻辑代码多会在这里面
dist/   => 编译输出目录里面index.html和js、css
public/   => 存放一些静态文件例如:图片、字体
tests/    => 测试逻辑
bower_components/    => bower包依赖源文件
node_modules/     => npm包依赖源文件
vendor/   => 自己扩展依赖
ember-cli-build.js  => 指定编译配置文件
bower.json   => bower依赖配置
package.json    => npm依赖配置

config/environment.js

module.exports = function(environment) {
  var ENV = {
    modulePrefix: 'todo',
    environment: environment,
    baseURL: '/',
    locationType: 'hash',  
    contentSecurityPolicy: {
      'connect-src': "'self' * localhost:3000",
      'img-src': "'self' * data:",
      'style-src': "'self' 'unsafe-inline'"
    }
  };

  if(environment === 'development') {
  }

  if (environment === 'test') {
    ENV.APP.rootElement = '#ember-testing';
  }

  if (environment === 'production') {
  }

  return ENV;
};

bower与npm区别

bower是管理前端库、npm是管理nodo开发使用库,前者是扁平化后者是树形结构。

Copyright © 2016 kaka