I Try Do


  • 首页

  • 归档

  • 分类

  • 标签

  • 搜索
close
I Try Do

ssh

发表于 2017-04-28 | 分类于 shell | | 阅读次数

Generating a new SSH key

  1. 生成秘钥

    1
    $ ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
  2. 把公钥文件id_rsa.pub拷贝到需要登录的服务器上

  1. 登录远程服务器,在用户根目录下新建.ssh文件夹(如果不存在),在其中新建authorized_keys文件(如果不存在),把id_rsa.pub添加到authorized_keys文件中

  2. 退出当前远程登录,之后就可以不使用密码远程登录了

I Try Do

linux rails 部署 配置基础

发表于 2017-04-26 | 分类于 rails , linux | | 阅读次数

important参考文章

  • http://thelazylog.com/deploying-rails-application-with-nginx-puma-and-mina/
  • https://gorails.com/deploy/ubuntu/
  • http://xufei.logdown.com/posts/2014/03/05/rails-mina-puma-nginx

用户管理

查询当前用户信息

1
2
3
4
5
6
7
$ who am i  # 伪终端的用户名 伪终端序号(pts/0) 打开时间
$ who -a # 打印能打印的全部
$ who -d # 打印死掉的进程
$ who -m # 同am i,mom likes
$ who -q # 打印当前登录用户数及用户名
$ who -u # 打印当前登录用户登录信息
$ who -r 打印运行等级

创建用户

新建一个叫 mars 的用户:

1
sudo adduser mars # 默认生成的 用户组 和 用户名 相同

切换用户到mars

1
su -l mars

用户组

查看用户属于哪些用户组
1
groups mars
将其它用户加入 sudo 用户组
1
2
$ su -l mars # 切换登录用户
$ sudo ls

会提示 mars 不在 sudoers 文件中,意思就是 mars 不在 sudo 用户组中,至于 sudoers 文件(/etc/sudoers)你现在最好不要动它,操作不慎会导致比较麻烦的后果。

使用 usermod 命令可以为用户添加用户组

  • -a<追加>  把用户追加到某些组中,仅与-G选项一起使用。
  • -g<群组>  修改用户所属的群组。
  • -G<群组>  修改用户所属的附加群组。

usermod -g 这条命令编辑/etc/passwd文件,修改相应用户的组ID

usermod -G 这条命令编辑/etc/group文件,增加组成员。

eg: 把mars用户加入sudo组: usermod -aG sudo mars # 多个组之间用空格隔开

1
2
3
$ groups mars
$ sudo usermod -G sudo mars
$ groups mars

删除用户
1
sudo deluser mars --remove-home

Linux 文件权限

变更文件所有者

1
$ sudo chown [新用户名] [文件名]

修改文件权限

1
$ chmod 700 iphone6 # 现在,其他用户已经不能读这个“ iphone6 ”文件了

方式二:加减赋值操作

1
$ chmod go-rw iphone6

g、o 还有 u 分别表示 group、others 和 user,+ 和 - 分别表示增加和去掉相应的权限。

添加SSH 到服务器

1
2
3
4
cd ~
mkdir .ssh
cd .ssh
vim authorized_keys # 将本机id_rsa.pub中的key粘贴进去

服务器生成ssh key

1
$ ssh-keygen -t rsa -b 4096 -C "your_email@example.com"

安装nginx

rails ngnix配置 参考1

1
2
$ [sudo] apt-get update  
$ [sudo] apt-get install nginx

配置文件: (配置文件所在目录:/etc/ngnix/sites-enabled/)

1
2
$ cd /etc/nginx/conf.d
$ vim nodeChinaClub.conf

使配置生效:

1
sudo service nginx reload

1
2
3
sudo service nginx start
sudo service nginx stop
sudo service nginx restart

vim /etc/nginx/sites-available/wedesign.conf

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
28
29
upstream wedesign {
server unix:///mnt/www/wedesign/shared/tmp/sockets/puma.sock;
}

server {
listen 80;
server_name rails.itrydo.com; # change to match your URL
root /mnt/www/wedesign/shared/public/assets; # I assume your app is located at that location

location / {
proxy_pass http://wedesign; # match the name of upstream directive which is defined above
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}

location ~* ^/assets/ {
# Per RFC2616 - 1 year maximum expiry
expires 1y;
add_header Cache-Control public;

# Some browsers still send conditional-GET requests if there's a
# Last-Modified header or an ETag header even if they haven't
# reached the expiry date sent in the Expires header.
add_header Last-Modified "";
add_header ETag "";
break;
}
}

creating symlink in /etc/nginx/sites-enabled

1
sudo ln -sf /etc/nginx/sites-available/wedesign.conf /etc/nginx/sites-enabled/wedesign.conf

启动报错可以执行下面命令,会打印出错误信息(个人测试)

1
sudo nginx -t -c /etc/nginx/nginx.conf

mina

1
2
3
bundle exec puma -e production -b unix:///mnt/www/wedesign/shared/tmp/sockets/puma.sock
# 后台启动 -d
bundle exec puma -e production -d -b unix:///mnt/www/wedesign/shared/tmp/sockets/puma.sock

安装git

1
sudo apt-get install git

