<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>ff4415</title>
    <link>https://ruby-china.org/ff4415</link>
    <description/>
    <language>en-us</language>
    <item>
      <title>在 Ubuntu 14.04 上使用 Puma 和 Nginx 部署 Rails App</title>
      <description>&lt;blockquote&gt;
&lt;p&gt;原文链接：
&lt;a href="https://www.digitalocean.com/community/tutorials/how-to-deploy-a-rails-app-with-puma-and-nginx-on-ubuntu-14-04" rel="nofollow" target="_blank" title=""&gt;how-to-deploy-a-rails-app-with-puma-and-nginx-on-ubuntu-14-04&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id="简介"&gt;简介&lt;/h3&gt;
&lt;p&gt;在部署自己的 Rails on Ruby 应用时，有很多有效的安装包可以考虑。这篇教程旨在帮助你用 PostgreSQL 作为数据库，在 Ubuntu14.04 下面使用 Pumma 和 Ngnix 部署 Ruby on Rails 的生产环境。&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Puma&lt;/code&gt;是一个&lt;code&gt;应用服务器&lt;/code&gt;(application server),与&lt;code&gt;Passenger&lt;/code&gt;或者&lt;code&gt;Unicon&lt;/code&gt;一样，允许你的&lt;code&gt;RAILS应用&lt;/code&gt;处理&lt;code&gt;并发请求&lt;/code&gt;。由于&lt;code&gt;Puma&lt;/code&gt;不是为用户直接访问而设计，我们需要使用&lt;code&gt;Nginx&lt;/code&gt;作为&lt;code&gt;反向代理&lt;/code&gt;,用于在用户和你的应用之间缓存&lt;code&gt;请求&lt;/code&gt;和&lt;code&gt;响应&lt;/code&gt;。&lt;/p&gt;
&lt;h3 id="要求"&gt;要求&lt;/h3&gt;
&lt;p&gt;本教程假设你拥有一台 Ubuntu 14.04 服务器，并在需要部署应用的用户下面安装了以下软件：&lt;/p&gt;

&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;[在 Ubuntu 14.04 上使用 rbenv 安装 Ruby on Rails] [1]&lt;/li&gt;
&lt;li&gt;[在 Ubuntu 14.04 下使用 PostgreSQL 部署 Ruby on Rails] [2]&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;如果你还没有以上配置，遵循以上链接的教程。我们假设你的&lt;code&gt;用户账号&lt;/code&gt;为 &lt;strong&gt;deploy&lt;/strong&gt;。&lt;/p&gt;

&lt;p&gt;以及，这篇教程没有包含  &lt;em&gt;如何配置开发和测试环境&lt;/em&gt;。如果你有这方面的需求，遵循 &lt;em&gt;[PostgreSQL with Rails tutorial][2]&lt;/em&gt; 中的例子。&lt;/p&gt;
&lt;h3 id="创建 Rails 应用"&gt;创建 Rails 应用&lt;/h3&gt;
&lt;p&gt;理想情况下，你已经有一个想要部署的 Rails 应用。如果是这样，你可以跳过这一节，在接下来使用合适的代替品。如果不是，第一步就是使用 PostgreSQL 作为数据库创建一个新的 Rails 应用。&lt;/p&gt;

&lt;p&gt;这个命令将会创建一个新的 Rails 应用，名为&lt;code&gt;appname&lt;/code&gt;.并使用 PostgreSQL 作为数据库。高亮的"appname"可以随便修改：&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;rails new &lt;code&gt;appname&lt;/code&gt; -d postgresql&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;然后跳转到用户目录：&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;cd &lt;code&gt;appname&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;让我们花点时间创建一个&lt;code&gt;PostgreSQL用户&lt;/code&gt;给你的 Rails 应用的生产环境。&lt;/p&gt;
&lt;h3 id="创建生产数据库用户"&gt;创建生产数据库用户&lt;/h3&gt;
&lt;p&gt;为了让事情简单，我们把生产数据库用户名和你的应用名字保持一致。比如，如果你的应用叫做"appname",你就像这样创建 PostgreSQL 用户：&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;sudo -u postgres createruser -s &lt;code&gt;appname&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;我们想要为此数据库用户设置密码，像这样进入 PostgresSQL 控制台：&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;sudo -u postgres psql&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;为数据库用户"appname"设置密码：&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;password appname&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;输入你想要的密码然后确认。&lt;/p&gt;

&lt;p&gt;退出 PostSQL 控制台：&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;\q&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;现在我们准备好用这些数据库连接信息配置你的应用了。&lt;/p&gt;
&lt;h3 id="配置数据库连接"&gt;配置数据库连接&lt;/h3&gt;
&lt;p&gt;确定你是在你的应用的&lt;code&gt;根目录&lt;/code&gt;(cd ~/appname)。&lt;/p&gt;

