15 Jan 2018
最近我已经完全从 Sublime
转到了 VS Code
,VS Code
的各种功能做的还是非常不错的. 在这里也向大家推荐。
其中我最喜欢的就是集成了 terminal,然后在做 Rails 相关的项目开发时,通过 Rspec 的插件可以快速的在集成的终端中运行测试和调试代码(pry debug
)。
这样在开发的过程中就不需要离开编辑器去调试代码,极大的缩短了BDD和 TDD 的循环时间。
由于我还是喜欢把 terminal 放到下面,然后也不能给 terminal 很大的空间,当测试失败的时候,会打印出很长的 backtrace,这时候经常就需要滚动鼠标才能查看失败的信息或者异常信息. 效果如下图所示:
这时想到了,Rspec 支持自定义的formatter,这样我就可以把输出的 backtrace 简化,保留我可能感兴趣的出错文件和测试信息.看上去的效果如下。
详细的custom_formatter.rb
代码请见: gist link
使用方法:
把 custom_formatter.rb
下载到本地,然后配置 Rspec 插件,设置如下:
"ruby.specCommand" : "spring rspec --require ~/custom_formatter.rb --format CustomFormatter"
Tips
在 VS Code 的 terminal 中可以,按住 Command 键然后点击带有行号的出错文件信息,以快速的打开文件
VS Code的 Markdown 插件也很棒,让我也不再需要单独的 markdown 编辑器
20 Sep 2017
MySQL Character Set基础知识
对于 MySQL 数据库你可以在不同的 Level 设置Character Set 和 Collation,包括:Server Level,Database Level,Table Level,Column Level 还有 Application Level.
Server Level:
可以通过命令行设置,也可以通过配置文件设置
默认: --character-set-server=latin1
latin1_swedish_ci
is the default collation for latin1
还可以通过重新编译时指定参数实现:use the DEFAULT_CHARSET and DEFAULT_COLLATION
作用范围:如果创建数据库时不指定,那么就使用 Server Level 的设置
查看当前的设定,可以查看系统变量:character_set_server and collation_server
Database Level:
可以在创建数据库时设置:
CREATE DATABASE db_name CHARACTER SET latin1 COLLATE latin1_swedish_ci ;
默认值:可以由 character_set_database
and collation_database
系统变量决定.
可以通过下面的命令查看当前的设置:
USE db_name ;
SELECT @@ character_set_database , @@ collation_database ;
或者
SELECT DEFAULT_CHARACTER_SET_NAME , DEFAULT_COLLATION_NAME
FROM INFORMATION_SCHEMA . SCHEMATA WHERE SCHEMA_NAME = 'db_name' ;
作用:如果建表时没有指定,那么会作为表的默认值,同时也是作为 LOAD DATA 的默认值
修改数据库level 的 character set 和 collation
ALTER DATABASE db_name CHARACTER SET utf8 COLLATE utf8_unicode_ci ;
或者单独修改
ALTER DATABASE my_database DEFAULT COLLATE utf8_unicode_ci;
ALTER DATABASE my_database DEFAULT CHARACTER SET utf8;
Table Level:
可以在建表的语句中进行设置
作用:如果字段没有具体制定,那么会作为字段的默认值
note:该功能是 mysql 的一个扩展,不是标准的SQL
使用下面语句可以同时修改 table 和 table 中字段的设置
ALTER TABLE tbl_name CONVERT TO CHARACTER SET charset_name [ COLLATE collation_name ];
查看某个数据库中的所有表的一些设置信息的语句
SHOW TABLE STATUS FROM db_name ;
Column Level:
N/A
Application Connection Level:
对于 Rails 应用,在 database.yml的数据库连接设置中加上 ?reconnect=true&encoding=utf8&collation=utf8_unicode_ci
查看数据库不同级别的元数据的设置的语句,比如:character set
SELECT DEFAULT_COLLATION_NAME FROM information_schema . SCHEMATA S WHERE schema_name = 'db_name' AND DEFAULT_COLLATION_NAME != 'utf8_unicode_ci' ;
SELECT TABLE_NAME , TABLE_COLLATION FROM information_schema . TABLES WHERE table_schema = 'db_name' AND table_collation != 'utf8_unicode_ci' ;
SELECT * FROM information_schema . COLUMNS WHERE table_schema = 'db_name' AND collation_name != 'utf8_unicode_ci' ;
ConvertDatabaseCharacterSetAndCollationToUtf8 Migration
class ConvertDatabaseCharacterSetAndCollationToUtf8 < ActiveRecord :: Migration
def up
execute <<~ SQL
ALTER DATABASE #{ ActiveRecord :: Base . connection . current_database } CHARACTER SET utf8 COLLATE utf8_unicode_ci;
SQL
end
def down
execute <<~ SQL
ALTER DATABASE #{ ActiveRecord :: Base . connection . current_database } CHARACTER SET latin1 COLLATE latin1_swedish_ci;
SQL
end
end
ConvertTablesCharacterSetAndCollationToUtf8 Migration
class ConvertTablesCharacterSetAndCollationToUtf8 < ActiveRecord :: Migration
def up
execute ( "SET foreign_key_checks = 0" )
latin_tables_sql = <<~ SQL
SELECT TABLE_NAME, TABLE_COLLATION
FROM information_schema.TABLES
WHERE table_schema = ' #{ ActiveRecord :: Base . connection . current_database } '
AND table_collation != 'utf8_unicode_ci';
SQL
results = ActiveRecord :: Base . connection . execute ( latin_tables_sql )
say "Total: #{ results . count } "
results . each do | result |
alter_table_sql = "ALTER TABLE #{ result [ 0 ] } CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci;"
execute alter_table_sql
end
execute ( "SET foreign_key_checks = 1" )
end
end
Rails Migration tips
在调试该功能的时候,学到的一些 tips:
rake db:migrate:status
查看当前migration 的状态,包括版本信息等
rake db:migrate VERSION=33333333
migrate指定 version
rake db:rollback STEP=n
通过 STEP 参数指定回滚的范围
User.connection
可以用来检查当前数据库设置和连接的信息
ActiveRecord::Base.connection.current_database
获取当前连接的数据库
ActiveRecord::Migrator.current_version
查看当前的版本
在 Rails Console 或者 Runner 中执行 SQL语句,可以使用 ActiveRecord::Migration.execute("SQL")
参考文章:
How to change all columns’ and tables’ collation to ‘utf8_bin’ in MySQL
07 Mar 2017
基本使用方法
案例说明: 给已经存在的 Company 增加一个 size 属性, 属性包括 large, medium, small 三个选项
从 Rails4.1 开始,可以通过 ActiveRecord::Enum
来快速实现这样的功能
class Company < ActiveRecord :: Base enum size: [ :large , :medium , :small ] end
定义了 enum
后,Rails会自动产生下面这些方法
Company . sizes # => {"large"=>0, "medium"=>1, "small"=>2} # Scope methods Company . large Company . medium Company . small # Query methods company . large? company . medium? # Action methods company . large! company . small!
Migration
enum
的实现是基于该字段是一个 integer 类型的。所以添加这个新的字段我们需要下面的 migration
class AddSizeToCompanies < ActiveRecord :: Migration def change add_column :companies , :size , :integer , null: false , default: 0 add_index :companies , :size end end
赋值操作
通过上面 Company.sizes 方法,我们看到 Rails 默认是从0开始对应的。所以上面的 migration 中默认值是0。当新建一个Company时,默认 company 的 size 是 large
company = Company . new company . size # => "large" # 多种赋值操作 company . size = :medium company . medium? # => true company . size = 2 company . small? # => true company . large = 'large' company . large? # => true
enum
会自动添加一些验证,如果给 size 属性赋错误的值,Rails会抛出异常
company . size = 5 # => ArgumentError: 5 is not a valid billing_category company . size = :bala # => ArgumentError: 'bala' is not a valid billing_category
当在前端的Form中填充到下拉列表中,可以这样做
f . input :size , collection: Company . sizes . keys . map { | s | [ s . titleize , s ]}, prompt: "Select a size"
需要注意的地方:
由于存到数据库的仍然是 number,所以如果有别的应用也使用同样的数据库,那么该应用需要知道对应关系。
Rails4.1 及之后的版本中,由于 enum
会自动产生一些方法,所以要特别注意选项的命名问题,尽量用明确的命名。 另外如果你还需要不同的属性,拥有相同的选项,那么你可以考虑这个 gem activerecord-enum-without-methods
同时在 Rails5 中,就可以使用_prefix
和_postfix
选项 来避免相应的问题。·
更好的Migration方法
上面的migration方法对于产品环境已经有数据的情况下,可能会产生问题。
对于Mysql 数据库,新加字段的时候对于已有的记录,mysql 会自动设置 NOT NULL
的已有记录为 default
但是对于 postgreSQL 就会出现下面的错误:
PG::NotNullViolation: ERROR: column “size” contains null values
这时可以先add_column
添加字段,不要加 NOT NULL 的限制,然后更新已有数据,然后再通过change_column_null
来添加 NOT NULL
限制。
17 Feb 2017
1. opacity: 0
相当于设置元素为透明
屏幕阅读器可读, 可以继续交互
2. visibility: hidden
.hide {
visibility: hidden;
}
屏幕阅读器不可读.
重新成visible后就可以重新进行交互了
后续的子节点可以设置为visible而变得可见
3. display: none
该元素不会被渲染, 所有后续的子节点也都是不会显示的
只可以通过dom api进行操作
屏幕阅读器不可读.
4. move out the viewport
.hide {
position: absolute;
top: -9999px;
left: -9999px;
}
该方法的目的是想保留交互的功能,同时不要影响布局.
屏幕阅读器可读.
5. clip-path
.hide {
clip-path: polygon(0px 0px,0px 0px,0px 0px,0px 0px);
}
通过裁剪的方法来隐藏.之前大家会用clip属性,现在clip属性已经废弃了,可以使用新的clip-path属性
想深入了解的可以看: 介绍clip-path属性
不过现在IE对clip-path还不支持
总结
用一张表来总结各种方法的区别:
方法
Occupy its position
User interaction
Screen Reader
Transition Animation
IE Support
opacity: 0
yes
yes
yes
yes
yes
visibility: hidden
yes
no
no
no
yes
display: none
no
no
no
no
yes
move out the viewport
no
yes
yes
yes
yes
clip-path
yes
no
yes
yes
no