#Ruby

Ruby有着便捷强大的Gem包管理机制,作为五十年后人类使用最多的编程语言,有必要提前普及一下Ruby Gem的编写制作教程,帮助大家更好的使用Ruby,使用Gem,最好也能让Ruby的Gem库更加丰富,社区能够更加活跃。那么如何从零开始制作和发布自己的Gem呢?一起来动手操作一下。

制作和发布Ruby Gem包一共分如下几个步骤:

  1. 在RubyGems上注册帐号(如果你只想在本地或团队内部使用你的Gem,可以跳过这一步)
  2. 编写和打包Gem(gem build xxx.gemspec)
  3. 测试Gem(mang自mu信者可以跳过这一步)
  4. 发布Gem(gem push xxx)

1. 注册RubyGems帐号

RubyGems.ORG 是一个大型的Gems仓库,你可以现在就加入它,贡献你的Gem。这一步想必无需多说,注册完成之后,你就拥有了属于自己的RubyGems帐号,别人就可以看到你的主页和你发布的Gems。

注册完成之后,你还需要将你的crendentials保存到本地,方便后续直接在命令行使用gem命令。运行

1
curl -u 你的用户名 https://rubygems.org/api/v1/api_key.yaml > ~/.gem/credentials; chmod 0600 ~/.gem/credentials

2. 编写和打包Gem

编写Gem

我们这次要发布的Gem叫做template_chorder,你也可以改名成任意你想要的名字。首先我们创建一个工程目录,我的目录名叫做GemTemplate,其中包含如下内容:

其中,template.gemspec是项目的描述文件,gem build命令会基于这个文件进行打包。

template.gemspec内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13

Gem::Specification.new do |s|
s.name = 'template_chorder'
s.version = '0.0.0'
s.date = '2019-01-11'
s.summary = "Template!"
s.description = "A simple template gem"
s.authors = ["Chorder"]
s.email = 'chorder@chorder.net'
s.files = ["lib/template.rb"]
s.homepage = 'https://chorder.net/2019/01/11/rubygemtemplate/'
s.license = 'MIT'
end

其中s.name就是将来这个包发布出去的名字。默认的,我们需要将工程的主代码放在lib目录里面,这是ruby的约定。我们的Gem只包含一个很简单的功能,只需要放置全部代码在一个文件当中即可。

lib/template.rb的代码如下:

1
2
3
4
5
class Template
def self.test
puts "Hello, Ruby!"
end
end

就是这么简单。

打包Gem

在工程的根目录,运行

1
gem build template.gemspec

工程根目录将会产生一个 template_chorder-0.0.0.gem文件。
就是这么简单。

3. 测试Gem

对于刚刚生成的template_chorder-0.0.0.gem,运行

1
gem install template_chorder-0.0.0.gem

来安装它。

安装好以后,就可以在irb解释器中引入和运行它了。完整的过程如下:

疑问
这里其实是有点疑问的,就是为什么gem的名字叫做template_chorder,而在irb中引入的却是template。确实,如果gem包中的文件取名不严谨的话,可能会与其他包产生冲突。至于如何消除冲突,请君自己先思考下。

卸载Gem包,运行 gem uninstall template_chorder

2. 发布Gem

制作好这样一个不负责任的Gem包以后,就可以厚颜无耻地在RubyGems上发布它。但是为了社区的环境卫生清洁,尽量还是不要发布那些粗制滥造的包,就以此为戒吧。
发布Gem包,运行 gem push template_chorder-0.0.0.gem,如果第1步当中的帐号注册和保存
crendentials文件都没有问题,那么包就可以发布出去了。

本文的包发布在:https://rubygems.org/gems/template_chorder

希望能够对你有所帮助。

简介

Devise是Rails中一个功能强大、逻辑复杂的用于实现站点用户管理和登录的组件。鉴于Ruby之不重复造轮子的精神思想,Devise是值得去深入研究学习一下的。由于Devise本身的复杂性,这里对搭建的过程做一个记录,也借此分享一下基于Devise实现最基本的站点用户管理和登录的过程。

环境准备

需要在机器上安装Ruby和Rails。
本次编程环境:

  • Debian 9(Kernel 4.9.0-6-amd64)
  • ruby-2.4.1
  • Rails 5.2.0