&lt;p&gt;用你喜好的文本编辑器打开你的应用的数据库配置文件。我们用&lt;code&gt;vi&lt;/code&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;vi config/database.yml&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;更新&lt;code&gt;production&lt;/code&gt; 段落，让它看起来像这样：&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;production:
  &amp;lt;&amp;lt;: *default
  host: localhost
  adapter: postgresql
  encoding: utf8
  database: appname_production
  pool: 5
  username: &amp;lt;%= ENV['APPNAME_DATABASE_USER'] %&amp;gt;
  password: &amp;lt;%= ENV['APPNAME_DATABASE_PASSWORD'] %&amp;gt;

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;注意数据库用户名和密码配置成通过环境变量读取，'&lt;code&gt;APPNAME&lt;/code&gt;_DATABASE_USER' 和'&lt;code&gt;APPNAME&lt;/code&gt;_DATABASE_PASSWORD'。这被认为是保证你的&lt;code&gt;生产密码&lt;/code&gt;和&lt;code&gt;密文&lt;/code&gt;(secrets) 在应用代码之外的最佳实践，否则在使用类似 GIT 这样的版本控制系统时容易把它们暴露出去。接下来我们就会介绍 &lt;em&gt;如何配置数据库权限和环境变量&lt;/em&gt;。&lt;/p&gt;

&lt;p&gt;Save and exit.&lt;/p&gt;
&lt;h3 id="安装rbenv-vars插件"&gt;安装 rbenv-vars 插件&lt;/h3&gt;
&lt;p&gt;在部署 Rails&lt;code&gt;生产应用&lt;/code&gt;(production Rails application) 之前，你需要使用&lt;code&gt;环境变量&lt;/code&gt;设置&lt;code&gt;生产安全密文&lt;/code&gt;(production secret key) 和&lt;code&gt;数据库密码&lt;/code&gt;。作为一种管理&lt;code&gt;环境变量&lt;/code&gt;的简单方式，可以使用 &lt;strong&gt;rbenv-vars&lt;/strong&gt; 插件 来实时加载&lt;code&gt;密码&lt;/code&gt;和&lt;code&gt;密文&lt;/code&gt;到我们的应用里面。&lt;/p&gt;

&lt;p&gt;要安装 rbenv-rars 插件，只用跳转到&lt;code&gt;.rbenv/plugins&lt;/code&gt;目录然后 clone it from GitHub. 比如，如果 rbenv 安装在你的&lt;code&gt;home&lt;/code&gt;目录，运行这些命令：&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd ~/.rbenv/plugins
git clone https://github.com/sstephenson/rbenv-vars.git
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="设置环境变量"&gt;设置环境变量&lt;/h3&gt;
&lt;p&gt;现在 rbenv-vars 插件已经安装了。让我们来配置需要的环境变量。&lt;/p&gt;

&lt;p&gt;首先，生成密文 (secret key),用于校验单个 cookie 的完整性：&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd ~/appname
rake secret
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;copy 生成的密文 (secret key),然后打开.rbenv-vars 文件：&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;vi .rbenv-vars&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;在这里设置的任何环境变量都会被你的 Rails 应用读取。&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;备注：这里实际是在你的程序根目录里新建一个.rbenv-vars 文件，然后写如环境变量&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;首先，设置 SECRET_KEY_BASE 变量 (替换高亮部分为你自己刚刚生成并拷贝的密文)：&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;SECRET_KEY_BASE=&lt;code&gt;your_generated_secret&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;然后，设置 APPNAME_DATABASE_USER 变量 (替换高亮的'APPNAME'为你自己的应用名称，'appname'是你生产数据库的用户名)：&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;APPNAME&lt;/code&gt;_DATABASE_USER=&lt;code&gt;appname&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;最后，设置 APPNAME_DATABASE_PASSWORD 变量 (替换高亮的'APPNAME'为你自己的应用名称，'prod_db_pass'是你生产数据库的用户密码)：&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;APPNAME&lt;/code&gt;_DATABASE_PASSWORD=&lt;code&gt;prod_db_pass&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Save and exit.&lt;/p&gt;

&lt;p&gt;你可以查看那些环境变量被 rbenv-vars 插件设置于你的应用：&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;rbenv vars&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;如果你改变你的密文或数据库密码，更新.rbenv-vars 文件。注意保持这个文件的私有性，不要把它包含在你的公开代码库里。&lt;/p&gt;
&lt;h3 id="创建生产数据库"&gt;创建生产数据库&lt;/h3&gt;
&lt;p&gt;现在你的应用已经配置好可以与你的 PostgreSQL 对话了。让我们来创建数据库：&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;RAILS_ENV=production rake db:create&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4 id="Generate a Controller"&gt;Generate a Controller&lt;/h4&gt;
&lt;p&gt;如果你依照的是这个例子，我们将生成一个 scaffold controller 这样我们的应用就有点东西可以看了：&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;rails generate scaffold Task title:string note:text&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;现在运行命令来更新这个生产数据库：&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;RAILS_ENV=production rake db:migrate&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;你还需要预编译&lt;code&gt;assets&lt;/code&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;RAILS_ENV=production rake assets:precompile&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;要测试你的应用是否工作，可以运行这个生产环境，并绑定你的服务器的公共 IP (替换为你自己的服务器的公共 IP 地址)：&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;RAILS_ENV=production rails server --binding=&lt;code&gt;server_public_IP&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;现在到浏览器访问这个 URL：&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="http://server_public_IP:3000/tasks" rel="nofollow" target="_blank"&gt;http://server_public_IP:3000/tasks&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;如果工作正常，你将看到这个页面：&lt;/p&gt;

&lt;p&gt;&lt;img src="https://assets.digitalocean.com/articles/rails_unicorn/tasks.png" title="" alt="page"&gt;&lt;/p&gt;

&lt;p&gt;回到你的 Rails server, Ctrl-c 停止应用。&lt;/p&gt;
&lt;h3 id="安装Puma"&gt;安装 Puma&lt;/h3&gt;
&lt;p&gt;现在准备安装 Puma。&lt;/p&gt;

