BigBing 技术博客

Rails5.2用Wepacker安装和使用Materialize CSS

快速应用Starter Template的效果

Materialize CSS是一个比较新的基于Google Material Design的前端框架,界面非常简洁,而且很容易使用。

其中,在最新发布的1.0版本中,去掉了对于JQuery的依赖,这是一个很大进步。因为在Rails5以后也是移除了JQuery,而且接下来在我的项目中,我会开始使用React.js作为前端的开发框架。

下面就来介绍一下通过Webpacker安装和使用Materialize的步骤:

准备工作: 在app/javascript/下面创建stylesheets目录以及application.scss文件:

$ mkdir app/javascript/stylesheets
$ touch app/javascript/stylesheets/application.scss

然后我们需要import刚才创建的scss文件,让Webpacker帮我们编译scss文件

// app/javascript/packs/application.js

import '../stylesheets/application'

在页面中引入Webpacker帮我们编译的application.jsapplication.css文件

# app/views/layouts/application.html.erb

<%= stylesheet_pack_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>

使用yarn安装materialize-css

yarn add materialize-css

我们可以在node_modules/materialize-css下面找到安装好的文件 下面我们要把materialize.js加入到application.js

// app/javascript/packs/application.js

import 'materialize-css/dist/js/materialize'

然后到application.scss中引入materialize.css

// app/javascript/stylesheets/application.scss

@import materialize-css/dist/css/materialize;

最后我们还需要在application.html.erb中加入Materialize依赖的字体和图标

// app/views/layouts/application.html.erb

<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">

安装配置到这里就完成了,接下来就是找一些Materialize的实例,应用到网站上吧。 更多的细节可以参考我完成的commit: Github commit

2019 Rubyconf AU 精彩内容回顾

大会总结

两天的2019年澳洲的 Ruby 技术大会顺利结束了,这次大会组织的还是很不错的,现场的秩序和投影和音效都不错,不足的地方就是由于场地选在比较老的Forum Melbourne,里面的座椅不是特别舒服。

本次大会的内容还是很丰富的,很多演讲者都是来自英国,美国。除了 Ruby 相关的技术主题,还有不少人文关怀的内容,比如 ADD(注意障碍),情绪管理和全球变暖的话题。

下面我来推荐几个我觉得非常不错的分享:

The Case Of The Missing Method - A Ruby Mystery Story

Nadia Odunayo 通过一个非常好的故事解释了 Ruby 中的 singleton class 的秘密,以及讲解了 singleton class 在 DSL 的实际应用,Nadia 的演讲节奏控制的非常好,声音非常清楚。

点击观看

How to hijack, proxy and smuggle sockets with Rack/Ruby

Dávid Halász 通过一个非常具体和实际的例子,演示了 Ruby 中的 Socket 编程相关的技术。

点击观看

Taming Monoliths Without Microservices

Kelly Sutton 在演讲中再次强调了如果要对 Monolithic Rails 应用进行拆分的话,重要的还是要把 Domain 划分清楚,以及如何恰当得处理 Domain 的界限和依赖,着重强调了不要有相互的依赖,依赖最好就是单向的。

点击观看

Representations Count

Tom Stuart, 来自英国,Understanding Computation书的作者。他有着一口典型的英式口音。一听到这样的口音就让我想到了 IT Crowd. Tom 演示了通过不同的抽象表达,会对写代码解决问题产生巨大的影响。他用直观的图形解释了如何优雅的实现一个带负号的四则运算的实现。

点击观看

A Branch in Time (a story about revision histories)

Tekin Süleyman 也是通过一个生动的故事讲解了写好 git commit 信息的重要性,视频中还会学到几个新的 git 命令可以帮助你快速查找历史,以及展示了一些写好 git commit 的最佳实践。

点击观看

Views, from the top

Tim Riley 系统的介绍了 dry-rb view的主要功能和使用方法。演示了如何通过 dry-rb 来写一个更加 OO 的 view 层的代码。

点击观看

Learn to make the point: data visualisation strategy

Mila Dymnikova 解释了数据可视化的重要作用,即使对于开发人员,在进行工作总结和汇报的时候也是非常重要的。她给出很具体的实现方法和一些好用的工具和服务。她的 PPT 做的非常生动。