开始

新建项目

首先新建一个Rails项目TestSite,创建Post scaffold,包含title和body两个字段

1
2
rails new TestSite
rails g scaffold Post title:string body:string

安装Devise

接着在Gemfile中添加devise

1
gem 'devise'

在项目中执行bundle,以及执行devise:install

1
2
bundle
rails generate devise:install

由于我们暂时只在本地测试,因此修改config/environments/development.rb文件,在其中加入mailer配置:

1
config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }

生成模型

指定Devise将要运行在哪个模型上,这里使用user作为模型,那么运行:

1
rails generate devise User

下一步,就是运行迁移:

1
rails db:migrate

控制器过滤

如果希望在应用运行之前校验用户身份,在ApplicationController中加入以下过滤器:

1
before_action :authenticate_user!

指定路由:

1
root to: 'posts#index'

添加注销功能

在Application的首页,加上用户注销的链接:

1
<%= link_to "Logout", destroy_user_session_path, method: "DELETE"  if current_user %>

配置视图

如果想要自定义登陆界面的视图,则运行以下命令:

1
rails g devise:views users

这里后面带模型名称,就会创建在这个模型范围内的视图(建议这样做,便于以后拓展多重用户身份模型)

此时就可以在相应的视图中自定义登录、注册、重置密码等相应的界面了。

配置控制器

生成控制器就和生成视图的流程是类似的,运行:

1
rails generate devise:controllers users

这样控制器就创建好了。

控制器这一段是值得好好说道说道的。
首先观察下控制器,控制器是可以追加功能的,也可以覆盖原来的方法,不过不推荐这样做,因为从目前经验来看devise自带的控制器已经足够健壮了。但是有时候,我们需要在原有的基础上新增一些功能,例如记录登录日志、增加一点自定义认证方式等等。这里简单介绍下如何在控制器中新增功能。
上一步操作,为我们生成了以下控制器:

1
2
3
4
5
6
app/controllers/users/confirmations_controller.rb
app/controllers/users/passwords_controller.rb
app/controllers/users/registrations_controller.rb
app/controllers/users/sessions_controller.rb
app/controllers/users/unlocks_controller.rb
app/controllers/users/omniauth_callbacks_controller.rb

这里以登录为例,如果我们想要改写登录功能,首先我们要在路由中改写我们要复写的控制器路由:

routes.rb中:

1
2
3
4
5
6
7
8
9
10
11
Rails.application.routes.draw do
#devise_for :users
resources :posts
root to: 'posts#index'

devise_for :users, controllers: {
# 这一行定义了有关sessions的控制选项,交由我们即将复写的sessions控制器处理。
sessions: 'users/sessions'
}

end

接着修改app/controllers/users/sessions_controller.rb,这里我们简单实现一个功能,当用户在前台登陆时,在后台的console中输出用户的登录信息。复写create方法:

1
2
3
4
5
6
7
# POST /resource/sign_in
def create
super
puts "="*64
puts resource.email
puts "="*64
end

尝试在前台登录,控制台输出了我们想要的信息:

待续

1.数组遍历方法总结

1
array = (1..10).to_a
1
2
3
4
5
length = array.length 
length.times do t
print "#{array[t]} "
end
puts "n"
1
2
3
4
5
length = array.length-1 
for i in 0..length do
print "#{array[i]} "
end
puts "n"
1
2
3
4
for i in array do 
print "#{i} "
end
puts "n"
1
2
array.each{x print x," "} 
puts "n"
1
2
3
4
5
6
7
length = array.length 
i = 0
while i< length do
print "#{array[i]} "
i = i+1
end
puts "n"
1
2
3
4
5
6
7
length = array.length 
i = 0
until i==length do
print "#{array[i]} "
i += 1
end
puts "n"
1
2
array.each_index do i 
print "#{array[i]} "