&lt;p&gt;一个简单的办法是把它加入你应用的 Gemfile。打开 Gemfile(确定你是在你的应用的根目录)：&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;vi Gemfile&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;在文件末尾，加入这一行：&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;gem 'puma'&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Save and exit.&lt;/p&gt;

&lt;p&gt;要安装 Puma，以及相关的依赖，run Bundler：&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;bundle&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;现在 puma 已经安装了，不过我们还需要配置它。&lt;/p&gt;
&lt;h3 id="配置Puma"&gt;配置 Puma&lt;/h3&gt;
&lt;p&gt;配置 Puma 之前，你要看一下你的服务器的 CPU 核的数量。用这个命令可以轻易做到：&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;grep -c processor /proc/cpuinfo&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;现在加入 Puma 配置到 &lt;code&gt;config/puma.rb&lt;/code&gt;。打开文件：&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;vi config/puma.rb&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;拷贝粘贴这些配置到文件里：&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Change to match your CPU core count
workers 2

# Min and Max threads per worker
threads 1, 6

app_dir = File.expand_path("../..", __FILE__)
shared_dir = "#{app_dir}/shared"

# Default to production
rails_env = ENV['RAILS_ENV'] || "production"
environment rails_env

# Set up socket location
bind "unix://#{shared_dir}/sockets/puma.sock"

# Logging
stdout_redirect "#{shared_dir}/log/puma.stdout.log", "#{shared_dir}/log/puma.stderr.log", true

# Set master PID and state locations
pidfile "#{shared_dir}/pids/puma.pid"
state_path "#{shared_dir}/pids/puma.state"
activate_control_app

on_worker_boot do
  require "active_record"
  ActiveRecord::Base.connection.disconnect! rescue ActiveRecord::ConnectionNotEstablished
  ActiveRecord::Base.establish_connection(YAML.load_file("#{app_dir}/config/database.yml")[rails_env])
end
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;把&lt;code&gt;workers&lt;/code&gt;的数量改为你的服务器的 CPU 核心的数量。&lt;/p&gt;

&lt;p&gt;Save and exit.
这会给 puma 配置你应用的位置，Puma 的 socket、logs、PIDs 的位置。可以自由修改这个文件，加入其他你需要的选项。&lt;/p&gt;

&lt;p&gt;现在创建配置文件里引用到的目录：&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;mkdir -p shared/pids shared/sockets shared/log&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id="创建Puma Upstart Script"&gt;创建 Puma Upstart Script&lt;/h3&gt;
&lt;p&gt;让我们创建一个 Upstart init script ,这样就能简单的开始和停止 Puma，并确保在服务器启动时同时启动。&lt;/p&gt;

&lt;p&gt;从 Puma GitHub 库下载 Jungle Upstart tool 到你的&lt;code&gt;home&lt;/code&gt;目录：&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd ~
wget https://raw.githubusercontent.com/puma/puma/master/tools/jungle/upstart/puma-manager.conf
wget https://raw.githubusercontent.com/puma/puma/master/tools/jungle/upstart/puma.conf
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;现在打开提供的 puma.conf 文件，这样我们能配置 Puma 开发用户：&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;vi puma.conf&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;找到指定&lt;code&gt;setuid&lt;/code&gt;和&lt;code&gt;setuid&lt;/code&gt;的两行，然后用你的开发用户和组的名字替换"apps"。比如，如果你的开发用户叫做"deploy",这几行看起来像这样：&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;setuid deploy
setgid deploy
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Save and exit.&lt;/p&gt;

&lt;p&gt;拷贝 scripts 到 Upstart servives 目录：&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;sudo cp puma.conf puma-manager.conf /etc/init&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;code&gt;puma-manager.conf&lt;/code&gt; 脚本引用了 它管理的应用的&lt;code&gt;/etc/puma.conf&lt;/code&gt;。现在创建并编辑这个编录文件：&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;sudo vi /etc/puma.conf&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;文件里的每一行就是你希望 puma-manager 管理的一个应用的路径。现在加入你的应用的路径。比如：&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;/home/&lt;code&gt;deploy&lt;/code&gt;/&lt;code&gt;appname&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Save and exit.&lt;/p&gt;

&lt;p&gt;现在你的应用已经配置为随服务器引导 (boot time) 而启动。你的应用在你的服务器 reboot 的时候重新启动。&lt;/p&gt;
&lt;h3 id="手动启动Puma应用"&gt;手动启动 Puma 应用&lt;/h3&gt;
&lt;p&gt;要启动所有被管理的 Puma 应用，运行命令：&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;sudo start puma-manager&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;或者你想使用 puma Upstart script 启动单个 Puma 应用：&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;sudo start puma app=/home/&lt;code&gt;deploy&lt;/code&gt;/&lt;code&gt;appname&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;可以使用&lt;code&gt;restart&lt;/code&gt; 和&lt;code&gt;stop&lt;/code&gt; 来控制应用：&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo stop puma-manager
sudo restart puma-manager
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;现在你的 Rails 应用的生产环境运行在 puma 下了，并被&lt;code&gt;shared/sockets/puma.sock&lt;/code&gt;socket 监听。在你的应用被外部用户访问之前，你需要设置 Nginx 反向代理。&lt;/p&gt;
&lt;h3 id="安装和配置Nginx"&gt;安装和配置 Nginx&lt;/h3&gt;
&lt;p&gt;使用 apt-get 安装 Nginx :&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;sudo apt-get install nginx&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;现在打开默认服务器块：&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;sudo vi /etc/nginx/sites-available/default&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;用下面的代码块替换文件内容。确定使用相应的&lt;code&gt;用户名&lt;/code&gt;和&lt;code&gt;应用名字&lt;/code&gt;替换&lt;code&gt;deploy&lt;/code&gt;和&lt;code&gt;appname&lt;/code&gt;部分：&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;upstream app {
    # Path to Puma SOCK file, as defined previously
    server unix:/home/deploy/appname/shared/sockets/puma.sock fail_timeout=0;
}

