5分でRailsでクローラーを作る。【その2】【文字】【ページソース】

[5分でRailsクローラーを作る。【その1】【xpath】](http://qiita.com/k_s/items/ba162e270c375dd1407b "5分でRailsクローラーを作る。【その1】【xpath】")

の続きです。

文字条件で取得 ---精度70%---

bots_controller.rb

    def if_crawl
        @bot = Bot.find(params[:id])
        doc = Nokogiri::HTML(open("#{@bot.url}"))#URLの指定
            
        doc.css('table').each do |crawl| #テーブルを引っ張る
            @crawl = crawl.inner_html.encode("UTF-8") #↓指定の単語が全て含まれてればtrue
             if @crawl.encode("UTF-8").include?(@bot.word1) && @crawl.encode("UTF-8").include?(@bot.word2) && @crawl.encode("UTF-8").include?(@bot.word3)
                 @if_crawl = crawl.inner_html.encode("UTF-8")
             end
        end
    end

・・・

      private
      
        def bot_params
          params.require(:bot).permit(:name, :url, :xpath, :word1, :word2, :word3) #word1~3を追加
        end

if_crawl.html.erb

<div class="form align">
    <div class="jumbotron font">
        送信に成功しました!
    </div>
    
    送った内容
    <div class="jumbotron padding height">
        <%= "<table>" + @if_crawl.encode("UTF-8") + "</table>" %>
    </div>
    
    プレビュー
    <div class="jumbotron">
        <%= simple_format("<table>" + @if_crawl.encode("UTF-8") + "</table>") %>
    </div>
    
    プレビュー2 #HTMLで表示
        <%= "<table>#{@crawl.encode("UTF-8")}</table>".html_safe %>
</div>
  get 'bots/if_crawl', to: 'bots#if_crawl'

new.html.erb


<div class="col-xs-12">
<table class="type07">
    <thead>
    <tr>
        <th scope="cols"></th>
        <th scope="cols">サイト名</th>
        <th scope="cols">URL</th>
        <th scope="cols">Xpath</th>
        <th scope="cols">取得方法1</th>
        <th scope="cols">取得方法2</th>
    </tr>
    </thead>
    <tbody>
        
    <% @bots.each do |bot| %>

        <tr>
            <th scope="row"><%= bot.id %></th>
    		<td><%= bot.name  %></td>
    		<td><%= bot.url.truncate(20) %></td>
    		<td><%= bot.xpath %></td>
            <td><%= link_to "crawl", bots_crawl_path(id: bot.id) %></td>
            <td><%= link_to "文字条件", bots_if_crawl_path(id: bot.id) %></td>
        </tr>
        
    <% end %>
    </tbody>
</table>
</div>
<div class="form">

  <%= form_for :bot, url: bots_path do |f| %>
    
    <p>
      <%= f.label :name, "サイト名" %><br>
      <%= f.text_field :name, class: 'form-control input-sm', style: "width:500px;", :placeholder => "サイト名"%>
    </p>
   
    <p>
      <%= f.label :url, "URL" %><br>
      <%= f.text_area :url, class: 'form-control input-sm', style: "width:500px;", size: "10", :placeholder => "URL"%>
    </p>
    
    <p>
      <%= f.label :xpath, "Xpath" %><br>
      <%= f.text_area :xpath, class: 'form-control input-sm', style: "width:500px;", size: "10", :placeholder => "xpathで抽出する際に必要になります"%>
    </p>
    
    ###追加###
    <p>
      <%= f.label :word1, "条件ワード1" %><br>
      <%= f.text_area :word1, class: 'form-control input-sm', style: "width:500px;", size: "10", :placeholder => "文字条件抽出に必要になります" %>
    </p>
    
    <p>
      <%= f.label :word2, "条件ワード2" %><br>
      <%= f.text_area :word2, class: 'form-control input-sm', style: "width:500px;", size: "10", :placeholder => "文字条件抽出に必要になります" %>
    </p>
    
    <p>
      <%= f.label :word3, "条件ワード3" %><br>
      <%= f.text_area :word3, class: 'form-control input-sm', style: "width:500px;", size: "10", :placeholder => "文字条件抽出に必要になります" %>
    </p>
    
    ###追加###

    <p>
      <%= f.submit "登録", class: 'btn btn-primary' %>
    </p>
  <% end %>
</div>

テスト

文字を取得

CZkHKxAtzytJcBK1494433908_1494433920.png

結果
プレビュー2
SAMPLE03	プロ
デザイン	スタイルシート
カラー	オレンジ

無理やり抜粋する ---精度90%---


今までのアプローチは必要なものだけを取得するものでしたが、
こちらは一旦全てを取得しそこから、不要なものを削ぎ落としていくものです。

bots_controller.rb

    def slice_crawl
        @bot = Bot.find(params[:id])
        @doc = Nokogiri::HTML(open("#{@bot.url}")).inner_html.encode("UTF-8") #URLの指定
        @index_doc = @doc.index("#{@bot.upper}") 
        @end_doc = @doc.rindex("</html>") - 1 
        @slice_crawl_pre = @doc.slice(@index_doc..@end_doc) 
        @table_doc = @slice_crawl_pre.index("table>") + 5
        @slice_crawl = @slice_crawl_pre.slice(0..@table_doc)
    end

      private
      
        def bot_params
          params.require(:bot).permit(:name, :url, :xpath, :word1, :word2, :word3, :upper) #upper(上段)を追加
        end


取得先のHTMLコードは 〜

〜 という構造ですが、
インデックスでこのtableタグの前後を削ぎます。


routes.rb

  get 'bots/slice_crawl', to: 'bots#slice_crawl'


slice_crawl.html.erb

<div class="form align">
    <div class="jumbotron font">
        取得に成功しました!
    </div>
    
    取得した内容
    <div class="jumbotron padding height">
        <%= @slice_crawl.encode("UTF-8") %>
    </div>
    
    プレビュー
    <div class="jumbotron">
        <%= simple_format(@slice_crawl.encode("UTF-8")) %>
    </div>
    
    プレビュー2
        <%= "<table>#{@slice_crawl.encode("UTF-8")}</table>".html_safe %>
</div>

index.html.erb


<div class="col-xs-12">
<table class="type07">
    <thead>
    <tr>
        <th scope="cols"></th>
        <th scope="cols">サイト名</th>
        <th scope="cols">URL</th>
        <th scope="cols">Xpath</th>
        <th scope="cols">取得方法1</th>
        <th scope="cols">取得方法2</th>
        <th scope="cols">取得方法3</th> #追加
    </tr>
    </thead>
    <tbody>
        
    <% @bots.each do |bot| %>

        <tr>
            <th scope="row"><%= bot.id %></th>
    		<td><%= bot.name  %></td>
    		<td><%= bot.url.truncate(20) %></td>
    		<td><%= bot.xpath %></td>
            <td><%= link_to "crawl", bots_crawl_path(id: bot.id) %></td>
            <td><%= link_to "文字条件", bots_if_crawl_path(id: bot.id) %></td>
            <td><%= link_to "抜粋", bots_slice_crawl_path(id: bot.id) %></td> #追加
        </tr>
        
    <% end %>
    </tbody>
</table>
</div>
    <p>
      <%= f.label :upper, "上段" %><br>
      <%= f.text_area :upper, class: 'form-control input-sm', style: "width:500px;", size: "10", :placeholder => "上段"%>

テスト

対象サイト
html取得

FVg0xCUajBSdzWe1494435139_1494435152.png

結果
プレビュー2
SAMPLE04	デザイン	枠線	カラー
有料	プロ	有り	216色
無料	アマチュア	なし	モノトーン


以上です!

********************************************************

「作ったアプリを発信しましょう!」
自分が作ったものを他者に発信しましょう。

Ruppishはあなたが作ったものを世に出すお手伝いをします。

[Ruppish](http://ruppish.com/)

********************************************************

5分でRailsでクローラーを作る。【その1】【xpath】

f:id:sksksksksk:20170510221830j:plain
あー、テーブル抽出したい!テーブル抽出したい!





今回は、Railsクローラーアプリを作成します。
抽出対象はテーブルです。



自治体の選挙開票結果を抽出してくれるクローラーを作れたりします。

nokogiriのインストー

gem "nokogiri"
bundle


nokogiriはHTML解析をしてくれるプラグインです。

MVCの作成

rails g model bot name:text url:text xpath word1:text word2:text word3:text upper:text lower:text
rails g controller bots
rake db:migrate


カラムの量が尋常じゃなく多いのは、テーブル取得のアプローチを複数用意して柔軟に対応できるためです。
自治体のテーブルは我流で書かれていたり、とりあえずよくわからない構造で書かれてることが多くそういったものに対応するために必要になってくるんですね。



基本のアクションをさっと用意します。

class BotsController < ApplicationController
    require 'open-uri' #Gem入れたんですが
    require 'nokogiri' #なぜか動かなかったので一応
    def new
     @bot = Bot.new
    end

    def create
     @bot = Bot.new(bot_params)
     @bot.save
     redirect_to bots_path
    end
    
    def index
      @bots = Bot.all
    end
    
      private
      
        def bot_params
          params.require(:bot).permit(:name, :url, :xpath)
        end
end


ルーティングです。

  resources :bots, only: [:create, :index, :new]


次にビューです。


<div class="col-xs-12">
<table class="type07">
    <thead>
    <tr>
        <th scope="cols"></th>
        <th scope="cols">サイト名</th>
        <th scope="cols">URL</th>
        <th scope="cols">Xpath</th>
    </tr>
    </thead>
    <tbody>
        
    <% @bots.each do |bot| %>

        <tr>
            <th scope="row"><%= bot.id %></th>
    		<td><%= bot.name  %></td>
    		<td><%= bot.url.truncate(20) %></td>
    		<td><%= bot.xpath %></td>
        </tr>
        
    <% end %>
    </tbody>
</table>
</div>

new
sEzndEZaRDy8Y_n1494428772_1494428789.png


index
CHh5p8QwJTds2nx1494428875_1494428900.png

とりあえずこんな感じまでパパッと作ります。

xpathで取得 ---- 精度70%

    def crawl
        @bot = Bot.find(params[:id]) #保存した抽出対象データを呼び出す。
        doc = Nokogiri::HTML(open("#{@bot.url}")) #url先のHTML開放
        @crawl = doc.xpath("#{@bot.xpath}").inner_html #xpathで取得、HTMLで出力
    end
<div class="form align">
    <div class="jumbotron font">
        取得に成功しました!
    </div>
    
    取得した内容
    <div class="jumbotron padding height">
        <%= @crawl.encode("UTF-8") %>
    </div>
    
    プレビュー
    <div class="jumbotron">
        <%= simple_format("<table>" + @crawl.encode("UTF-8") + "</table>") %>
    </div>

    プレビュー2
        <%= "<table>#{@crawl.encode("UTF-8")}</table>".html_safe %> #htmlとして表示したい場合
</div>

<div class="col-xs-12">
<table class="type07">
    <thead>
    <tr>
        <th scope="cols"></th>
        <th scope="cols">選挙名</th>
        <th scope="cols">URL</th>
        <th scope="cols">Xpath</th>
        <th scope="cols">取得方法</th> #追加
    </tr>
    </thead>
    <tbody>
        
    <% @bots.each do |bot| %>

        <tr>
            <th scope="row"><%= bot.id %></th>
    		<td><%= bot.name  %></td>
    		<td><%= bot.url.truncate(20) %></td>
    		<td><%= bot.xpath %></td>
            <td><%= link_to "crawl", bots_crawl_path(id: bot.id) %></td> #追加
        </tr>
        
    <% end %>
    </tbody>
</table>
</div>
  get 'bots/crawl', to: 'bots#crawl'

xpathテスト

xpath取得

faG7YESfHG92DT71494431659_1494431675.png

crawlリンク押した結果

okeWadSEgQg8guO1494431763_1494431790.png



できました!





長くなりそうなので、
残りの2つは別記事で書きます。





********************************************************

「作ったアプリを発信しましょう!」
自分が作ったものを他者に発信しましょう。

Ruppishはあなたが作ったものを世に出すお手伝いをします。

[Ruppish](http://ruppish.com/)

********************************************************

5分でRailsアプリにマークダウンとプレビューを実装。

f:id:sksksksksk:20170510221830j:plain

Railsアプリにマークダウン機能を実装します。

今回はQiitaマークダウンというGemを使用します。

アプリの作成

$ rails g model post content:text
$ rails g controller posts
$ rake db:migrate

/app/controller/posts_controller.rb

    def new
        @post = Post.new
    end
    
    def create
          @post = Post.new(post_params)
          @post.save
          redirect_to @post
    end
    
    def show
        @post = Post.find(params[:id])
        @post.save!
    end

    private
    
     def post_params
         params.require(:post).permit(:content)
     end

/app/views/new.html.erb

<%= form_for(@post) do |f| %>
    <%= f.text_area :content %>
    <%= f.submit %>
<% end %>

/app/views/show.html.erb

<%= @post.content %>

/config/routes.rb

  resources :posts, only:[:create, :show, :new]

これで投稿できるようになります。


Qiitaマークダウンの導入

gem 'qiita-markdown'
gem 'github-linguist'
bundle

bundleが失敗する人は2つのプラグインが足りていません
以下を実行してください。

ちなみにCloud9ではエラーは出ません。

$ sudo yum -y install libicu-devel
$ gem install charlock_holmes -v '0.7.3'
$ sudo yum -y install cmake
$ gem install rugged -v '0.25.0b4'

これでマークダウンが使えます。
show.html.erbを以下のように修正してください。

<%= qiita_markdown(@post.content) %>

helperも必要になります。

/application_helper.rb

module ApplicationHelper
  def qiita_markdown(markdown)
    processor = Qiita::Markdown::Processor.new(hostname: "example.com")
    processor.call(markdown)[:output].to_s.html_safe
  end
end

プレビューを作成

書いた記事が横もしくは下でリアルタイムで表示されます。

マークダウン記法では自分の記事がうまく描かれるかチェックしなければならないので必須でしょう。

ここでは、そのプレビューも作成してみましょう。



Vue.jsとmarked.jsを読み込みます。

app/views/application.html.erb

 <script src='https://cdnjs.cloudflare.com/ajax/libs/marked/0.3.5/marked.js'></script>
 <script src='https://cdnjs.cloudflare.com/ajax/libs/vue/1.0.10/vue.js'></script>

formを編集します。
/new.html.erb

<%= form_for(@post) do |f| %>
<div class="form-group">
<div id='editor'>
<textarea name="post[content]" id="n" class="form-control" rows="20" v-model='input' debounce='50'></textarea>
<div class="di_inline_t preview">
<div v-html='input | marked' style: :"width: 650px;"></div>
 </div>
</div>
</div>
<%= f.submit %>
<% end %>


<script type="text/javascript">
 window.onload = function() {
 new Vue({
 el: '#editor',
 data: {
 input: '<%== j @post.content %>',
 },
 filters: {
 marked: marked,
 },
 });
 };
</script>

Bootstrapの導入

bootstrapを導入しないと一部のマークダウンが反映されません。

gem 'bootstrap-sass'

なんでもいいです.scss

@import "bootstrap-sprockets";
@import "bootstrap";

再起動します。
これで使えるようになります。
リロードしないと使えないという人はapplication.jsの//= require turbolinksを決してください。
あるとうまく動かないことがあります。

おしゃれなマークダウン

コードをみやすくする為にscssに以下のコードを追加するといいかもしれません。

//------------------------シンタックスハイライト

.code-frame {

  background-color: #eee;

  .code-lang {
    span {
      padding: .5em;
      color: #fff;
      background-color: #666;
    }
  }

  .highlight {
    .hll { background-color: #ffffcc }
    .c { color: #999988; font-style: italic } /* Comment */
    .err { color: #a61717; background-color: #e3d2d2 } /* Error */
    .k { color: #000000; font-weight: bold } /* Keyword */
    .o { color: #000000; font-weight: bold } /* Operator */
    .cm { color: #999988; font-style: italic } /* Comment.Multiline */
    .cp { color: #999999; font-weight: bold; font-style: italic } /* Comment.Preproc */
    .c1 { color: #999988; font-style: italic } /* Comment.Single */
    .cs { color: #999999; font-weight: bold; font-style: italic } /* Comment.Special */
    .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
    .ge { color: #000000; font-style: italic } /* Generic.Emph */
    .gr { color: #aa0000 } /* Generic.Error */
    .gh { color: #999999 } /* Generic.Heading */
    .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
    .go { color: #888888 } /* Generic.Output */
    .gp { color: #555555 } /* Generic.Prompt */
    .gs { font-weight: bold } /* Generic.Strong */
    .gu { color: #aaaaaa } /* Generic.Subheading */
    .gt { color: #aa0000 } /* Generic.Traceback */
    .kc { color: #000000; font-weight: bold } /* Keyword.Constant */
    .kd { color: #000000; font-weight: bold } /* Keyword.Declaration */
    .kn { color: #000000; font-weight: bold } /* Keyword.Namespace */
    .kp { color: #000000; font-weight: bold } /* Keyword.Pseudo */
    .kr { color: #000000; font-weight: bold } /* Keyword.Reserved */
    .kt { color: #445588; font-weight: bold } /* Keyword.Type */
    .m { color: #009999 } /* Literal.Number */
    .s { color: #d01040 } /* Literal.String */
    .na { color: #008080 } /* Name.Attribute */
    .nb { color: #0086B3 } /* Name.Builtin */
    .nc { color: #445588; font-weight: bold } /* Name.Class */
    .no { color: #008080 } /* Name.Constant */
    .nd { color: #3c5d5d; font-weight: bold } /* Name.Decorator */
    .ni { color: #800080 } /* Name.Entity */
    .ne { color: #990000; font-weight: bold } /* Name.Exception */
    .nf { color: #990000; font-weight: bold } /* Name.Function */
    .nl { color: #990000; font-weight: bold } /* Name.Label */
    .nn { color: #555555 } /* Name.Namespace */
    .nt { color: #000080 } /* Name.Tag */
    .nv { color: #008080 } /* Name.Variable */
    .ow { color: #000000; font-weight: bold } /* Operator.Word */
    .w { color: #bbbbbb } /* Text.Whitespace */
    .mf { color: #009999 } /* Literal.Number.Float */
    .mh { color: #009999 } /* Literal.Number.Hex */
    .mi { color: #009999 } /* Literal.Number.Integer */
    .mo { color: #009999 } /* Literal.Number.Oct */
    .sb { color: #d01040 } /* Literal.String.Backtick */
    .sc { color: #d01040 } /* Literal.String.Char */
    .sd { color: #d01040 } /* Literal.String.Doc */
    .s2 { color: #d01040 } /* Literal.String.Double */
    .se { color: #d01040 } /* Literal.String.Escape */
    .sh { color: #d01040 } /* Literal.String.Heredoc */
    .si { color: #d01040 } /* Literal.String.Interpol */
    .sx { color: #d01040 } /* Literal.String.Other */
    .sr { color: #009926 } /* Literal.String.Regex */
    .s1 { color: #d01040 } /* Literal.String.Single */
    .ss { color: #990073 } /* Literal.String.Symbol */
    .bp { color: #999999 } /* Name.Builtin.Pseudo */
    .vc { color: #008080 } /* Name.Variable.Class */
    .vg { color: #008080 } /* Name.Variable.Global */
    .vi { color: #008080 } /* Name.Variable.Instance */
    .il { color: #009999 } /* Literal.Number.Integer.Long */
  }
}

以上です!



*********************************************************
「作ったアプリを発信しましょう!」

自分が作ったものを他者に発信しましょう。

Ruppishはあなたが作ったものを世に出すお手伝いをします。

Ruppish

*********************************************************

5分でRailsアプリにおしゃれでかっこいいグラフを実装。

f:id:sksksksksk:20170510232656p:plain

今回はおしゃれなグラフを作成します。

アニメーションがつき複数のグラフも作成することができます。

個人的にはChartkickよりもおすすめです。

しかも、実装が非常に簡単です。

ソースを読み込む JS

<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/highcharts-more.js"></script>
<script src="https://code.highcharts.com/modules/exporting.js"></script>

Jsのソースをいくつか読み込みます。

グラフを表示させる為のDIV

<div id="container" style="min-width: 400px; max-width: 600px; height: 400px; margin: 0 auto"></div>

divの間にチャートが表示されます。

チャートを生成するJS

Highcharts.chart('container', {
 
    chart: {
        polar: true,
        type: 'line'
    },
 
    title: {
        text: 'Budget vs spending',
        x: -80
    },
 
    pane: {
        size: '80%'
    },
 
    xAxis: {
        categories: ['Sales', 'Marketing', 'Development', 'Customer Support',
                'Information Technology', 'Administration'],
        tickmarkPlacement: 'on',
        lineWidth: 0
    },
 
    yAxis: {
        gridLineInterpolation: 'polygon',
        lineWidth: 0,
        min: 0

以上です。これだけで表示されます。

今回私が作ったものはこちらのコードです。

<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/highcharts-more.js"></script>
<script src="https://code.highcharts.com/modules/exporting.js"></script>
 
<div id="container" style="min-width: 400px; max-width: 600px; height: 400px; margin: 0 auto"></div>

<script>
Highcharts.chart('container', {

    chart: {
        polar: true,
        type: 'line'
    },

    title: {
        text: 'Budget vs spending',
        x: -80
    },

    pane: {
        size: '80%'
    },

    xAxis: {
        categories: ['Sales', 'Marketing', 'Development', 'Customer Support',
                'Information Technology', 'Administration'],
        tickmarkPlacement: 'on',
        lineWidth: 0
    },

    yAxis: {
        gridLineInterpolation: 'polygon',
        lineWidth: 0,
        min: 0
    },

    tooltip: {
        shared: true,
        pointFormat: '<span style="color:{series.color}">{series.name}: <b>${point.y:,.0f}</b><br/>'
    },

    legend: {
        align: 'right',
        verticalAlign: 'top',
        y: 70,
        layout: 'vertical'
    },

    series: [{
        name: 'Allocated Budget',
        data: [43000, 19000, 60000, 35000, 17000, 10000],
        pointPlacement: 'on'
    }, {
        name: 'Actual Spending',
        data: [50000, 39000, 42000, 31000, 26000, 14000],
        pointPlacement: 'on'
    }]

});
</script>


以上です。





///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
製作物を発信できるアプリを公開したのでよかったら使ってください。
http://ruppish.com/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

5分でRailsアプリにMySQLを導入

f:id:sksksksksk:20170510232333p:plain

RailsアプリにMySQLを導入します。


サンプルコード
https://github.com/sagaekeiga/MySQL

MySQL2のインストー

gem 'mysql2'
bundle

MySQLの起動

mysqlを起動します。

$ mysql-ctl start

初期設定とデータベース・テーブルの作成

$ SET PASSWORD FOR 'root'@'localhost' = PASSWORD('パスワード'); #rootユーザーのパスワードを変更

$ CREATE DATABASE データベース名 DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci; #データベースの作成

$ GRANT ALL ON データベース名.* TO 'ユーザー名(任意)'@'localhost'; #ユーザー(任意)にデータベースの権限をrootユーザーから移譲

$ SET PASSWORD FOR 'ユーザー名(任意)'@'localhost' = PASSWORD('パスワード'); #ユーザー(任意)のパスワードをセット

・パスワードは任意です。最初のパスワードはrootユーザーのパスワードです。二番目のパスワードは新規で作成したユーザーのパスワードです。

・データベース名はなんでも構いません。わかりやすいものをつけましょう。

以下、補足です。

$ show databases; #データベース確認コマンド
$ SHOW TABLES; #テーブル確認コマンド
$ select user,host from mysql.user; #登録ユーザーの状況確認コマンド

私は以下のように設定しました。

$ mysql -u root#rootユーザーでログイン

mysql> SET PASSWORD FOR 'root'@'localhost' = PASSWORD('s19930528');

mysql>CREATE DATABASE sample_database DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci;                                                    

mysql> GRANT ALL ON sample_database.* TO 'sample'@'localhost';                                                                                            

mysql> SET PASSWORD FOR 'sample'@'localhost' = PASSWORD('secret');                                                                               

mysql> quit

アプリ側の設定

mysqlの準備は整いましたので、アプリ側の設定に移ります。

mysqlとアプリを連携させる為にはdatabase.ymlを設定する必要があります。



/config/database.yml

----削除----
default: &default
  adapter: sqlite3
  pool: 5
  timeout: 5000
----削除----

development:
    adapter: mysql2
    encoding: utf8
    database: sample_database
    username: sample
    host: localhost
    password: secret
    socket: /var/run/mysqld/mysqld.sock

test:
    adapter: mysql2
    encoding: utf8
    database: sample_database
    username: sample
    host: localhost
    password: secret
    socket: /var/run/mysqld/mysqld.sock

mysqlで設定した内容を反映させます。

ここで重要なのはmysql.sockの指定です。

mysql.sockの場所は以下のコマンドで確認できます。
mysqlからでた状態でコマンドを実行してください。

$ mysql_config --socket
/var/run/mysqld/mysqld.sock

アプリを作成し、接続できたかを確認

$ rails g model post title:text content:text
$ rake db:migrate

/db/seed.rb

Post.create!(title:  "テスト",
             content: "テスト")
$ rake db:seed
$ rails c
2.3.0 :001 > Post.all
  Post Load (0.4ms)  SELECT `posts`.* FROM `posts`
 => #<ActiveRecord::Relation [#<Post id: 1, title: "テスト", content: "テスト", created_at: "2017-05-08 11:06:37", updated_at: "2017-05-08 11:06:37"

できました!




///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
製作物を発信できるアプリを公開したのでよかったら使ってください。
http://ruppish.com/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

5分でUnicornを設定する。--Unicorn,Nginx

f:id:sksksksksk:20170510225653p:plain

前回は、NginxとUnicornの連携はsock名を同一にする、ということをお話しました。
それを踏まえて、進めていきます。

デモ

デモ
Git Hub

Unicornのインストー

gem 'unicorn'
bundle

Unicorn.rbファイルの作成

自動では作成されませんので手動で作成しましょう。
このファイルの中身がunicornの設定を行うものになります。



config/uncorn.rb

worker_processes 2
working_directory "/home/anime/deploy_sample/current" #appと同じ階層を指定

timeout 3600


listen "/var/run/unicorn/Nginxで設定した名前.sock" ★
pid "/var/run/unicorn/Nginxで設定した名前.pid"


stderr_path "/home/anime/deploy_sample/current/log/unicorn.log"
stdout_path "/home/anime/deploy_sample/current/log/unicorn.log"


preload_app true

これだけで済みます。
特に★の部分の名前には気をつけてください。



冒頭でも説明しましたが、
ここの名前を一致させることでNginxと連携させることができます。

working_directory "/home/anime/deploy_sample/current" #appと同じ階層を指定

unicornを起動するディレクトリを指定します。
currentの下にはアプリが存在します。


デプロイ時は/home/anime/deploy_sample/の下にアプリを置いてくれと設定したことを思い出してください。



今回はこのような設定を書きました。

worker_processes 2
working_directory "/home/anime/deploy_sample/current"

timeout 3600


listen "/var/run/unicorn/unicorn_deploy_sample.sock"
pid "/var/run/unicorn/unicorn_deploy_sample.pid"


stderr_path "/home/anime/deploy_sample/current/log/unicorn.log"
stdout_path "/home/anime/deploy_sample/current/log/unicorn.log"


preload_app true

さて、これをgitに入れてデプロイ、その後起動してみましょう。


$ git add .
$ git commit -m ユニコーン
$ git push
$ cap production deploy

起動
[anime@tk2-241-30026 current]$ bundle exec unicorn_rails -c config/unicorn.rb -E production -D
[anime@tk2-241-30026 current]$


できた!と、思ったら、production環境のシークレットキーを設定していなく、HTTP500エラーです。

シークレットキーの作成

$ bundle exec rake secret


生成されたキーをsecret.ymlに設定します。

config/secret.yml

production:
  secret_key_base: 生成されたキー


もう一度デプロイして結果を確認します。
デモ

できました。


再起動した時に以下のエラーが出ますが、これはすでにアプリケーションサーバが起動している為です。

master failed to start, check stderr log for details


ですので、以下のようにプロセスを殺して起動してください。
プロセスIDはその度に異なるので、適切に処置してください。
 

[anime@tk2-241-30026 current]$ ps -ef | grep unicorn                                                                              
anime    22414     1  0 00:18 ?        00:00:01 unicorn_rails master -c config/unicorn.rb -E production -D                                                                                  
anime    22417 22414  0 00:18 ?        00:00:00 unicorn_rails worker[0] -c config/unicorn.rb -E production -D                                                                               
anime    22420 22414  0 00:18 ?        00:00:00 unicorn_rails worker[1] -c config/unicorn.rb -E production -D                                                                                                                                                            
[anime@tk2-241-30026 current]$ kill -QUIT 22414
[anime@tk2-241-30026 current]$ bundle exec unicorn_rails -c config/unicorn.rb -E production -D




以上です。
いかがでしょうか?



参考
http://mlearning.ga/?p=37

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
製作物を発信できるアプリを公開したのでよかったら使ってください。
http://ruppish.com/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

5分でWebサーバを設定する。--Nginx,さくらのVPS

f:id:sksksksksk:20170510225141p:plain
NginxとUnicornの関係性ってよくわからないですよね。




アプリを動かすにはWebサーバの上でアプリケーションサーバを動かす必要があります。今回はWebサーバの設定を行います。



Nginxのインストールは完了しているものとします。

デモ

デモ

.confファイルの作成と編集

NginxとUnicornを連携する為には.sockファイル名を合わせる必要があります。
そのファイルは.confのファイルにあります。



まずは.confファイルのディレクトリへ移動しましょう

cd /etc/nginx/conf.d/

デフォルトで用意されている.confファイルがありますがこれを使うと、

一つのアプリにしか対応できなくなるので(厳密にはできますが管理が大変になります)、同じ階層に.confファイルを作成します。



.confの前の名前はなんでもいいです。



ちなみに私の.confディレクトリは以下のようにいっぱいあります。

$ ls
_default.conf.bak  bot.conf  default.conf  preliminary.conf  presentation.conf  sample.conf  text.conf  wordpress.conf  yurukyara.conf


今回は新しくファイルを作成します。

$ sudo touch deploy_sample.conf

このファイルを編集し、以下のコードを記載します。

upstream unicorn-unix-domain-socket-pre{ #①
    server unix:/var/run/unicorn/アプリで指定した名前.sock fail_timeout=0;
}

server {
    listen 80;
    server_name IPアドレス or ドメイン;
    root /home/anime/var/www/anime/public;

       ↓アクセスとエラーログを吐く場所を指定します。
    access_log  /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log;

      ↓設定は自由です。慣れたらカスタマイズしてください。
    proxy_connect_timeout       3600;
    proxy_send_timeout          3600;
    proxy_read_timeout          3600;
    send_timeout                3600;
    location / {
            proxy_pass http://unicorn-unix-domain-socket-pre; #①と名前を合わせてください。
    }
 }

ここで重要なのは2つです。
>|ruby|]
server unix:/var/run/unicorn/アプリで指定した名前.sock fail_timeout=0;
|


unicornを使う場合ですが、〜〜.sockの部分は名前を一致させてください。

この部分がwebサーバとアプリケーションサーバを連携させる核の部分です。

server_name IPアドレス or ドメイン;

ここにはサーバのIPか取得したドメインを挿入してください。

出ないとアクセスしてもアプリが表示されません。


Nginxの再起動


設定が終わったら、:wqで上書きを保存をして以下のコマンドでNginx設定を反映させましょう。

$ sudo service nginx restart


今回、私が作ったサンプルはこちらです。

upstream unicorn-unix-domain-socket-deploy_sample{
    server unix:/var/run/unicorn/unicorn_deploy_sample.sock fail_timeout=0;
}


server {
    listen 80;
    server_name candii.tk;
    root /home/anime/var/www/anime/public;

    access_log  /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log;

    proxy_connect_timeout       3600;
    proxy_send_timeout          3600;
    proxy_read_timeout          3600;
    send_timeout                3600;

    location / {
            proxy_pass http://unicorn-unix-domain-socket-deploy_sample;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
    }
 }

以上で、Webサーバの設定は完了です。
次は  unicornの設定をします。


参考

http://mlearning.ga/?p=32



///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
製作物を発信できるアプリを公開したのでよかったら使ってください。
http://ruppish.com/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////