2.Ruby连接数据库

  • mysql

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    require 'mysql'  
    begin
    db = Mysql.init
    db.options(Mysql::SET_CHARSET_NAME, 'utf8')
    db = Mysql.real_connect("127.0.0.1", "root", "123456", "test", 3306)
    db.query("SET NAMES utf8")
    db.query("drop table if exists tb_test")
    db.query("create table tb_test (id int,
    text LONGTEXT) ENGINE=MyISAM DEFAULT CHARSET=utf8")
    db.query("insert into tb_test (id, text) values (
    1,'first line'),(2,'second line')")
    printf "%d rows were inserted\n",db.affected_rows
    rslt = db.query("select text from tb_test")
    while row = rslt.fetch_row do
    puts row[0]
    end
    rescue Mysql::Error => e
    puts "Error code: #{e.errno}"
    puts "Error message: #{e.error}"
    puts "Error SQLSTATE: #{e.sqlstate}" if e.respond_to?("sqlstate")
    ensure
    db.close if db
    end
  • redis

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

    require 'redis'

    def writeToFile(file,content)
    fp = File.new(file,"a+")
    if fp
    fp.syswrite(content)
    else
    puts "..."
    end
    end

    def connect(host)
    redis = Redis.new(:host => host,:port => 6379)
    redis.info.keys.each do |key|
    puts "#{key}:\t"+redis.info["#{key}"]
    end
    end

    connect("1.1.1.1")
  • sqlite3

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    require 'sqlite3'

    db = SQLite3::Database.new('test.db')

    db.execute("create table test(
    ID integet not null,
    Username varchar(20) null,
    Password varchar(64) null)")
    db.execute("insert into test(ID.Username,Password)
    values('0','admin','admin')")
    db.execute("select * from test")
    db.execute("update test set password='12345' where id=0")

3.Ruby socket

  • 服务端:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    require 'socket'

    server = TCPServer.open('0.0.0.0', 8080)
    loop do
    Thread.start(server.accept) do |client|
    begin
    while true
    puts "#{client.to_i} online"
    data = client.read()
    throw "empty" if data.empty?
    #puts data.length
    puts data
    end
    rescue Exception => e
    puts "#{client.to_i} offline"
    end
    end
    end
  • 客户端:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    require 'socket'

    hostname = '127.0.0.1'
    port = 8080
    buf = 'test'
    s = TCPSocket.open(hostname, port)
    s.write buf
    sleep(1)
    s.close

4.ruby gem 文档服务

rubygems.org上的gem文档访问起来太慢了,其实gem本身就自带doc的功能
安装gem的时候会默认安装相应gem的doc,如果不想占用空间安装doc,则gem install XXX –no-doc 即可。
使用下列命令可以启动gem自带的文档:

1
gem server --port 1234

然后访问

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

### 5.ruby改变控制台输出内容的颜色
```Ruby
puts "\033[1m前景色\033[0m\n"
puts " \033[30mBlack (30)\033[0m\n"
puts " \033[31mRed (31)\033[0m\n"
puts " \033[32mGreen (32)\033[0m\n"
puts " \033[33mYellow (33)\033[0m\n"
puts " \033[34mBlue (34)\033[0m\n"
puts " \033[35mMagenta (35)\033[0m\n"
puts " \033[36mCyan (36)\033[0m\n"
puts " \033[37mWhite (37)\033[0m\n"
puts ''
puts "\033[1m背景色\033[0m\n"
puts " \033[40m\033[37mBlack (40), White Text\033[0m\n"
puts " \033[41mRed (41)\033[0m\n"
puts " \033[42mGreen (42)\033[0m\n"
puts " \033[43mYellow (43)\033[0m\n"
puts " \033[44mBlue (44)\033[0m\n"
puts " \033[45mMagenta (45)\033[0m\n"
puts " \033[46mCyan (46)\033[0m\n"
puts " \033[47mWhite (47)\033[0m\n"
puts ''
puts "\033[1m其他\033[0m\n"
puts " Reset (0)"
puts " \033[1mBold (1)\033[0m\n"
puts " \033[4mUnderlined (4)\033[0m\n"

colors

6.一些比较特别的包

Ruby json gem
https://rubygems.global.ssl.fastly.net/gems/json-1.8.3.gem
树莓派wiringpi gpio包
http://pi.gadgetoid.com/article/wiringpi-as-a-ruby-gem

7.安装rvm的正确姿势

参考自:http://rvm.io/rvm/install
首先添加gpg公钥:

1
gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3

安装稳定版本的rvm

1
curl -sSL https://get.rvm.io | bash -s stable --ruby

8.解决kali2.0中RVM不能编译ruby-2.3.3

  • 错误详情:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    ruby-2.3.3 - #compiling.......................................................................-
    Error running '__rvm_make -j4',
    showing last 15 lines of /usr/local/rvm/log/1488041042_ruby-2.3.3/make.log
    exts.mk:210: recipe for target 'ext/openssl/all' failed
    make[1]: *** [ext/openssl/all] Error 2
    make[1]: *** Waiting for unfinished jobs....
    installing default nkf libraries
    compiling objspace_dump.c
    linking shared-object json/ext/generator.so
    make[2]: Leaving directory '/usr/local/rvm/src/ruby-2.3.3/ext/json/generator'
    linking shared-object objspace.so
    make[2]: Leaving directory '/usr/local/rvm/src/ruby-2.3.3/ext/objspace'
    linking shared-object nkf.so
    make[2]: Leaving directory '/usr/local/rvm/src/ruby-2.3.3/ext/nkf'
    make[1]: Leaving directory '/usr/local/rvm/src/ruby-2.3.3'
    uncommon.mk:203: recipe for target 'build-ext' failed
    make: *** [build-ext] Error 2
    ++ return 2
    There has been an error while running make. Halting the installation.

查看/usr/local/rvm/log/1488041042_ruby-2.3.3/make.log发现是openssl版本过老导致的。

  • 解决:
    第一步:先安装用于rvm的openssl:
    1
    rvm pkg install openssl

第二步:编译安装ruby,指定openssl目录(我的是/usr/local/rvm/usr/)

1
rvm install ruby-2.3.3 --with-openssl-dir=/usr/local/rvm/usr/

9.设置Gems默认源为ruby-china

现在没有淘宝源了,只有ruby-china源

1
gem sources --add https://gems.ruby-china.org/ --remove https://rubygems.org/

设置Bundler默认源为ruby-china:

1
bundle config mirror.https://rubygems.org https://gems.ruby-china.org

这样修改以后,即使Gemfile中指定了Source,也会用国内的源。

Windows中搭建Ruby On Rails环境

步骤如下

  1. 安装ruby (我选择的版本是ruby 2.2.3p173)
  2. 安装rails gem
    在这之前建议先把gem的源换成淘宝的源,速度快点。
    1
    2
    3
    4
    5
    6
    7
    8
    gem sources --add https://ruby.taobao.org/ --remove https://rubygems.org/
    gem sources -l
    *** CURRENT SOURCES ***

    https://ruby.taobao.org
    # 请确保只有 ruby.taobao.org

    gem install rails

之后:

1
2
gem install rails
gem install bundler
  1. 安装devkit
    下载地址 http://rubyinstaller.org/downloads

如果是win10,选择 DevKit-mingw64-64-4.7.2-20130224-1432-sfx.exe 这个版本。

然后运行,并选择解压到c:\devkit

进入c:\devkit目录
运行

ruby dk.rb init

之后修改config.yml

添加下面三行

1
2
3
---
- C:/Ruby22-x64
- C:/Ruby22-x64

注意把路径换成当前ruby的安装路径,-前后各有一个空格不可忽略。
然后运行

ruby dk.rb install

最后进入需要建立工程的目录,使用如下命令新建rails项目

rails new testapp

如果在此过程中报错,则进入testapp中
使用

bundler install

来安装所需要的依赖包。

如果还报错,修改testapp目录中的Gemfile

将第一行的sources源内容改为

source 'https://ruby.taobao.org/'

然后再执行bundler install命令

Debian中搭建Ruby On Rails开发环境

假设你已经安装好ruby了

接下来安装rvm

$ curl -L https://get.rvm.io | bash -s stable

某些情况下,可能需要编译一下rvm的初始化脚本

我的位置是在/etc/profile.d/rvm.sh,所以运行这一句:

$source /etc/profile.d/rvm.sh

接着安装bundler

gem install bundler

然后安装rails

gem install rails

如果这地方出现错误,尝试使用rvm切换ruby的版本:

rvm install 2.0.0
rvm 2.0.0 --default

CentOS中搭建ruby on rails开发环境

1
2
3
4
5
6
curl -L https://get.rvm.io | bash -s stable
source /usr/local/rvm/bin/rvm
rvm install 2.0.0
rvm 2.0.0 --default
gem install bundler
gem install rails
Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×