Faraday Gem notes

https://github.com/lostisland/faraday

DraggedImage

https://ruby-china.org/topics/26060

支持开箱即用的adapter

DraggedImage-1

第三方的adapter Typhoeus

基本使用

response = Faraday.get 'http://sushi.com/nigiri/sake.json'

你可以只使用默认的中间件堆栈和默认适配器
https://github.com/lostisland/faraday/blob/master/lib/faraday/rack_builder.rb

更复杂的用法是 new 一个 Connection 对象

conn = Faraday.new(:url => 'http://www.example.com')
response = conn.get '/users'                 # GET http://www.example.com/users'

Connections 可以使用options hash 作为参数或使用block进行配置

conn = Faraday.new(:url => 'http://sushi.com') do |faraday|
  faraday.request  :url_encoded             # form-encode POST params
  faraday.response :logger                  # log requests and responses to $stdout
  faraday.adapter  Faraday.default_adapter  # make requests with Net::HTTP
end

# Filter sensitive information from logs with a regex matcher

conn = Faraday.new(:url => 'http://sushi.com/api_key=s3cr3t') do |faraday|
  faraday.request  :url_encoded             # form-encode POST params
  faraday.response :logger do | logger |
    logger.filter(/(api_key=)(\w+)/,'\1[REMOVED]')
  end
  faraday.adapter  Faraday.default_adapter  # make requests with Net::HTTP
end

# Override the log formatting on demand
 
class MyFormatter < Faraday::Response::Logger::Formatter
  def request(env)
    info('Request', env)  
  end
  
  def request(env)
    info('Response', env)
  end
end

conn = Faraday.new(:url => 'http://sushi.com/api_key=s3cr3t') do |faraday|
  faraday.response :logger, StructLogger.new(STDOUT), formatter: MyFormatter
end

拿到conn后就可以发请求了

## GET ##

response = conn.get '/nigiri/sake.json'     # GET http://sushi.com/nigiri/sake.json
response.body

conn.get '/nigiri', { :name => 'Maguro' }   # GET http://sushi.com/nigiri?name=Maguro

conn.get do |req|                           # GET http://sushi.com/search?page=2&limit=100
  req.url '/search', :page => 2
  req.params['limit'] = 100
end

## POST ##

conn.post '/nigiri', { :name => 'Maguro' }  # POST "name=maguro" to http://sushi.com/nigiri

每个request都可以单独配置

# post payload as JSON instead of "www-form-urlencoded" encoding:
conn.post do |req|
  req.url '/nigiri'
  req.headers['Content-Type'] = 'application/json'
  req.body = '{ "name": "Unagi" }'
end

## Per-request options ##

conn.get do |req|
  req.url '/search'
  req.options.timeout = 5           # open/read timeout in seconds
  req.options.open_timeout = 2      # connection open timeout in seconds
end

## Streaming responses ##

streamed = []                       # A buffer to store the streamed data
conn.get('/nigiri/sake.json') do |req|
  # Set a callback which will receive tuples of chunk Strings
  # and the sum of characters received so far
  req.options.on_data = Proc.new do |chunk, overall_received_bytes|
    puts "Received #{overall_received_bytes} characters"
    streamed << chunk
  end
end
streamed.join

也可以注入一些随意的数据到context 这样所有middleware都可以访问了

# Anything you inject using context option will be available in the env on all middlewares

conn.get do |req|
  req.url '/search'
  req.options.context = {
      foo: 'foo',
      bar: 'bar'
  }
end

Advanced middleware usage

The order in which middleware is stacked is important. Like with Rack, the first middleware on the list wraps all others, while the last middleware is the innermost one, so that must be the adapter.

中间件堆叠的顺序很重要。与Rack一样,列表中的第一个中间件包装了所有其他中间件,而最后一个中间件是最里面的中间件,因此必须是适配器。

Faraday.new(...) do |conn|
  # POST/PUT params encoders:
  conn.request :multipart
  conn.request :url_encoded

  # Last middleware must be the adapter:
  conn.adapter :net_http
end

两个middleware

  • Request::Multipart 检查payload 是否有文件, 否则一切都不会受到影响;
  • Request::UrlEncoded application/x-www-form-urlencoded 编码类型

示例 payload 有文件, Content-Typemultipart/form-data

# uploading a file:
payload[:profile_pic] = Faraday::UploadIO.new('/path/to/avatar.jpg', 'image/jpeg')

# "Multipart" middleware detects files and encodes with "multipart/form-data":
conn.put '/profile', payload

Writing middleware

实现 call 实例方法的class

def call(request_env)
  # do something with the request
  # request_env[:request_headers].merge!(...)

  @app.call(request_env).on_complete do |response_env|
    # do something with the response
    # response_env[:response_headers].merge!(...)
  end
end

只在 on_complete block 处理 response 是很重要的, 请求是异步的

env 包含request和response的信息

# request phase
:method - :get, :post, ...
:url    - URI for the current request; also contains GET parameters
:body   - POST parameters for :post/:put requests
:request_headers

# response phase
:status - HTTP response status code, such as 200
:body   - the response body
:response_headers

links

2019/3/25 posted in  Ruby

PostgreSQL 5.7. Schemas 笔记

https://www.postgresql.org/docs/9.4/ddl-schemas.html

A database contains one or more named schemas, which in turn contain tables. Schemas also contain other kinds of named objects, including data types, functions, and operators. The same object name can be used in different schemas without conflict; for example, both schema1 and myschema can contain tables named mytable. Unlike databases, schemas are not rigidly separated: a user can access objects in any of the schemas in the database he is connected to, if he has privileges to do so.

  • 一个数据库包含多个schema, schema里包含tables, database 的下一层逻辑结构就是 schema
  • schema 也包括各种 objects, data types, functions, operators
  • 不同schem里的table名可以相同