安装rbenv

1
sudo apt-get install rbenv ruby-build

手动安装:

参考1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
git clone https://github.com/rbenv/rbenv.git ~/.rbenv
cd ~/.rbenv && src/configure && make -C src
echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc
echo 'eval "$(rbenv init -)"' >> ~/.bashrc
~/.rbenv/bin/rbenv init
exec $SHELL
# 安装ruby-build
git clone https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build
# 通过 gem 命令安装完 gem 后无需手动输入 rbenv rehash 命令, 推荐
git clone git://github.com/sstephenson/rbenv-gem-rehash.git ~/.rbenv/plugins/rbenv-gem-rehash
# 通过 rbenv update 命令来更新 rbenv 以及所有插件, 推荐
git clone git://github.com/rkh/rbenv-update.git ~/.rbenv/plugins/rbenv-update
# 使用 Ruby China 的镜像安装 Ruby, 国内用户推荐
git clone git://github.com/AndorChen/rbenv-china-mirror.git ~/.rbenv/plugins/rbenv-china-mirror

安装ruby

1
2
3
4
5
sudo apt-get install -y libssl-dev libreadline-dev zlib1g-dev
rbenv install 2.4.1
rbenv versions
rbenv local 2.4.1
gem install bundler

安装mysql

检查系统中是否已经安装了MySQL

1
sudo netstat -tap | grep mysql

如果没有安装,则安装MySQL.

1
sudo apt-get install mysql-server mysql-client libmysqlclient-dev

测试安装是否成功:

1
sudo netstat -tap | grep mysql

也可通过登录MySQL测试

1
mysql -uroot -p

MySQL的一些简单管理:

1
2
3
4
5
6
7
8
9
# 启动MySQL服务:                       
sudo service mysql start
# 停止MySQL服务:
sudo service mysql stop
# 修改 MySQL 的管理员密码:
sudo mysqladmin -u root password newpassword
# 设置远程访问(正常情况下,mysql占用的3306端口只是在IP 127.0.0.1上监听,拒绝了其他IP的访问(通过netstat可以查看到)。取消本地监听需要修改 my.cnf 文件:):
sudo vi /etc/mysql/my.cnf
bind-address = 127.0.0.1 //找到此内容并且注释

MySQL安装后的目录结构分析(此结构只针对于使用apt-get install 在线安装情况):

1
2
3
4
5
6
7
8
# 数据库存放目录:               
/var/lib/mysql/
# 相关配置文件存放目录:
/usr/share/mysql
# 相关命令存放目录:
/usr/bin(mysqladmin mysqldump等命令)
# 启动脚步存放目录:
/etc/rc.d/init.d/

图形软件

1
2
Navicat
Sequel pro

安装node

1
sudo apt-get install nodejs

mina 和 cap部署的配置方式

参考1: cap_and_mina

参考2: Mina + Puma

参考3:

中文项目,英文项目单独部署

mina

首次部署可能无法自动创建数据库

1
2
3
cd /mnt/www/wedesign/current
# then run
rake db:create RAILS_ENV=production

成功部署相关配置

/mnt/www/wedesign/shared/config/

puma.rb

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#!/usr/bin/env puma

environment "production"

daemonize true
workers 2
threads 2,16

bind "unix:///mnt/www/wedesign/shared/tmp/sockets/puma.sock"

pidfile "/mnt/www/wedesign/shared/tmp/pids/puma.pid"
state_path "/mnt/www/wedesign/shared/tmp/sockets/puma.state"

stdout_redirect '/mnt/www/wedesign/shared/log/stdout', '/mnt/www/wedesign/shared/log/stderr'

directory "/mnt/www/wedesign/current"

activate_control_app 'unix:///mnt/www/wedesign/shared/tmp/sockets/pumactl.sock'

prune_bundler

database.yml

1
2
3
4
5
6
7
8
9
10
11
12
default: &default
adapter: mysql2
encoding: utf8
pool: 5
username: root
password:
host: localhost
production:
<<: *default
database: [project_database_name]
username: [database_username]
password: [database_password]

secrets.yml

1
2
3
4
production:
#secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>
# or run rake secret
secret_key_base: [secret_key]

/etc/nginx/sites-available/

wedesign.conf

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
28
29
upstream wedesign {
server unix:///mnt/www/wedesign/shared/tmp/sockets/puma.sock;
}

server {
listen 80;
server_name rails.itrydo.com; # change to match your URL
root /mnt/www/wedesign/shared/public; # I assume your app is located at that location

location / {
proxy_pass http://wedesign; # match the name of upstream directive which is defined above
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}

location ~* ^/assets/ {
# Per RFC2616 - 1 year maximum expiry
expires 1y;
add_header Cache-Control public;

# Some browsers still send conditional-GET requests if there's a
# Last-Modified header or an ETag header even if they haven't
# reached the expiry date sent in the Expires header.
add_header Last-Modified "";
add_header ETag "";
break;
}
}

then

1
$ sudo ln -sf /etc/nginx/sites-available/wedesign.conf /etc/nginx/sites-enabled/wedesign.conf

I Try Do

vue基础

发表于 2017-03-26 | 分类于 vue | | 阅读次数