server {
    listen 80;
    server_name localhost;

    root /home/deploy/appname/public;

    try_files $uri/index.html $uri @app;

    location @app {
        proxy_pass http://app;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_redirect off;
    }

    error_page 500 502 503 504 /500.html;
    client_max_body_size 4G;
    keepalive_timeout 10;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Save and exit.&lt;/p&gt;

&lt;p&gt;这个配置 Nginx 作为反向代理，这样 HTTP 请求通过 Unix socket 抵达 Puma 应用服务器。随意修改配置到你感到满意为止。&lt;/p&gt;

&lt;p&gt;重启 Nginx 使修改生效：&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;sudo service nginx restart&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;现在你的应用的生产环境已经可以通过你的服务器的公共 IP 地址或者 FQDN 访问了。要访问我们之前创建的 Tasks controller，在 web 浏览器里面访问：&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="http://server_public_IP/tasks" rel="nofollow" target="_blank"&gt;http://server_public_IP/tasks&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;你会看到和第一次测试时同样的页面，不过现在被架设在了 nginx 和 Puma 上。&lt;/p&gt;
&lt;h3 id="结论"&gt;结论&lt;/h3&gt;
&lt;p&gt;恭喜！
你已经在 Nginx 和 Puma 上部署了你的 Rails on Ruby 应用的生产环境。&lt;/p&gt;

&lt;p&gt;如果你希望增强你在生产环境下的 Rails 应用部署的能力，你可以查看系列教程 &lt;a href="https://www.digitalocean.com/community/tutorial_series/how-to-use-capistrano-to-automate-deployments" rel="nofollow" target="_blank" title=""&gt;How To Use Capistrano to Automate Deployments&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;这个系列基于 CentOS，不过对于自动部署你的应用也有帮助。&lt;/p&gt;

&lt;p&gt;[1]: &lt;a href="https://ruby-china.org/topics/32449" rel="nofollow" target="_blank"&gt;https://ruby-china.org/topics/32449&lt;/a&gt;
[2]: &lt;a href="https://ruby-china.org/topics/32450" rel="nofollow" target="_blank"&gt;https://ruby-china.org/topics/32450&lt;/a&gt;&lt;/p&gt;</description>
      <author>ff4415</author>
      <pubDate>Sun, 05 Mar 2017 22:01:57 +0800</pubDate>
      <link>https://ruby-china.org/topics/32451</link>
      <guid>https://ruby-china.org/topics/32451</guid>
    </item>
    <item>
      <title>在 Ubuntu 14.04 下使用 PostgreSQL 部署 Ruby on Rails</title>
      <description>&lt;blockquote&gt;
&lt;p&gt;原文链接： &lt;a href="https://www.digitalocean.com/community/tutorials/how-to-use-postgresql-with-your-ruby-on-rails-application-on-ubuntu-14-04" rel="nofollow" target="_blank" title=""&gt;How To Use PostgreSQL with Your Ruby on Rails Application on Ubuntu 14.04&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id="简介"&gt;简介&lt;/h3&gt;
&lt;p&gt;Ruby on Rails 使用 sqlite3 作为默认数据库。在很多情况下 sqlite3 都很好用，不过也可能会不满足你的应用。如果你的应用要求可扩展性，集中化，可控性 (或者其它特性) 等等由客户端/服务端 SQL 数据库，比如 PostgreSQL 或 MySQL 提供的特性。你就需要执行一些额外的步骤去搭载并运行它们。&lt;/p&gt;

&lt;p&gt;此教程展示如何在 Ubuntu 14.04 服务器上建立一个 Ruby on Rails 的开发环境，来让你的应用程序使用 PostgreSQL 数据库。首先，我们简述如何安装和配置 PostgreSQL，然后我们会展示如何创建一个使用 PostgreSQL 作为数据库服务器的 rails 应用程序。&lt;/p&gt;
&lt;h3 id="预备条件"&gt;预备条件&lt;/h3&gt;
&lt;p&gt;此教程要求预先有一个工作的 Ruby on Rails 开发环境。如果你还没有搭建这样一个环境，可以可以遵循以下教程：&lt;a href="https://ruby-china.org/topics/32449" title=""&gt; 在 Ubuntu 14.04 上使用 rbenv 安装 Ruby on Rails&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;你还需要有 superuser 权限，或&lt;code&gt;sudo&lt;/code&gt;账户，如此你才能安装 PostgreSQL 数据库软件。&lt;/p&gt;

&lt;p&gt;如果你准备就绪，那么我们开始安装 PostgreSQL.&lt;/p&gt;
&lt;h3 id="安装 PostgreSQL"&gt;安装 PostgreSQL&lt;/h3&gt;
&lt;p&gt;如果你还没有安装好的 PostgreSQL，那么照着下面来：&lt;/p&gt;

&lt;p&gt;首先，更新 apt-get:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ sudo apt-get update&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;然后安装 PostgreSQL 和它的开发库：&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ sudo apt-get install postgresql postgresql-contrib libpq-dev&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;PostgreSQL 安装好了，不过你还需要创建一个新的数据库账号来给你的 Rails 应用程序使用。&lt;/p&gt;
&lt;h3 id="创建数据库账号"&gt;创建数据库账号&lt;/h3&gt;
&lt;p&gt;用以下命名创建一个 PostgreSQL superuser 账号 (把 pguser 替换为你自己的账号):&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ sudo -u postgres createuser -s pguser&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;如果你要为数据库账号设置一个密码，使用以下命令进入 PostgreSQL 控制台：&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ sudo -u postgres psql&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;PostgreSQL 控制台由一个&lt;code&gt;postgres=#&lt;/code&gt;提示符标识，输入以下命令给你创建的数据库账号设置密码：&lt;/p&gt;

&lt;p&gt;&lt;code&gt;postgres=# \password pguser&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;输入你想要的密码，然后确认。&lt;/p&gt;

&lt;p&gt;现在使用以下命令退出 PostgreSQL 控制台：&lt;/p&gt;

&lt;p&gt;&lt;code&gt;postgres=# \q&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;接下来我们来创建 Rails 应用程序。&lt;/p&gt;
&lt;h3 id="创建新的 Rails 应用"&gt;创建新的 Rails 应用&lt;/h3&gt;
&lt;p&gt;在你的 home 目录创建新的  Rails 应用。使用&lt;code&gt;-d postgresql&lt;/code&gt; 选项 来设置 PostgreSQL 作为数据库，注意替换 &lt;em&gt;appname&lt;/em&gt; 为你自己应用的名字：&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ cd ~
$ rails new appname -d postgresql
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;然后进入应用程序目录：&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ cd appname&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;下一步是配置应用的数据库联接。&lt;/p&gt;
&lt;h3 id="配置数据库联接"&gt;配置数据库联接&lt;/h3&gt;
&lt;p&gt;你先前创建的 PostgreSQL 账号 将用来 创建你应用程序的测试和开发环境数据库。我们需要给你的应用程序配置适当的数据库设置。&lt;/p&gt;

&lt;p&gt;打开你的应用程序的数据库配置文件：&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ vi config/database.yml&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;在&lt;code&gt;default&lt;/code&gt;段落，找到"pool: 5"这一行，然后在这行下面加上以下几行 (注意把 &lt;em&gt;pguser&lt;/em&gt; 和 &lt;em&gt;pguser_password&lt;/em&gt; 替换成你自己的 PostgreSQL 账号和密码):&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;config/database.yml excerpt&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;host: localhost
username: pguser
password: pguser_password
&lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;保存然后退出。&lt;/p&gt;
&lt;h3 id="创建应用程序数据库"&gt;创建应用程序数据库&lt;/h3&gt;
&lt;p&gt;使用 rake 命令创建你的应用程序的 &lt;code&gt;development&lt;/code&gt;和&lt;code&gt;test&lt;/code&gt;数据库：&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ rake db:create&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;这将会在你的 PostgreSQL 服务器上创建两个数据库。例如，如果你的应用程序名字为"appname",那么创建的数据库就会叫做"appname_development" 和 "appname_test".&lt;/p&gt;

&lt;p&gt;如果在这里返回一个 error，重读前面的章节 (配置服务器联接) 确保&lt;code&gt;database.yml&lt;/code&gt;下面的&lt;code&gt;host&lt;/code&gt;,&lt;code&gt;username&lt;/code&gt;和&lt;code&gt;password&lt;/code&gt;设置正确。确定数据库信息设置正确后，尝试重新创建应用程序数据库。&lt;/p&gt;
&lt;h3 id="测试配置"&gt;测试配置&lt;/h3&gt;
&lt;p&gt;测试你的应用程序是否能使用 PostgreSQL 最简单的方式就是运行它。&lt;/p&gt;

&lt;p&gt;比如，运行开发环境 (默认的),使用以下命令：&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ rails server&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;这将会在 localhost port 3000 下面运行你的 Rails 程序。&lt;/p&gt;

&lt;p&gt;如果你的 Rails 程序在远程服务器，而你想通过 web 浏览器访问它，可以把程序绑定到你的服务器的一个公网 IP 地址。首先，查看服务器的公网 IP，然后使用&lt;code&gt;rails server&lt;/code&gt;命令 (把 server_public_IP 替换成你自己的服务器 IP):&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ rails server --binding=server_public_IP&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;现在你就可以通过浏览器里在服务器的公网 IP 地址下的 3000 端口访问你的 Rails 应用程序了：&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Visit in a web browser:&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;code&gt;http://server_public_IP:3000&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;如果你看到了"Welcome aboard" Ruby on Rails 页面，那么你的程序就配置成功并且连接到 PostgreSQL 数据库了。&lt;/p&gt;
&lt;h3 id="结论"&gt;结论&lt;/h3&gt;
&lt;p&gt;现在你可以在 Ubuntu 14.04 下面用 PostgreSQL 作为数据库运行 Ruby on Rails 程序的开发环境了。&lt;/p&gt;

&lt;p&gt;Good luck!&lt;/p&gt;</description>
      <author>ff4415</author>
      <pubDate>Sun, 05 Mar 2017 21:55:58 +0800</pubDate>
      <link>https://ruby-china.org/topics/32450</link>
      <guid>https://ruby-china.org/topics/32450</guid>
    </item>
    <item>
      <title>在 Ubuntu 14.04 上使用 rbenv  安装 Ruby on Rails</title>
      <description>&lt;blockquote&gt;
&lt;p&gt;原文链接： &lt;a href="https://www.digitalocean.com/community/tutorials/how-to-install-ruby-on-rails-with-rbenv-on-ubuntu-14-04" rel="nofollow" target="_blank" title=""&gt;How To Install Ruby on Rails with rbenv on Ubuntu 14.04&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id="简介"&gt;简介&lt;/h3&gt;
&lt;p&gt;Ruby on Rails 是一个非常流行的开源 web 框架，提供了用 Ruby 编写 web 应用的极佳途径。&lt;/p&gt;

&lt;p&gt;此教程展示如何使用 rbenv 在 Ubuntu 14.04 上安装 Ruby on Rails，为你提供一个开发 Ruby on Rails 应用程序的稳定环境。rbenv 提供了一个方便途径来安装和管理多个 Ruby 版本，而且相比 RVM 要更简单以及更少侵入 (less intrusive)。这将帮助你确保用以开发的 Ruby 版本匹配你的生产环境。&lt;/p&gt;
&lt;h3 id="预备条件"&gt;预备条件&lt;/h3&gt;
&lt;p&gt;安装 rbenv 之前，你需要有一台 Ubuntu 14.04 服务器的&lt;strong&gt;superuser&lt;/strong&gt;权限。如果你需要自己设置，请依据此教程的 1~3 步骤：&lt;a href="https://www.digitalocean.com/community/tutorials/initial-server-setup-with-ubuntu-14-04" rel="nofollow" target="_blank" title=""&gt;Initial Server Setup on Ubuntu 14.04&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;当你满足了预备条件，我们就可以继续安装 rbenv 了。&lt;/p&gt;
&lt;h3 id="安装 rbenv"&gt;安装 rbenv&lt;/h3&gt;
&lt;p&gt;现在来安装 rbenv，我们使用它来安装和管理 Ruby 安装包。&lt;/p&gt;

&lt;p&gt;首先，更新 apt-get:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ sudo apt-get update&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;使用 apt-get 安装 rbenv 和 Ruby 依赖：&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ sudo apt-get install git-core curl zlib1g-dev build-essential libssl-dev libreadline-dev libyaml-dev libsqlite3-dev sqlite3 libxml2-dev libxslt1-dev libcurl4-openssl-dev python-software-properties libffi-dev&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;然后我就可以安装 rbenv 了。最简单的方法就是使用 Ruby 用户来运行以下命令：&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ cd&lt;/code&gt;
&lt;code&gt;$ git clone git://github.com/sstephenson/rbenv.git .rbenv&lt;/code&gt;
&lt;code&gt;$ echo 'export PATH="$HOME/.rbenv/bin:$PATH"' &amp;gt;&amp;gt; ~/.bash_profile&lt;/code&gt;
&lt;code&gt;$ echo 'eval "$(rbenv init -)"' &amp;gt;&amp;gt; ~/.bash_profile&lt;/code&gt;
&lt;code&gt;$&lt;/code&gt;
&lt;code&gt;$ git clone git://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build&lt;/code&gt;
&lt;code&gt;$ echo 'export PATH="$HOME/.rbenv/plugins/ruby-build/bin:$PATH"' &amp;gt;&amp;gt; ~/.bash_profile&lt;/code&gt;
&lt;code&gt;$ source ~/.bash_profile&lt;/code&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;注意：在 Ubuntu Desktop 版本里，要把以上代码块里面的&lt;code&gt;.bash_profile&lt;/code&gt;都替换为&lt;code&gt;.bashrc&lt;/code&gt;。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;以上将会把 rbenv 安装到你的 home 目录，并设置了相应的环境变量使 rbenv 对应到可用的 Ruby 版本。&lt;/p&gt;

&lt;p&gt;现在来安装 Ruby。&lt;/p&gt;
&lt;h3 id="安装 Ruby"&gt;安装 Ruby&lt;/h3&gt;
&lt;p&gt;使用 rbenv 之前，关心一下哪个 Ruby 版本是你想要安装的。我们这里要安装的文章写作时的最新版本，Ruby 2.2.3。你可以到&lt;a href="https://www.ruby-lang.org/en/downloads/" rel="nofollow" target="_blank" title=""&gt; Ruby Downloads page&lt;/a&gt; 查询一下 Ruby 的最新版本。&lt;/p&gt;

&lt;p&gt;作为 Ruby 用户登录，使用以下命令安装：&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ rbenv install -v 2.2.3&lt;/code&gt;
&lt;code&gt;$ rbenv global 2.2.3&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;global&lt;/code&gt;子命令设置所有 shell 默认使用的 Ruby 版本。如果你想要安装并使用别的版本，简单运行 rbenv 命令跟个版本号就可以了。&lt;/p&gt;

&lt;p&gt;以下命令效验 Ruby 已经正确安装：&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ ruby -v&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;很可能你不想要 Rubygems 给你安装的每个 gem 生成一堆的本地文档。这会拉长安装过程。想要关闭，运行这个命令：&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ echo "gem: --no-document" &amp;gt; ~/.gemrc&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;你也可能想要安装 bundle gem，来管理你的应用程序依赖：&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ gem install bundler&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;现在 Ruby 安装好了，接着来安装 Rails。&lt;/p&gt;
&lt;h3 id="安装 Rails"&gt;安装 Rails&lt;/h3&gt;
&lt;p&gt;以同一个用户登录，使用以下命令安装 Rails(可以用 &lt;code&gt;-v&lt;/code&gt; 选项指定版本号):&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ gem install rails&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;任何时候，当你安装新版本 Ruby 或者提供命令的 gem 之后，你需要运行&lt;code&gt;rehash&lt;/code&gt;子命令。这将会给 rbenv 识别到的所有 Ruby 可执行文件安装&lt;em&gt;shims&lt;/em&gt;，这样你才能使用这些可执行文件：&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ rbenv rehash&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;通过打印版本号来效验 Rails 已经正确安装，命令如下：&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ rails -v&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;如果安装正确，你将看到已安装 Rails 的版本号。&lt;/p&gt;
&lt;h3 id="安装 Javascript Runtime"&gt;安装 Javascript Runtime&lt;/h3&gt;
&lt;p&gt;以下 Rails 特性，比如 Asset Pipeline, 依赖 Javascript runtime。通过安装 Node.js 来提供这些功能：&lt;/p&gt;

&lt;p&gt;将 Node.js PPA 加入 apt-get:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ sudo add-apt-repository ppa:chris-lea/node.js&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;然后更新 apt-get 并安装 Node.js 程序包：&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ sudo apt-get update&lt;/code&gt;
&lt;code&gt;$ sudo apt-get install nodejs&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;恭喜！Ruby on Rails 现在安装到你的系统了。&lt;/p&gt;
&lt;h3 id="可选步骤"&gt;可选步骤&lt;/h3&gt;
&lt;p&gt;如果想改进安装步骤，这里给几个建议：&lt;/p&gt;
&lt;h4 id="配置 Git"&gt;配置 Git&lt;/h4&gt;
&lt;p&gt;一个好的版本控制系统是程序编码的基础。参考安装 Git 教程的&lt;a href="https://www.digitalocean.com/community/tutorials/how-to-install-git-on-ubuntu-14-04#how-to-set-up-git" rel="nofollow" target="_blank" title=""&gt; How To Set Up Git &lt;/a&gt;章节。&lt;/p&gt;
&lt;h4 id="安装数据库"&gt;安装数据库&lt;/h4&gt;
&lt;p&gt;Rails 使用 sqlite3 作为默认数据库。这可能不能满足你的需求。你可能会需要安装一个 RDBMS，比如 MySQL 或 PostgreSQL 这样的。&lt;/p&gt;

&lt;p&gt;例如，如果你要安装 MySQL 作为数据库，用 apt-get 安装 MySQL 如下：&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ sudo apt-get install mysql-server mysql-client libmysqlclient-dev&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;然后安装 &lt;code&gt;mysql2&lt;/code&gt; gem，如下：&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ gem install mysql2&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;然后就可以在你的 Rails 应用程序中使用 MySQL 了。注意确保 MySQL 和你的 Rails 程序配置正确。&lt;/p&gt;
&lt;h3 id="创建测试应用(可选)"&gt;创建测试应用 (可选)&lt;/h3&gt;
&lt;p&gt;如果你想要确定你的 Ruby on Rails 是否顺利的安装好了。你可以快速创建一个测试程序来测试一下。为了简单，我们的测试程序使用 sqlite3 作为数据库：&lt;/p&gt;

&lt;p&gt;在 home 目录创建一个新 Rails 程序：&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ cd ~&lt;/code&gt;
&lt;code&gt;$ rails new testapp&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;然后进入程序目录：&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ cd testapp&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;创建 sqlite3 数据库：&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ rake db:create&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;如果你不知道服务器的公共 IP 地址，可以使用如下命令查看：&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ ip addr show eth0 | grep inet | awk '{ print $2; }' | sed 's/\/.*$//'&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;拷贝 IPv4 地址到剪切板，使用以下命令启动你的 Rails 程序 (用拷贝的 IP 地址替换 &lt;strong&gt;server_public_IP&lt;/strong&gt; ):&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ rails server --binding=server_public_IP&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;如果工作正常，你的程序会运行在服务器的公共 IP 的端口号 3000 下面。使用 web 浏览器访问如下：&lt;/p&gt;

&lt;p&gt;&lt;code&gt;http://server_public_IP:3000&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;如果看到 Rails 的 "Welcome aboard" 页面，说明你的 Ruby on Rails 程序工作正常！&lt;/p&gt;
&lt;h3 id="结尾"&gt;结尾&lt;/h3&gt;
&lt;p&gt;现在你可以开始开发新 Ruby on Rails 程序了。Good luck!&lt;/p&gt;</description>
      <author>ff4415</author>
      <pubDate>Sun, 05 Mar 2017 21:54:09 +0800</pubDate>
      <link>https://ruby-china.org/topics/32449</link>
      <guid>https://ruby-china.org/topics/32449</guid>
    </item>
    <item>
      <title>微信自定义菜单，使用 net/http 标准库发起 POST，返回『40016』错误</title>
      <description>&lt;h2 id="代码"&gt;代码&lt;/h2&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;poJson&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="s2"&gt;"button"&lt;/span&gt;&lt;span class="p"&gt;:[&lt;/span&gt;
     &lt;span class="p"&gt;{&lt;/span&gt;  
          &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="ss"&gt;:"click"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s2"&gt;"name"&lt;/span&gt;&lt;span class="ss"&gt;:"sing"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s2"&gt;"key"&lt;/span&gt;&lt;span class="ss"&gt;:"V1001_TODAY_MUSIC"&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
           &lt;span class="s2"&gt;"name"&lt;/span&gt;&lt;span class="ss"&gt;:"菜单"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
           &lt;span class="s2"&gt;"sub_button"&lt;/span&gt;&lt;span class="p"&gt;:[&lt;/span&gt;
           &lt;span class="p"&gt;{&lt;/span&gt;    
               &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="ss"&gt;:"view"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
               &lt;span class="s2"&gt;"name"&lt;/span&gt;&lt;span class="ss"&gt;:"search"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
               &lt;span class="s2"&gt;"url"&lt;/span&gt;&lt;span class="ss"&gt;:"http://www.soso.com/"&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
               &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="ss"&gt;:"view"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
               &lt;span class="s2"&gt;"name"&lt;/span&gt;&lt;span class="ss"&gt;:"video"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
               &lt;span class="s2"&gt;"url"&lt;/span&gt;&lt;span class="ss"&gt;:"http://v.qq.com/"&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
               &lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="ss"&gt;:"click"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
               &lt;span class="s2"&gt;"name"&lt;/span&gt;&lt;span class="ss"&gt;:"favor"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
               &lt;span class="s2"&gt;"key"&lt;/span&gt;&lt;span class="ss"&gt;:"V1001_GOOD"&lt;/span&gt;
            &lt;span class="p"&gt;}]&lt;/span&gt;
       &lt;span class="p"&gt;}]&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;uri&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;URI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'https://api.weixin.qq.com/cgi-bin/token'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;uri&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;URI&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;encode_www_form&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Net&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;HTTP&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uri&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;hash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt; &lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;body&lt;/span&gt;

&lt;span class="n"&gt;uri&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;URI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"https://api.weixin.qq.com/cgi-bin/menu/create?access_token=&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="nb"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"access_token"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Net&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;HTTP&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post_form&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uri&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"data"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;poJson&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="错误码"&gt;错误码&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;"{\"errcode\":40016,\"errmsg\":\"invalid button size hint: [dX4b8a0899vr22]\"}"&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;但是在微信接口测试工具里测试成功。&lt;/p&gt;
&lt;h2 id="在这个问题上已经纠结 了一天，我怀疑是我的post包构造的有问题，希望大家能帮我指出。"&gt;在这个问题上已经纠结 了一天，我怀疑是我的 post 包构造的有问题，希望大家能帮我指出。&lt;/h2&gt;&lt;h2 id="已解决"&gt;已解决&lt;/h2&gt;
&lt;p&gt;换用 rest-client 解决了问题&lt;/p&gt;

&lt;p&gt;&lt;code&gt;gem 'rest-client', '~&amp;gt; 2.0'&lt;/code&gt;&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'rest-client'&lt;/span&gt;

&lt;span class="no"&gt;RestClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_json&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;提交成功&lt;/p&gt;

&lt;p&gt;返回码：
&lt;code&gt;"{\"errcode\":0,\"errmsg\":\"ok\"}"&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;##中文问题&lt;/p&gt;

&lt;p&gt;重新 post 一个带有中文的 json&lt;/p&gt;

&lt;p&gt;返回错误码：&lt;/p&gt;

&lt;p&gt;&lt;code&gt;"{\"errcode\":40033,\"errmsg\":\"invalid charset. please check your request, if include \\\\uxxxx will create fail! hint: [xGNora0471vr20]\"}"&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;按照社区里的方法&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'rest-client'&lt;/span&gt;

&lt;span class="n"&gt;pj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"button"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;buttons&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;gsub!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/\\u([0-9a-z]{4})/&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="vg"&gt;$1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_i&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;)].&lt;/span&gt;&lt;span class="nf"&gt;pack&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"U"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_json&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;blank?&lt;/span&gt;