在创建一个新的 database 时, PostgreSQL 会自动为其创建一个 名为 public 的 schema。 如果未设置 search_path 变量,那 么 PostgreSQL 会将你创建的所有对象默认放入 public schema 中。_

使用schema带来的好处

  • 允许多用户使用一个数据库而不会相互干扰, 数据隔离
  • 将数据库对象组织到逻辑组中以使其更易于管理
  • 第三方应用程序可以放在单独的模式中, 这样它们就不会与其他对象的名称冲突

5.7.1. Creating a Schema

code example:

CREATE SCHEMA myschema;

访问schema的表

schema.table

实际上,更通用的语法

database.schema.table

在schema里创建表

CREATE TABLE myschema.mytable (
 ...
);

删除空schema

DROP SCHEMA myschema;

删除schema 并且也删除其中的对象

DROP SCHEMA myschema CASCADE;

为某个用户创建schema

CREATE SCHEMA schemaname AUTHORIZATION username;

5.7.2. The Public Schema

默认创建的表都在public schema

下面两条语句是等价的

CREATE TABLE products ( ... );
CREATE TABLE public.products ( ... );

5.7.3. The Schema Search Path

当执行类 似 SELECT * FROM dogs 这种语句时, PostgreSQL 是怎么知道要查的是哪个 schema 中的表 呢?

可以加schema前缀解决, 也可以设置 search_path 变量解决

查看

SHOW search_path;
search_path
--------------
 "$user",public

PostgreSQL 有一个少为人知的系统变量叫作 user , 它代表了当前登录用户的名称。 执行 SELECT user 就能看到其名称。
对于search_path 里的$user, 如果当前登录的角色是 doggy, 那么所有的查询都会优先去 doggy schema 中寻找目标表, 如果找不到才会去 public schema 下找

设置新的schema倒search path里

SET search_path TO myschema,public;

这样 默认 创建访问 table 都在 myschema schema里

2019/3/4 posted in  阅读笔记

使用 sameersbn/docker-gitlab 部署gitlab

https://github.com/sameersbn/docker-gitlab#installation

使用compose

wget https://raw.githubusercontent.com/sameersbn/docker-gitlab/master/docker-compose.yml

aliyun smtp 服务配置

    - SMTP_ENABLED=true
    - SMTP_DOMAIN=smtpdm.aliyun.com
    - SMTP_HOST=smtpdm.aliyun.com
    - SMTP_PORT=80
    - SMTP_USER=master@xxx.com
    - SMTP_PASS=passworld
    - SMTP_STARTTLS=false
    - SMTP_AUTHENTICATION=login

备份

  • GITLAB_BACKUP_SCHEDULE = daily
  • GITLAB_BACKUP_ARCHIVE_PERMISSIONS = 0644
  • GITLAB_BACKUP_DIR = /home/git/data/backups
  • GITLAB_BACKUP_TIME=04:00
2018/10/13

树莓派 x86 系统安装记

2018/10/6

lede软路由安装

下载地址

http://firmware.koolshare.cn/LEDE_X64_fw867/

telegram-cloud-photo-size-5-6292077946080438431-x

combined和 uefi-gpt 两种,前者支持MBR的分区表和BIOS系统,后者支持GPT 分区表和EFI系统

mac或者linux直接用dd写入磁盘就行

下载解压

sudo dd if=./openwrt-koolshare-mod-v2.31-r10822-50aa0525d1-x86-64-combined-squashfs.img   of=/dev/disk2
2018/10/6

2-6 通过explain查询和分析SQL的执行计划

https://www.imooc.com/video/3710

explain 分析执行计划

说明

关于 type 为 index_merge

之前项目一个sql示例

mysql> mysql> explain SELECT COUNT(id) FROM `orders`  WHERE `orders`.`types` = 2 AND `orders`.`status` = 2 AND  `orders`.`pay_type` IN (1, 2);
+----+-------------+--------+------------+-------------+-----------------------------------------------------------------------+----------------------------------------------+---------+------+-------+----------+----------------------------------------------------------------------------+
| id | select_type | table  | partitions | type        | possible_keys                                                         | key                                          | key_len | ref  | rows  | filtered | Extra                                                                      |
+----+-------------+--------+------------+-------------+-----------------------------------------------------------------------+----------------------------------------------+---------+------+-------+----------+----------------------------------------------------------------------------+
|  1 | SIMPLE      | orders | NULL       | index_merge | index_orders_on_types,index_orders_on_status,index_orders_on_pay_type | index_orders_on_types,index_orders_on_status | 5,5     | NULL | 97112 |    14.71 | Using intersect(index_orders_on_types,index_orders_on_status); Using where |
+----+-------------+--------+------------+-------------+-----------------------------------------------------------------------+----------------------------------------------+---------+------+-------+----------+----------------------------------------------------------------------------+

type 为 index_merge

对多个索引分别进行条件扫描,然后将它们各自的结果进行合并(intersect/union)。

links

2018/9/26

HOW TO BUILD A HOME CLIMBING WALL

原文
https://www.rei.com/blog/climb/build-home-climbing-wall

抱石墙的构造方式与木框架房屋的构造方式大致相同:

2018/9/26

Android 关闭 ssl pinning 方案

2017/12/12

Ruby 使用 Fiddle 调用 C 函数

Ruby & Fiddle
2017/5/25

Google Play In-app Billing notes

google iap
2016/9/12