demo

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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
var vm = new Vue({
el: 'body',
data: {
a: 1
},
// 计算属性
computed: {
b: function(){ //默认是get
return this.a + 1;
},
c: {
get: function(){
return this.a + 1;
}
set: function(val){
this.a = val;
}
}
},
// 过滤器@1.x currency capitalize uppercase downcase debounce(ms) limitBy(count, index=0) filterBy(str) orderBy(1/-1) ...
fileters: {

},

// @1.x transition
// 动画过度 可通过类定义,也可使用transitions
// <div class="animated" v-show="toggle" transition="bounce"></div>
// 这里的class animated是animate.css做动画必须类!
transitions: {
bounce: {
enterClass: 'zoomInLeft',
leaveClass: 'zoomOutRight'
}
},

// @2.x transition
// .fade-enter{} // 初始状态
// .fade-enter-active{} //变化成的状态->显示
// .fade-leave{}
// .fade-leave-active{} //变化成的状态->离开(消失)
<transition name="fade" @before-enter="beforeEnter()" @enter="enter()" @after-enter="afterEnter" @before-leave="beforeLeave" @leave="leave" @after-leave="afterLeave">
<p></p>
</transition>

//2.x 结合animate.css使用
<transition enter-active-class="zoomInLeft" leave-active-class="bounceOutRight">
<p class="animated" v-show="show"></p>
</transition

created: function(){}, // 创建之后
beforeCompile: function(){}, // 编译之前 @1.x
compiled: function(){}, // 变异之后 @1.x
ready: function(){}, //节点插入到文档 @1.x

beforeDestroy: function(){}, //销毁之前
destroyed: function(){} // 销毁之后
})
vm.$el // 元素
vm.$data // data本身
vm.$mount // 手动挂载Vue程序
vm.options // 获取自定义属性对象
vm.$destroy // 销毁对象
vm.$log() // 查看当前数据状态

// 全局自定义过滤器
Vue.filter('toDouble', function(val){
return val * 2;
});
// 双向过滤器 v-model
Vue.filter('modelVal', {
read: function(val){
return val
},
write: function(val){
return val;
}
})

// 全局自定义指令
// <span v-red>abc</span>
Vue.directive('red', function(){
//this.el 绑定该指令的元素(原生dom元素)
this.el.style.background = 'red';
});
// 自定义元素指令 elementDirective

// 自定义键盘
// @keydown.ctrl = "show()"
// @keydown.mycustomenter = "show()"
Vue.directive('on').keyCodes.ctrl = 17 // @1.x
Vue.directive('on').keyCodes.mycustomenter = 13 //@1.x
// Vue.config.keyCodes.ctrl=17 //@2.x

// 监听数据变化
vm.$watch('a', function(){});
// vm.$watch('obj', function(){}, {deep: true});检测对象

自定义组件

全局组件

方法1:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<body>
<div id="box">
<custom></custom>
</div>
<script>
// only: vue@1.x can use
var Custom = Vue.extend({
data: function(){
return {
title: '我是自定义标题'
}
},
template: '<h3>{{title}}</h3>'
})
Vue.component('custom', Custom);

var vm = new Vue({
el: '#box',
})
</script>
</body>

方法2:

1
2
3
Vue.component('custom', {
template: '<h3>我是自定义模板</h3>'
})

局部组件

方法1:

1
2
3
4
5
6
7
8
9
10
var Custom = Vue.extend({
template: '<h3>我是自定义模板</h3>'
})

var vm = new Vue({
el: '#box',
components: {
custom: Custom
}
})

方法2:

1
2
3
4
5
6
7
8
new Vue({
el: '#box',
components: {
custom: {
template: '<h3>我是自定义模板</h3>'
}
}
})

讲模板中的html提取到外部

1
2
3
4
5
6
7
8
9
10
11
12
13
<template id="custom">
<h3>我是自定义模板</h3>
</template>
<script>
new Vue({
el: '#box',
components: {
custom: {
template: '#custom'
}
}
})
</script>

动态组件


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<body>
<div id="box">
<component :is="custom"></component>
</div>
<script>
new Vue({
el: '#box',
data: {
custom: 'a'
},
components: {
a: {
template: '<h1>我是a</h1>'
},
b: {
template: '<h1>我是b</h1>'
}
}
})
</script>
</body>

调试工具

dev-tools

父->子组件数据传递

props

[‘msg’]