&lt;span class="no"&gt;RestClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;缺少这一行
&lt;code&gt;payload = pj.to_json if payload.blank?&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;有时候会报错误码：
&lt;code&gt;"{\"errcode\":44002,\"errmsg\":\"empty post data hint: [FQ_D_0824vr18]\"}"&lt;/code&gt;&lt;/p&gt;
&lt;h3 id="遗留问题"&gt;遗留问题&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;在本地 &lt;code&gt;rails c&lt;/code&gt; 调用&lt;code&gt;"中文".to_json&lt;/code&gt; 解析中文很正常，为什么 post 过去就变成'\uxxxx'了。 &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;为什么用'net/http'标准库 post 就不行了。
我用&lt;code&gt;Net::HTTP.post_form(uri, "data" =&amp;gt; data)&lt;/code&gt; post 到了本地，
&lt;code&gt;p params["data"]&lt;/code&gt; 显示输出
&lt;code&gt;"{\"button\":[{\"type\":\"click\",\"name\":\"xxx\",\"key\":\"18\"}]}"&lt;/code&gt; 看着都很正常。
问题到底是出在了哪里。&lt;img title=":dizzy_face:" alt="😵" src="https://twemoji.ruby-china.com/2/svg/1f635.svg" class="twemoji"&gt; &lt;img title=":sob:" alt="😭" src="https://twemoji.ruby-china.com/2/svg/1f62d.svg" class="twemoji"&gt; &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <author>ff4415</author>
      <pubDate>Wed, 16 Nov 2016 18:34:07 +0800</pubDate>
      <link>https://ruby-china.org/topics/31615</link>
      <guid>https://ruby-china.org/topics/31615</guid>
    </item>
  </channel>
</rss>