点击观看

Building APIs you want to hug with GraphQL

Tom Ridge 介绍了如何设计和实现一个好的 GraphQL APIs.

点击观看

What the hell is a JRuby?

Tom Gamon 非常简洁清楚得总结了几种不同的 Ruby 的实现,重点介绍了 JRuby 的实现以及在什么情况下我们可能会考虑在产品环境使用 JRuby。视频里面提到的两本书《Working with ruby threads》《Ruby Under a Microscope》确实都是非常不错的。

点击观看

It’s Down! Simulating Incidents in Production

Kelsey Pedersen通过一个具体的实例,讲解了如何通过 Feature Flag 模拟产品环境的故障,然后如何分析故障以及完善相关的工具和流程。非常具有实战意义。

点击观看

Mechanically Confident

Adam Cuppy 演员出身的他有丰富的舞台经验,声音非常洪亮,非常能够调动现场的气氛,他总结了如何通过一些实践来建立好的 routine,从而不断取得进步然后建立自信。

点击观看

What were they thinking?”

Keith Pitty 凭借非常多年的经验,总结了软件开发方面的一些思考。

点击观看

更多视频请到Ruby Australia 的 Youtube 官网查看

Add a new database migration tips in Rails

When you are using MySQL, if a migration fails the DDL will not be rolled back with the transaction, potentially leaving the database in an invalid state, which could theoretically bring the whole application down.

Referencing model classes in a migration

Generally you would not need to reference model classes in a migration unless you were modifying existing data in some way, or adding new data. Sometimes we need to do this, but referencing application model classes raises some problems.

  • If a model class is referenced in one migration, then the model’s table is altered in a subsequent migration, the annotation written to the model’s file will not reflect the subsequent alteration.
  • Old migrations referencing the model might fail if the model code has evolved significantly since the time the migration was written.

To avoid these problems, you should:

  1. Avoid using Active Record models in your migrations by using SQL
  2. If you must use Active Record models, create a migration-specific class for the purpose.

Let’s look at an example where we want to strip leading and trailing whitespace from a column. A naive implementation might look something like this:

class MyMigration < ActiveRecord::Migration
  def change
    User.where.not(name: nil).each do |user|
      user.update name: user.name.strip
    end
  end
end

Using SQL

Of course, doing this in SQL is quite simple and far more efficient than using Active Record to load and modify each record individually:

class MyMigration < ActiveRecord::Migration
  def change
    execute <<-SQL.squish
      UPDATE users
         SET name = LTRIM(RTRIM(name))
       WHERE name IS NOT NULL
    SQL
  end
end

Note: that squish-ing your SQL is recommended because it makes the migration output a lot easier to read.

Using a migration-specific model class

Some data migrations can’t be easilly expressed in SQL, so let’s say we want to stick with using Active Record. In such cases, we can create a migration specific class for the purpose:

class MyMigration < ActiveRecord::Migration
  class User < ActiveRecord::Base
  end

  def change
    User.where.not(name: nil).each do |user|
      user.update name: user.name.strip
    end
  end
end

Here the migration will use the MyMigration::User class instead of ::User

为 VS Code定制 Rspec 的 formatter

最近我已经完全从 Sublime 转到了 VS CodeVS Code 的各种功能做的还是非常不错的. 在这里也向大家推荐。

其中我最喜欢的就是集成了 terminal,然后在做 Rails 相关的项目开发时,通过 Rspec 的插件可以快速的在集成的终端中运行测试和调试代码(pry debug)。

这样在开发的过程中就不需要离开编辑器去调试代码,极大的缩短了BDD和 TDD 的循环时间。

由于我还是喜欢把 terminal 放到下面,然后也不能给 terminal 很大的空间,当测试失败的时候,会打印出很长的 backtrace,这时候经常就需要滚动鼠标才能查看失败的信息或者异常信息. 效果如下图所示: Rspec default formatter

这时想到了,Rspec 支持自定义的formatter,这样我就可以把输出的 backtrace 简化,保留我可能感兴趣的出错文件和测试信息.看上去的效果如下。 Rspec custom formatter

详细的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 编辑器

使用 Rails Migration转换 MySQL数据库和表的字符集总结

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