{
msg: String,
num: Number
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<body>
<div id="box">
// @1.x中 .sync子组件更改,同步到父组件
// @2.x中,不允许使用.sync了
<custom :root.sync="root" :my-msg="msg"></custom>
</div>
<script>
var vm = new Vue({
el: '#box',
data: {
root: 'root var'
msg: 'my msg'
},
components: {
custom: {
props: ['root', 'myMsg'],
template: '<h3>{{root}} - {{myMsg}}</h3>'
}
}
})
</script>
</body>

子->父组件数据传递

$emit: 发送

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
28
29
30
31
<body>
<div id="box">
<custom @child-msg="get"></custom>
</div>
<script>
var vm = new Vue({
el: '#box',
data: {},
methods: {
get: function(msg){
// msg: 'sub title'
}
},
components: {
custom: {
template: '<h3>{{title}}</h3>'
data: function(){
return {
title: 'sub title'
}
},
methods: {
send: function(){
this.$emit('child-msg', this.title)
}
}
}
}
})
</script>
</body>

slot 槽口

匿名slot

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<body>
<div id="box">
<custom>
<p>I'm use slot</p>
</custom>
</div>
<template id="custom">
<h3>我是自定义模板</h3>
<slot>为空的默认值</slot>
<p>footer</p>
</template>
<script>
new Vue({
el: '#box',
components: {
custom: {
template: '#custom'
}
}
})
</script>
</body>

命名slot

1
2
3
4
5
6
7
8
9
10
<custom>
<p slot="slot1">I'm use slot</p>
<p slot="slot2">I'm use slot</p>
</custom>
<template id="custom">
<h3>我是自定义模板</h3>
<slot name="slot1">为空的slot1默认值</slot>
<slot name="slot2">为空的slot2默认值</slot>
<p>footer</p>
</template>

vue-router

I Try Do

ruby基础

发表于 2017-03-23 | 分类于 ruby | | 阅读次数

闭包

use block

1
2
3
4
5
6
def foo
a = 3
yield a
end

foo {|b| puts b}

use & and call

1
2
3
4
5
6
def foo(&block)
a = 2
block.call(a)
end

foo {|a| puts a}

proc

proc可以看做是block的对象表示,类名为Proc

1
proc = Proc.new {|x| x*2}

lambda

lambda的class也是Proc

1
lambda = lambda {|x| x*2}

lambda和proc的区别是: 实例化方式的不同而已,proc更像对象,lambda更像方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
## diff1
p = Proc.new {|x, y| p x,y}
p.call(1) # 1, nil
p.call(1,2) # 1,2
p.cal(1,2,3) # 1,2

l = lambda {|x,y| p x,y}
l.call(1) # err
l.call(1,2) # 1,2
l.call(1,2,3) # err

## diff2
p = Proc.new {|x| return x}
p.call(1) # err

l = lambda {|x| return x}
p.call(1) # 1

Class

基础类示例

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
28
29
class Point
attr_accessor :x # getter setter
attr_reader :y # getter
@@origin = 0
ORIGIN = 2 # 常量 # 取值 Point::ORIGIN
def initialize(x = 0, y = 0)
# @x 实例变量
# @@x 类变量
# $x 全局变量
# x 局部变量
@x = x
@y = y
end

# 实例方法
def +(p2)
Point.new(x+p2.x, y+p2.y)
end

# 类方法
def self.foo
end

# 内部定义的都是类方法
class << self
def bar
end
end
end

继承

  • public

    • visibility: in/out
    • inheritance: Yes
    • call an obj: Yes
  • protected

    • visibility: within
    • inheritance: Yes
    • call an obj: Yes
  • private

    • visibility: within
    • inheritance: Yes
    • call an obj: No
1
2
3
4
5
6
7
class Point3D < Point
def initialize(x=0, y=0, z=0)
# @x, @y, @z = x, y , z
super(x, y)
@z = z
end
end

module

  • include 引入成实例方法
  • extend 引入成类方法
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    module Helper
    # instance method
    def test
    end
    # 类方法
    module ClassMethods
    def test2
    end
    end
    # hook klass为引入的类这里是 Point
    def self.included(klass)
    klass.extend ClassMethods
    end
    end
    # Point class
    class Point
    include Helper
    end

方法优先级:
singleton中的方法 - 实例方法 - module方法 - 父类实例方法

异常处理

产生: raise
处理: rescue

1
2
3
4
5
6
7
8
def foo
begin
# raise "boom in foo"
raise TypeError, "boom in foo", caller
rescue => e
puts e
end
end

枚举和比较模块

Comparable

1
2
3
4
5
6
7
8
9
10
class People
attr_reader :name
include Comparable
def initialize name
@name = name
end
def <=> other
self.name <=> other.name
end
end

Enumerable

1
2
3
4
5
6
7
8
9
10
11
12
13
class People
attr_reader :people
include Enumerable
def initialize people
@people = people
end
def each
raise "please provide a block" unless block_given?
people.each do |person|
yield person
end
end
end

正则表达式

生成正则的方法

  • /ruby/
  • %r{ruby}
  • Regexp.new

使用

1
2
3
"ruby" =~ /ruby/  # 0
"ruby".match(/ru/) # ru
"ruby".gsub!(/r/, i) # iuby

正则编写测试网站

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
28
29
30
[abc]	A single character of: a, b, or c
[^abc] Any single character except: a, b, or c
[a-z] Any single character in the range a-z
[a-zA-Z] Any single character in the range a-z or A-Z
^ Start of line
$ End of line
\A Start of string
\z End of string
. Any single character
\s Any whitespace character
\S Any non-whitespace character
\d Any digit
\D Any non-digit
\w Any word character (letter, number, underscore)
\W Any non-word character
\b Any word boundary
(...) Capture everything enclosed
(a|b) a or b
a? Zero or one of a
a* Zero or more of a
a+ One or more of a
a{3} Exactly 3 of a
a{3,} 3 or more of a
a{3,6} Between 3 and 6 of a

options:
i case insensitive
m make dot match newlines
x ignore whitespace in regex
o perform #{...} substitutions only once

时间、日期

  • DateTime < Date
  • Time # core library
    1
    2
    3
    4
    # 设置环境变量time zone
    ENV['TZ'] = 'Asia/Shanghai'
    # 或者
    Time.now.new_offset(Rational(8,24))

文件操作

file-doc 2.2.0

多线程

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
def foo
Thread.current['a'] = 1
10.times do
puts 'foo'
end
end

def bar
10.times do
puts 'bar'
end
end

t1 = Thread.new {foo()}
t2 = Thread.new {bar()}
t1.join
t2.join # 这里主线程等待t1,t2执行完成,才继续主线程执行,否则主线程停止,子线程将被释放

puts t1['a'] # 1

Thread.new 创建线程

t1.priority = -1

t1.priority = 1 # 设置优先

t1.join 开始执行t1线程,主线程等待t1完成

Thread.current # 当前线程对象

Thread.abort_on_exception = true # 一个线程异常,所有线程都退出

mutex

1
2
3
4
5
6
7
8
9
10
11
12
mutex = Mutex.new
count1 = count2 = 0
Thread.new do
loop do
mutex.synchronize do # 类似ios的线程锁!
count1 += 1
count2 += 1
end
end
end
sleep(1)
mutex.lock

元编程(metaprogramming)

eval

1
2
eval "1 + 1"
eval "def foo; puts 'foo'; end"

instance_eval

1
2
String.instance_eval "def foo; puts 'instance_eval foo'; end"
String.foo #输出 instance_eval foo

class_eval

1
2
3
String.class_eval "def foo; puts 'class_eval foo'; end"
str = 'abc'
str.foo #输出: class_eval foo

define_method

1
2
3
define_method(:foo) { puts 'abc' }
# 带一个参数的方法定义
define_method(:foo) {|arg| puts arg }
1
2
3
4
5
def method_missing method_name
self.class.send(:define_method, method_name){
puts method_name
}
end

编写gem

  1. 封装class module
  2. 讲文件放到lib test bin等目录中
  3. 编写gemspec文件
  4. gem build gemspec_file

    发布gem

  5. rubygems.org注册账号
  6. 设置账号与电脑绑定
  7. gem push gem_name
I Try Do

Active Record

发表于 2017-03-05 | 分类于 ruby on rails | | 阅读次数

数据类型

rails中在mysql,postgresql, sqlite中的类型对照表
参考

Rails mysql postgresql sqlite
:binary blob bytea blob
:boolean tinyint(1) boolean boolean
:date date date date
:datetime datetime timestamp datetime
:decimal decimal decimal decimal
:float float float float
:integer int(11) integer integer
:string varchar(255) * varchar(255)
:text text text text
:time time time datetime
:timestamp datetime timestamp datetime

初始化项目

创建项目

1
2
3
$ rails new wechat
$ rails new wechat [--skip-bundle] # skip bundle install
$ rails new wechat -d mysql # use mysql as database

创建model

1
rails g model User username:string phone:string:index age:integer

执行与回滚迁移文件

1
2
3
4
bundle exec rake db:migrate
bundle exec rake db:rollback
# 回滚两步
bundle exec rake db:rollback STEP=2

进入控制台

1
rails c

数据模型

创建users表

1
$ rails g model User phone:string:index email:string age:integer

修改数据表

假设数据库中的表名为USER,显式指定User模型关联USER数据表,负责默认表名为:users

1
2
3
class User < ActiveRecord::Base
self.table_name = "USER"
end

控制器

1
$ rails g controller users index new edit show

迁移文件

执行迁移文件

1
$ bundle exec rake db:migrate

回滚迁移文件

1
$ bundle exec rake db:rollback

数据验证

presence [必须存在]

1
2
3
4
5
6
7
validates :name, presence: true
# 只在创建时候验证
validates :name, presence: {on: :create}
# 只在更新时验证
validates :name, presence: {on: :update}
# '自定义错误内容'
validates :name, presence: {on: :create, message: '姓名不能为空'}

absence [必须为空]

1
validates :name, absence: true

length

  • maximum 最大长度 length: {maximum: 255}
  • minimum 最小长度 length: {minimum: 3}
  • in 范围 length: {in: 3..20}
  • is 长度必须为多少 length: {is: 5}

confirmation 确认性验证

1
validates :password, confirmation: true  #password_confirmation[shouldn't nil]

inclusion 包含性验证[province必须为北京或者上海]

1
validates :province, inclusion: {in: ['北京', '上海']}

exclusion 不包含性验证[不在某个集合之内]

format 正则匹配

1
2
3
4
class User < ActiveRecord::Base
EMAIL = /\A.+@.+\z/i # 常量 正则
validates :email, presence: true, length: {maximum: 255}, format: {with: EMAIL}
end

uniqueness 唯一

1
2
3
class User < ActiveRecord::Base
validates :phone, uniqueness: true
end

允许为空的唯一性验证 和 条件验证

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class User < ActiveRecord::Base
# 存在验证唯一,或者可以为空
validates :phone, uniqueness: {allow_nil: true} # method1
validates :phone, uniqueness: {allow_blank: true} # method2
# 条件验证1[fun] 仅仅方法返回true才进行验证
validates :phone, uniqueness: true, :if => :test?
def test?
false
end
# 条件验证2[string] 用户名为空进行验证
validates :phone, uniqueness: true, :if => "name.nil?"
# 条件验证3[proc]
validates :phone, uniqueness: true, :if => Proc.new {name.nil?}
# 条件验证 test? 成立 才会内部代码块的验证
with_options if: :test? do
validates :name, presence: true
validates :phone, presence: true
end
def test? do
(1+1 == 2)
end
end

自定义验证

  • validates_with

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    class MyValidator < ActiveModel::Validator
    def validate(record)
    if record.name.nil?
    record.errors[:name] << '用户名不能为空'
    end
    if record.phone.nil?
    record.errors[:name] << '手机号不能为空'
    end
    end
    end
    class User < ActiveRecord::Base
    validates_with MyValidator
    end
  • validates_each

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    class NamepresenceValidator < ActiveModel::EachValidator
    # 参数: 记录 属性 值
    def validate_each(record, attribute, value)
    if vale.nil?
    record.erros[attribute] << "用户名不能为空"
    end
    end
    end
    class User < ActiveRecord::Base
    validates :name, namepresence: true
    end

自定义验证方法

1
2
3
4
5
6
7
8
class User < ActiveRecord::Base
validate :my_validator
def my_validator
if name.nil?
errors[:name] << '姓名不能为空'
end
end
end

判断数据是否合法

  • valid? 判断是否合法
  • invalid? 判断是否不合法

验证错误信息

1
2
3
4
u = User.new
u.valid? # if false
u.errors.messages # return hash
u.errors[:name] # name属性不合法的信息描述

跳过数据验证方法

  • save(validate: false)
  • update_all
  • update_column
  • update_columns
  • update_attibute
  • update_counters
  • touch
  • toggle!
  • increment_counter
  • increment!
  • decrement_counter
  • decrement!

验证失败错误信息

1
2
3
4
5
6
7
8
9
10
11
12
# 创建
u = User.new
# 验证
u.valid?
# 查看验证错误信息
u.errors.messages
# 添加name属性的错误信息
u.errors[:name] < '用户名不能为空'
# 等价于
u.errors.add(:name, '用户名不能为空')
# 查看错误条数
u.errors.size

回调

可用的回调

创建对象回调

  • before_validation
  • after_validation
  • before_save
  • before_create
  • after_create
  • after_save

更新对象

  • before_validation
  • after_validation
  • before_save
  • before_update
  • after_update
  • after_save

销毁对象

  • before_destroy
  • after_dstroy

事务回调

  • after_commit #事务提交成功后执行
  • after_rollback #事务提交失败执行

可以触发回调的方法

  • create
  • create!
  • decrement!
  • destroy
  • destroy!
  • destroy_all
  • increment!
  • save
  • save!
  • save(validate: false)
  • toggle!
  • update_attribute
  • update
  • update!
  • valid?

跳过回调

  • decrement
  • decrement_count
  • delete
  • delete_all
  • increment
  • increment_counter
  • toggle
  • touch
  • update_column

终止回调

before_*

  • 返回false
  • 抛出异常

after_*

  • 抛出异常

条件回调 [和验证的条件回调类似]

eg:

1
2
3
4
5
6
7
8
9
10
11
12
class User < ActiveRecord::Base
# 仅仅当创建的时候执行AfterCommit
after_commit :AfterCommit, on: :create
# test? 为真, 才会执行BeforeSave
before_save :BeforeSave, if: :test?
def test?
true
end
def BeforeSave
puts 'before_save'
end
end

I Try Do

ruby环境搭建

发表于 2017-03-04 | | 阅读次数

安装配置

rvm ruby ..

ruby-china wike

RVM安装ruby

查看安装的ruby

1
rvm list

安装指定版本ruby

1
rvm install ruby 2.2.2

使用制定版本ruby

1
rvm use 2.2.2

gem源更换

查看所有gem源

1
$ gem sources -l

移除一个gem源

1
$ gem sources --remove https://rubygems.org/

添加一个gem源

1
$ gem source -a https://gems.ruby-china.org

安装rails

gem安装rails

1
$ gem install rails -v 4.2.3

rails创建项目

1
$ rails new [myPro] [--skip-bundle]

路由配置

eg:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 手动配置posts的show路由   as配置路由名称
# get 'posts/:id', :to => 'posts#show', :as => 'show_post'

# 排除show路由
# resources :posts, :except => :show

resources :posts do
# posts/recent
# get 'recent', :on => :collection
# 集合路由
collection do
# posts/recent
get 'recent'
end
# 成员路由
member do
# posts/:id/recent
get 'recent'
end
end

I Try Do

函数去抖动之debounce

发表于 2017-02-25 | 分类于 算法 | | 阅读次数

snippet-key @js function debounce

underscore v1.7.0相关的源码剖

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
28
29
30
31
32
33
34
35
36
// underscore v1.7.0相关的源码剖
_.debounce = function(func, wait, immediate) {
// immediate默认为false
var timeout, args, context, timestamp, result;

var later = function() {
// 当wait指定的时间间隔期间多次调用_.debounce返回的函数,则会不断更新timestamp的值,导致last < wait && last >= 0一直为true,从而不断启动新的计时器延时执行func
var last = _.now() - timestamp;

if (last < wait && last >= 0) {
timeout = setTimeout(later, wait - last);
} else {
timeout = null;
if (!immediate) {
result = func.apply(context, args);
if (!timeout) context = args = null;
}
}
};

return function() {
context = this;
args = arguments;
timestamp = _.now();
// 第一次调用该方法时,且immediate为true,则调用func函数
var callNow = immediate && !timeout;
// 在wait指定的时间间隔内首次调用该方法,则启动计时器定时调用func函数
if (!timeout) timeout = setTimeout(later, wait);
if (callNow) {
result = func.apply(context, args);
context = args = null;
}

return result;
};
};

个人实现

功能和underscore实现一样, 去除了underscore的依赖

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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
  /**
* 包裹函数 一段时间间隔只执行函数一次
* @param funcRef 函数引用
* @param wait default, 300ms
* 是否立即触发,触发后wait时间内不触发该方法,wait时间后才可以重新触发
* false:wait后触发 没有返回值
* true: wait前触发, 可以有返回值
* @param immediate default false
* return : 返回新的函数,使用:将需要调用funcRef的地方,替换为调用新返回的函数即可
*/
function debounce(funcRef, wait, immediate) {
var context, args, timestamp, timeout;
wait = wait || 300;
return function () {
context = this;
args = arguments;
timestamp = new Date().getTime();
var nowCall = immediate && !timeout;
if(!timeout){
timeout = setTimeout(later, wait)
}
if(nowCall){
var result = funcRef.apply(context, arguments);
context = args = null;
return result;
}
};
function later() {
// 当wait指定的时间间隔期间多次调用_.debounce返回的函数,则会不断更新timestamp的值,导致last < wait && last >= 0一直为true,从而不断启动新的计时器延时执行func
var last = new Date().getTime() - timestamp;
if (last < wait && last >= 0) {
timeout = setTimeout(later, wait - last);
}else {
timeout = null;
if (!immediate) {
funcRef.apply(context, args);
if (!timeout) context = args = null;
}
}
}
}

I Try Do

git常用命令

发表于 2017-02-22 | | 阅读次数

命令大全

png

删除git代码管理中已经提交的服务器的提交

1
2
3
#git reset --hard HEAD~1 # 取消当前版本之前的一次提交
git reset --hard HEAD~2 # 取消当前版本之前的两次提交
git push origin HEAD --force # 强制提交到远程版本库,从而删除之前的两次提交数据

在mac中自动保存git用户名与密码如此简单

在Mac OS X中这个操作竟然如此简单。只需在Terminal中输入如下的命令:

1
git config --global credential.helper osxkeychain

然后在git操作时只要输入一次用户名与密码,以后就不用输入了。

【参考资料】

Git keeps prompting me for password

I Try Do

angular中$filter过滤器的使用

发表于 2017-02-18 | 分类于 angular.js | | 阅读次数

系统提供过滤器

currency(货币处理)

1
{{num | currency : '¥'}}  //默认为 '$'

date(日期格式化)更详细配置参见这里

1
2
3
4
5
6
{{ today | date:'yyyy-MM-dd' }} //2015-01-01
# y M d h m s E 分别表示 年 月 日 时 分 秒 星期
# 年月日:({{ today | date:'yyyy-MM-dd' }}) 2015-10-19
# 时分秒:({{ today | date:'HH:mm:ss.sss' }}) 10:02:15.701
# 英文星期:({{ today | date:'EEEE' }})Monday
# 英文星期简写:({{ today | date:'EEE' }})Mon

filter(匹配字串)

1
2
3
4
5
6
7
8
9
10
11
12
$scope.childrenArray = [
{name:'kimi',age:3},
{name:'cindy',age:4},
{name:'anglar',age:4},
{name:'shitou',age:6},
{name:'tiantian',age:5}
];
$scope.func = function(e){return e.age>4;}
{{ childrenArray | filter : 'a' }} //匹配属性值中含有a的
{{ childrenArray | filter : 4 }} //匹配属性值中含有4的
{{ childrenArray | filter : {name : 'i'} }} //参数是对象,匹配name属性中含有i的
{{childrenArray | filter : func }} //参数是函数,指定返回age>4的

json(对象格式化成json字符串)

1
{{ jsonTest | json}} //没有参数。这东西有什么用呢,我一般也不会在页面上输出一个json串啊,官网说它可以用来进行调试,嗯,是个不错的选择。

limitTo(限制数组长度或者字符串长度)

1
2
#有点鸡肋,首先只能从数组或字符串的开头进行截取,其次,js原生的函数就可以代替它了
{{ childrenArray | limitTo : 2 }} //将会显示数组中的前两项

lowercase(小写)

uppercase(大写)

number(格式化数字)

1
2
3
4
5
6
7
8
//在html中用法
{{ number_expression | number : fractionSize}}
//在js中用法
$filter('number')(number, fractionSize)
//参数
//number 待精确的数字
//factionSize(可选) 小数点后精确位数,默认值是3.
#(默认情况下保留的小数位数小于等于3. 比如: 1234-->1234;1234.56789-->1234.568;1234.56-->1234.56 )

orderBy (排序)


自定义过滤器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//定义filters module
var filters = angular.module('filters', []);
filters.filter('stringAdd',function(){
return function (obj, addString) {
return obj + addString;
}
});
//html中使用
{{ '07' | stringAdd:':00' }} // 07:00
// js中使用
# 注入$filter
$filter('stringAdd')('07', ':00'); // 07:00

// 过滤器有对个参数用 :隔开
// {{ yourExpression | yourFilter: arg1:arg2:... }}
I Try Do

redis的安装和配置

发表于 2017-02-18 | 分类于 redis | | 阅读次数

【参考】


安装Redis

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 希望将redis安装到此目录 
/usr/local/redis
# 希望将安装包下载到此目录
/usr/local/src

那么安装过程指令如下:
$ mkdir /usr/local/redis
$ cd /usr/local/src
$ wget http://download.redis.io/releases/redis-3.0.7.tar.gz
$ tar xzf redis-3.0.7.tar.gz
$ cd redis-3.0.7
$ make PREFIX=/usr/local/redis install #安装到指定目录中

#如果make失败,一般是你们系统中还未安装gcc,那么可以通过yum安装:
$ yum install gcc

#在安装redis成功后,你将可以在/usr/local/redis看到一个bin的目录,里面包括了以下文件:
redis-benchmark redis-check-aof redis-check-dump redis-cli redis-server

将Redis做成服务

redis默认运行脚本
  • ps: /etc/init.d/目录下的脚本就类似与windows中的注册表,在系统启动的时候某些指定脚本将被执行
  • 按以上步骤安装Redi时,其服务脚本位于:/usr/local/src/redis-3.0.7/utils/redis_init_script
拷贝脚本到/etc/init.d/目录下,并命名为redis
1
$ [sudo] cp /usr/local/src/redis-3.0.7/utils/redis_init_script /etc/init.d/redis

对启动脚本进行修改

打开redis脚本文件,并进行编辑

1
2
3
4
5
6
7
8
9
$ vim /etc/init.d/redis

#修改到正确的路径
#EXEC=/usr/local/bin/redis-server
EXEC=/usr/local/redis/bin/redis-server
#CLIEXEC=/usr/local/bin/redis-cli
CLIEXEC=/usr/local/redis/bin/redis-cli
# 设置配置文件路径
#CONF="/etc/redis/${REDISPORT}.conf"


配置Redis启动信息

在上面shell脚本指定的配置目录中创建文件,并进行编辑。更详细配置参考这里

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
28
29
30
31
32
$ [sudo] mkdir /etc/redis/
$ [sudo] vim /etc/redis/6379.conf

写入配置:
#!/bin/sh
# 是否以后台进程运行,默认为no
daemonize yes
# 如以后台进程运行,则需指定一个pid,默认为/var/run/redis.pid
pidfile /var/run/redis.pid
# 监听端口,默认为6379
port 6379
#绑定主机IP,默认值为127.0.0.1(注释)
bind 127.0.0.1
# 超时时间,默认为300(秒)
timeout 300
# 日志记录等级,有4个可选值,debug,verbose(默认值),notice,warning
loglevel verbose
#可用数据库数,默认值为16,默认数据库为0
databases 16
#指出在多长时间内,有多少次更新操作,就将数据同步到数据文件。这个可以多个条件配合,比如默认配置文件中的设置,就设置了三个条件。
# 900秒(15分钟)内至少有1个key被改变
save 900 1
# 300秒(5分钟)内至少有10个key被改变
save 300 10
# 存储至本地数据库时是否压缩数据,默认为yes
rdbcompression yes
# 本地数据库文件名,默认值为dump.rdb
dbfilename dump.rdb
# 本地数据库存放路径,默认值为 ./
dir /usr/apps/redis_db
#开启之后,redis将在每100毫秒时使用1毫秒的CPU时间来对redis的hash表进行重新hash,可以降低内存的使用。当你的使 用场景中,有非常严格的实时性需要,不能够接受Redis时不时的对请求有2毫秒的延迟的话,把这项配置为no。如果没有这么严格的实时性要求,可以设置为yes,以便能够尽可能快的释放内存
activerehashing yes


启动redis服务

手动启动命令

1
$ service redis start

方便redis客户端的使用,可以将Redis的所在目录添加到系统参数PATH中

  • 修改profile文件:/etc/profile
  • 最文件最后一行添加export PATH="$PATH:/usr/local/redis/bin"
  • 应用配置执行
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    $ . /etc/profile  
    ```
    * 至此可以直径调用redis-cli的命令了
    ```bash
    $ redis-cli
    redis 127.0.0.1:6379> auth superman
    OK
    redis 127.0.0.1:6379> ping
    PONG
    redis 127.0.0.1:6379>
1234
wsen

wsen

不积跬步无以至千里

38 日志
19 分类
20 标签
© 2019 wsen
由 Hexo 强力驱动
主题 - NexT.Pisces