20190411のRubyに関する記事は14件です。

21日目:H30秋基本情報技術者試験の問3データベース

前回のアウトプットから、だいぶ間が空いたが、今回から暫く、基本情報技術者試験問題に向き合う。

コンサートチケットの予約販売サイト、特にチケット販売サブシステムを用いる問題だった。
特に、今回のスクールの大成すべく、問3は実際にDBのみならず、Appも作成したい。
出典: 平成30年度 秋期 基本情報技術者試験(FE)試験区分 午後 問1 問3

DB仕様、ER図

Cacooを用いてみた。カラム名が冗長な気がする。
Entity Relationship Diagram.png

販売サブシステムの(引用、一部編集)

  1. コンサートの席種はS,A,Bがあり、コンサート毎にその価格と発売席数は異なる。
  2. 取り扱うコンサートの席種(S,A,B)毎の販売可能な席数を管理する。
  3. 会員が購入申込すると、一意な販売IDを生成して販売表にレコード追加
  4. 会員が支払いをすると、決済処理として決済表に追加。
  5. 決済期限の翌日に、決済期限を過ぎた販売表中のレコードと販売IDが同じレコードが決済表にない場合、購入申込は取り消され、バッチ処理として、決済表に当該販売IDを主キーとして決済表に決済日をnull、決済額を-1としてレコード追加
  6. バッチ処理は毎夜0~4時の販売サイトのシステムメンテナンス時に行う
  7. 購入申込席数が販売可能な席数を上回る場合は、販売終了と表示し、購入申込を受け付けない 等々。。。

※注意事項
コンサート席種のカラムが、商品詳細表と販売表に1つずつあり、重複していて気持ち悪いが、
試験問題がそうなっており、敢えてそうしてる模様なので、そのままにする。
その意図を反映するため、席種の商品詳細表側はinteger、販売表側はstringにしておく。

使用環境

  • ホストOS: Windows10 Home
  • 仮想環境OS: Ubuntu Bento/Bionic
  • Ruby:2.51
  • Rails: 5.2.2
  • DB: PostgreSQL

rails gコマ

今回もdeviseを利用することを、頭に入れておきたい。

terminal
rails new concert_ticket -d postgesql
Gemfile
# miniracerをコメントアウト
gem 'miniracer'
# authentication
gem 'devise'
terminal
bundle
database.yml
username: admin
password: 〇×△
host: localhost
terminal
rails db:create
terminal
# deviseのインストール
rails g devise:install
# Userモデルにdeviseを追加。モデルなので、単数形
rails g devise User name:string email:string point:integer

# 商品表と商品詳細表テーブルはscaffoldを用いる
rails g scaffold Concert concert_info:text concert_date:datetime
rails g scaffold ConcertDetail concert:references seat_grade:integer seat_price:integer tickets_total:integer

# Saleモデルの追加
# カラムが多い。販売表モデル 商品表外部キー 会員表外部キー 席種        席数         販売日        販売額        決済期限日         使用ポイント       
rails g model Sale concert:references user:references seat_grade:string seats_total:integer sale_date:datetime sales_total:integer payment_deadline:datetime used_point:integer

# 決済表モデルを追加
rails g model Payment sale:references payment_date:datetime payment_total:integer added_point:integer

関連付け

app/models/concert.rb
has_many :concert_detail
has_many :sale
app/models/concert_detail.rb
belongs_to :concert
app/models/user.rb
has_many :sale
app/models/sale.rb
has_one :payment
belongs_to :concert
belongs_to :user
app/models/payment.rb
belongs_to :sale

userテーブルにadminカラム追加

単に入れ忘れた。

terminal
rails g migration AddAdminToUser admin:boolean
/db/migrate/(timestanp)_add_admin_to_student.rb
class AddAdminToUser < ActiveRecord::Migration[5.2]
  def change
    add_column :students, :admin, :boolean,default: false
  end
end

validation追加

後からさらに追加していくと思うが、次のデータ入力の為に。
なお、ファイル中のvalidation前後のコードは省略。

app/models/user.rb
# name の空欄不可
validates :name, presence: true
# emailの空欄不可、一意指定
validates :email, presence: true, uniqueness: true
# emailの構成文字の大文字小文字の区別はしない
# あとで、正規表現込みのvalidation追加等するが、あとまわし。
validates :email, presence: { case_sensitive: false }
app/models/sale.rb
# 購入席数の空欄不可
validates :seats_total, presence: true
# 購入席数は4席まで。(試験問題には無いけど)
validates :seats_total, numericality: {less_than_or_equal_to: 4}

初期データ作成 (seeds.rb使用)

普段はコンソールからが多いが、rails tutorialをやって、seeds.rbの方が勝手が良かったので。
あと、gem Fakerは、SAOなど『遊び』があって、好きだが、rubyメソッドの勉強にならないので、今回はパス

ユーザ作成

カラムは氏名とemailアドレス

db/seeds.rb
# 管理者
User.create!(name: 'おりばー', email: 'ないしょ@gmail.com', password: 'ないしょ', admin: true)

# 一般ユーザ。とりあえず、20人作る。
20.times do |i|
  nm = (1..5).map { ('あ'..'ん').to_a[rand(20)] }.join
  em = ('a'..'z').to_a.shuffle[1..5].join

  User.create!(name: nm, email: "#{em}-#{i}@gmail.com", password: SecureRandom.base64)
end

商品表と商品詳細表の作成

(まだ足りないと思うが)リファクタリングの結果、コードが合わさったので、纏めて表示。
なお、qiita用に、一部コードの順序を変えてある、が、見づらい。

db/seeds.rb
# concert
# 20回分のコンサート、20組分のアーティストを作成
require 'active_support/all'

concert_name = %w[雅楽 令和 ジャズ ラスト ロック アニソン]
local = %w[東京 札幌 名古屋 大阪 広島 宮崎 台南 Cebu Perth]
artists = []

# 20回分のコンサート、20組分のアーティストを作成
(1..20).each do |n|
  # コンサート開催日として、期間s1 ~ s2までのランダムな年月日を作成
  s1 = Date.new(2019,5,31)
  s2 = Date.new(2020,3,31)
  s = Random.rand(s1..s2)

  # 出演アーティストをランダムで作成して、配列に入れる。
  # 作成した配列の並びをシャッフルし、先頭から1~5アーティストを取得し、カンマで繋げた文字列に。
  artists << (1..3).map { ('A'..'Z').to_a[rand(20)] }.join.to_s
  who_join = artists.shuffle.take(rand(5)+1).join('、')

  # 試験問題の"クリスマスコンサート2018 in 東京 出演:Xバンド・・・"の表記に沿ってあげる。
  infomation = "#{concert_name.sample}コンサート #{s.strftime('%Y')} in #{local.sample} 出演:#{who_join}"
  # コンサート情報の開催年と、開催日時が合致するようにした。
  Concert.create!(concert_info: infomation, concert_date: s.strftime('%Y-%-m-%-d'))

  con = Concert.find(n)
  (0..2).each do |i|
    # seat_price S > A > B
    # prices = [price_s , price_a , price_b]
    # capa= [sの席数、aの席数、bの席数]
    prices = [[40000, 35000, 30000], [28000, 25000, 23000, 19000], [18000, 15000, 13000, 11000, 9000]]
    capa = [rand(10..50), rand(100..500), rand(500..1000)]
    ConcertDetail.create!(concert:con,seat_grade:i, seat_price:prices[i].sample, tickets_total: capa[i-1])
  end      
end

actrive_recordを使おう

参照

初期データ投入

terminal
ralis db:seed

カラム名を変更しよう

思った。非常に分かりづらい。controller作成時に疲れそう。
会員表(User)テーブルはパス。あと、コードは一部省略

商品表(Concert)テーブル
現状カラム:コンサート情報:concert_info , 開催日時:concert_date
=>infomation , date

db/migrate/(timestanp)_create_concerts.rb
    create_table :concerts do |t|
      t.text :infomation
      t.datetime :date
      t.timestamps
    end

商品詳細表(ConcertDetail)テーブル
現状:席種:seat_grade , 販売価格:seat_price , 販売席数:ticket_total
=> grade , price , capacity

db/migrate/(timestanp)_create_concert_details.rb
create_table :concert_details do |t|
      t.references :concert, foreign_key: true
      t.integer :grade
      t.integer :price
      t.integer :capacity
      t.timestamps
    end

販売表(Sale)テーブル
席種:seat_grade、席数:seats_total、販売日:sale_date、販売額:sales_total、決済期限日:payment_deadline、使用ポイント:used_point
=> grade , number_of_seats , date , amount , payment_deadline , used_point
このテーブルは安易にリネームすると尚更分かりづらくなるので、注意した。
販売額amountとごっちゃにならず、席数に最適な短い訳が思いつかないので、一応英語に従った。、

db/migrate/(timestanp)_create_sales.rb
create_table :sales do |t|
      t.references :concert, foreign_key: true
      t.references :user, foreign_key: true
      t.string :grade
      t.integer :number_of_seats
      t.datetime :date
      t.integer :amount
      t.datetime :payment_deadline
      t.integer :used_point
      t.timestamps
    end

決済表(Payment)テーブル
決済日:payment_date、決済額:payment_total、付与ポイント:added_point
=> date , amount , added_point

db/migrate/(timestanp)_create_payments.rb
create_table :payments do |t|
      t.references :sale, foreign_key: true
      t.datetime :date
      t.integer :amount
      t.integer :added_point
      t.timestamps
    end

seeds.rbファイルもカラム名を使用しているので、一部変更

terminal
rails db:migrate:reset
rails db:migrate
rails db:seed

ER図を修正

modified.png

あとは、controllerとviewを弄っていくか。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Rubyのバージョン指定があるプロジェクトで良くあるエラーと対処法

rbenv global 2.3.0 

などで、プロジェクトに応じてバージョンを下げた際に起こるエラーに対しての対処法。

$ rails s
rbenv: rails: command not found

The `rails' command exists in these Ruby versions:
  2.3.0
  2.3.1
  2.6.2

こんなエラーが出てしまった・・・・・

対処法

gem i -v 5.1.3 rails

これでもだめ、、、、、、


Gemfile.lockにあるbundlerのバージョンに合わせて、インストール

$ gem install bundler -v 1.3.0

これで行けた!!
ただ、bundle installする時に、エラー文に沿ってGemfileの修正が必要。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

なぜあなたは初心者エンジニアから脱出できないのか

概要

タイトルの通り。それ以上でもそれ以下でもありません。
自分自身がRubyとRailsをゴリゴリやっていたのに初心者からいつまでも抜け出せないなぁというところから今に至ります。
とくに初心者から抜け出せない、だけど将来はエンジニアになりたい独学大学生に送りたい。

なぜ初心者か

ずっとRubyとRailsを書き、それにこだわってきたときは気づけなかったんですが、答えは単純。RubyとRailsは知ってても他のことは知らなかったから。
要はコンピューター内で動くプログラムは少しかじれてたけど、動く機械のことを知らなさ過ぎたから。
要はコンピューターサイエンスについてだったりWebの知識がない。(Webアプリを作りながらこの状況だからそりゃ脱出はできない。)

Railsにこだわりすぎた

Railsは一行でいろいろできすぎる。
すごくありがたいけど、そのせいで理解したフリで先へ先へとすすめてしまっている。(特にScaffoldはよくないと思ってる。)
知識があって省略するのと、知らないまま省略するのでは大きな差があるとめちゃめちゃに実感した。要はフレームワークはRailsに限らず便利でいいんだけど、ちゃんと同時に知識をつけないと無知のまま世界が広がることになる
作ってたり勉強している分には別にどうってことないけれど、仕事にするぞ、ってなったときに、苦労が半端じゃない。

言語の選び方が雑だった

正直最初は興味のある分野、言語をやっていいと思う。入りがつまらないとしんどいし、やめてしまうから。実際自分も最初はゲームを作りたくてUnityとC#を触ってキャッキャウフフしてた。
だけど、その後職業としてWEBエンジニアになりたいと勉強し始めた方法が失敗だった。RubyとRailsは学習コスト的に楽そうだと始めた。確かに楽だった。でも昔の人はいい事を言うもので、楽あれば苦あり。のちに苦が訪れた。
確かに手を動かして、ポートフォリオを作ってみたいなところは簡単に進む。だけれども小手先感が半端じゃない。それは当然で、あとから考えれば本当に必要な知識はついていなかったのだから

どうやったら脱出できるのか

正直なところ、今抜け出そうとしている最中だからわからない。ただ、WEBやコンピューターサイエンスの勉強をしていると、少しずつブラックボックスになっていたことはわかってきた
こうして一個一個知らないことをつぶすほかないと思う。正直面倒だし、地味だけどすごい大切
RubyやRailsも初心者がやっちゃダメというわけでなくて、ただちゃんと理解してますか?って考えながらやった方がいい。(あと個人的にはこれらはMVPがすぐほしいStart Upがやるといいのかなぁと思ったりもする。あとはちゃんと勉強できる人。)

終わりに

職業でエンジニアになりたい、という人以外は別に初心者から抜け出さなくてもいいと思う。大変だし。
ただ、もしエンジニアに何が何でもなる、というなら、手を動かすだけなのもダメな気がする。ちゃんと勉強して、なぜ動くか、どう動くかきっちり確認する。
車を運転する人は中でどう動作するか知らなくてもいいけど、作ったりメンテナンスする人が適当な理解はまずいに決まっている。ちゃんと勉強していった方が、遠回りかもしれないけど、必要なことだと思う。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

独学でプログラミングを学んでいる僕が使っているUdemy教材

テスターやネットワークのエンジニアとしての傍ら、12月よりプログラミングの独学を始めた僕が使っている教材について書いていこうと思う。僕が使っている教材について書いてきます。
その前に、独学よりプログラミングスクール行けばいいじゃんって言う人に向けて僕が何故独学しているのかを記しておこう。

(1)お金がない

色々音楽機材を買いすぎてお金がなかった(笑)今でも毎月5,6万円ほど払っています(笑)エンジニアとしてお金稼ぎます‼

(2)仮に通ってもどうせ独学しなければいけない気がした。

「ruby使ってtwitterに似たアプリ作ります!」位のレベル感で50万円近く払うのって結構自分的には嫌だったんだよね。
色々サービスがあるのに、勉強する環境を構築するのにここまでお金を支払う必要性があるのかと感じたっていう所がでかい。


+

やってきた・やっている教材

(1)【世界で30万人が受講】フルスタック・Webエンジニア講座(2017最新版)
https://www.udemy.com/share/1000IwBEYSd1dXRng=/

 HTML5,CSS3,Javascript,jQuery,Bootstrap4,Wordpress,PHP,MySQL,API,モバイルアプリ,Pythonなど結構詰め込んでいる。
 PCに環境を構築するためとか、プログラミングについての基本的な考え方について学ぶためには良いと思います。
 文系出身の僕には関数とか何で使うかちょっと理解できない所あったけど、JS,PHP,Pythonで何回か説明されるうちに分かるようになってきたところあるし。一方で、様々な分野を取り上げている弊害と言えますが、深く学ぶ分にはおススメ出来ないです。それぞれについてのUdemy教材を買うか、書籍を買っていきましょう!

(2)【JavaScript】作って覚える!未経験者が一流WEBエンジニアになる為のノウハウを完全網羅!
https://www.udemy.com/share/100ddoBEYSd1dXRng=/

 Javascriptについて。簡単なアプリプリ作成まで書いてあるので、初心者の方にとっては良いと思う。パーと一通り流し見して、後はオリジナルアプリ制作とか模倣みたいな感じで良いのでは。

(3)Learn to Program in Javascript: Beginner to Pro
https://www.udemy.com/share/1004oqBEYSd1dXRng=/

言語Javascript。英語教材、無料で購入した覚えがある。プログラミング自体英語だし、英語の方がテンポ感あって、無駄がなくて良いよね、と感じることはまれにあります。

(4)手を動かしながら2週間で学ぶ AWS 基本から応用まで
https://www.udemy.com/share/100taiBEYSd1dXRng=/
今勉強している。

(5)【最短30分でできる!】Laravel5.7入門: 初心者でも簡単! ブラウザだけでLaravelを使ったWeb開発!
https://www.udemy.com/share/100wDkBEYSd1dXRng=/
Larabelに興味あって、無料だったので、視聴。Paiza Cloud上でやっているから、別途環境構築は必要だけど、MVCを理解するのには、講座自体の時間も短いし良い気がする。

(6)実践Webサイトコーディング講座 | HTML5とCSS3を使って、カフェのサイトやWebメディアサイトを作ってみよう
https://www.udemy.com/share/1005eiBEYSd1dXRng=/
HTMLとCSSについて。photoshopを適宜使ってデザインを構築しているので、Webエンジニア向けというより、Webデザイナー入門といった感じの講座。初学者の段階では良いかも。講座に関しては、繰り返し説明している所が多々あるので、冗長に感じる人もいるかもしれない。

(7)ゼロからはじめる Dockerによるアプリケーション実行環境構築
https://www.udemy.com/share/100gMSBEYSd1dXRng=/

(8)フロントエンドエンジニアのためのReact・Reduxアプリケーション開発入門

(9)非エンジニアでも学べるPHP入門講座
https://www.udemy.com/share/10094kBEYSd1dXRng=/

(10)8 Beautiful Ruby on Rails Apps in 30 Days & TDD - Immersive
https://www.udemy.com/share/10017ABEYSd1dXRng=/

(11)初めてでもできるWordPressで作る人気の出るホームページ作成
https://www.udemy.com/share/100k3ABEYSd1dXRng=/

(12)よくわかるRuby on Rails入門-RubyとRailsを基礎から学びWebアプリケーションをネットに公開しよう
https://www.udemy.com/share/100AcWBEYSd1dXRng=/

(13)フルスタックエンジニアが教える 即戦力Railsエンジニア養成講座
https://www.udemy.com/share/1003s4BEYSd1dXRng=/

まだ書きかけなので、その適宜リライトしながら投稿していこうと思う。

下記のようになれるように頑張っていこうと思います。では。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

#python で #ruby の Hash#merge 的なことをやる ( 複数のディクショナリをマージする )

{**{"a" : 1}, **{"b" : 2}}
# {'a': 1, 'b': 2}
{**{"a" : 1}, **{"a" : 2}}
# {'a': 2}
 {**{"a" : 1}, **{"b" : 2}, **{"b" : 3, "c" : 4 }}
# {'a': 1, 'b': 3, 'c': 4}

Original by Github issue

https://github.com/YumaInaura/YumaInaura/issues/1180

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[学習用]Rails5にてCarrierWaveでサムネイル画像と最大画像と拡張子の制限をしたアプリを作る

画像アップアプリ.jpg
※Bootstrap入れて調整したもの。

スムーズにうまく行ったのでメモ。

Ralis5
Ubuntu16

GemFileに追加する

gem 'carrierwave'
gem 'mini_magick'

コマンド入力

$ bundle
$ rails g scaffold upload image:string content:text name:string
$ rails g uploader images
$ rails db:migrate

必要事項の追記

Scaffoldで作ったuploadのmodelsに追記

app/models/upload.rb
class Upload < ApplicationRecord
  mount_uploader :image, ImagesUploader
end

CarrierWaveのファイルに追加

app/uploaders/images_uploader.rb
class ImagesUploader < CarrierWave::Uploader::Base
  # Include RMagick or MiniMagick support:
  # include CarrierWave::RMagick
  include CarrierWave::MiniMagick

  # Choose what kind of storage to use for this uploader:
  storage :file
  # storage :fog

  # Override the directory where uploaded files will be stored.
  # This is a sensible default for uploaders that are meant to be mounted:
  def store_dir
    "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
  end

  # 許可する画像の拡張子
  def extension_whitelist
    %w(jpg jpeg gif png)
  end

  # サムネイル画像
  version :thumb do
    process resize_to_fill: [80, 80]
  end

  # Maxサイズ
  version :content do
    process resize_to_limit: [640, 640]
  end
end

Viewsファイルを修正・追加

_horm.html.erb

app/views/uploads/_horm.html.erb
  <div class="field">
    <%= form.label :image %>
    <%= form.file_field :image %>
  </div>

show.html.erb

app/views/uploads/show.html.erb
<%= image_tag @upload.image_url(:content) if @upload.image.present? %>

index.html.erb

app/views/uploads/index.html.erb
<table>
  <thead>
    <tr>
      <th>Image</th>
      <th>Content</th>
      <th>Name</th>
      <th colspan="3"></th>
    </tr>
  </thead>

  <tbody>
    <% @uploads.each do |upload| %>
      <tr>
        <td>
          <%= image_tag upload.image_url(:thumb) if upload.image.present? %>
        </td>
        <td><%= upload.content %></td>
        <td><%= upload.name %></td>
        <td><%= link_to 'Show', upload %></td>
        <td><%= link_to 'Edit', edit_upload_path(upload) %></td>
        <td><%= link_to 'Destroy', upload, method: :delete, data: { confirm: 'Are you sure?' } %></td>
      </tr>
    <% end %>
  </tbody>
</table>

これで画像のサムネイル投稿、最大サイズの制限、投稿拡張子の制限ができる。

サムネイルには

ImageMagick が必要なのでサーバーに入れてない場合は入れる。

画像にリンクをつける

app/views/uploads/index.html.erb
          <%= link_to (image_tag upload.image_url(:thumb) if upload.image.present?), upload %>

または

app/views/uploads/index.html.erb
          <%= link_to upload do %>
            <%= image_tag upload.image_url(:thumb) if upload.image.present? %>
          <% end %>

サムネイル画像

imges1.jpg
完成直後のアプリ

詳細ページの最大画像

image2.jpg
完成直後のアプリ

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

sub!がnilを返すのはパターンマッチが発生しなかった場合である

公式ドキュメントによると、「sub! は通常 self を変更して返しますが、 置換が起こらなかった場合は nil を返します。」とある。
が、それだと説明できない挙動がある。

a='abd';a.sub!('abd','abc') # => 'abc'
a='abc';a.sub!('abc','abc') # => 'abc'
a='abc';a.sub!('foo','abc') # => nil

この例1-2で、置換が発生していないにもかかわらずselfが返ってきている。
これは「パターンマッチが発生しなかった場合はnilを返す」と解釈すると説明がつく。

特に正規表現を使う場合、この誤解は致命傷だと思う。

a='abd';a.sub!(/a\w+/,'abc') # => 'abc'
a='abc';a.sub!(/a\w+/,'abc') # => 'abc'

この例2-2が「pattern /a\w+/がマッチした結果が replace と一致するため」nilを返すという誤解を、私は10年以上持ち続けていた。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Ruby on Rails で動画投稿機能を実装してみた

基本的には画像の投稿と同じ

1.carrierwaveの導入
2.カラムを追加
3.モデルにアップローダを追加
4.コントローラにパラメータ追加
5.フォームの作成
6.ビューに表示

1.carrierwaveの導入

Gemfile
gem 'carrierwave'

Gemfileに追記↑

ターミナル
$ bundle install

rails s 再起動忘れないように...

ターミナル
$ rails g uploader video

carrierwave generatorを使用しビデオをアップロードするためのアップローダを作成する。
app/uploaders/video_uploader.rb が生成されていることを確認。

2.モデルでカラムを追加

ターミナル
$ rails g migration add_video_to_post video:string
# rails g migration add_カラム名_to_モデル名 カラム名:string
ターミナル
$ rake db:migrate

3.モデルにアップローダを追加

tweet.rb
class Tweet < ApplicationRecord
  mount_uploader :video, VideoUploader
# mount_uploader :カラム名, carrierwaveの設定ファイルのクラス名
end

4.コントローラにパラメータ追加

tweets_controller.rb
class TweetsController < ApplicationController

#(略)

  def new
    @tweet = Tweet.new
  end

  def create
    @tweet = Tweet.create(tweet_params)
  end

  private
  def tweet_params
    params.require(:tweet).permit(:video)
   #params.require(:モデル名).permit(:カラム名)
  end

end

5.フォームの作成

new.html.haml
 = form_for @tweet do |f|
    = f.file_field :video
    = f.submit "送信"

6.ビューに表示

index.html.haml
= video_tag tweet.video_url.to_s,loop: true, controls: true,;

#loop: true loop処理
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

RailsアプリをHeroku上で、NginxとUnicornで動かす方法

unicornの導入

Gemfile
gem 'unicorn'

追加し、bundle install

Procfileも編集するが、後でnginxの設定をするために、ここではやらない。

※参考サイト
https://workabroad.jp/posts/1225

nginxの導入

※参考サイト
https://github.com/heroku/heroku-buildpack-nginx
あとは、このサイトのSetupに沿って進めていく。

herokuにデプロイできたら、下記コマンドで確認。

heroku logs -t

約2日間、分からずに積んだため、このようにまとめました。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

#GCP ( Google Cloud Platform ) の Google翻訳API で #MarkDown を翻訳するとスタイルが崩れてしまうので #ruby gem で一旦 #HTML 変換してから Markdown に逆変換する #shell コマンドの例

Prepare

  • sudo gem install reverse_markdown
  • sudo gem install redcarpet
  • install gcloud
  • setting Google Translate API on GCP

tmp/example.md

```
# あまがみヘッダー

*そうだ京都行かない。*

## うずらの卵

- 神風パラダイス
- おおむね大丈夫です

```
print('孫氏や老師の楽園')
print('一寸先はホタテ')
```

~/.secret/google-service-credential.json

your GCP service account file json

get-token.sh

GOOGLE_APPLICATION_CREDENTIALS=~/.secret/google-service-credential.json gcloud auth

translate.sh

#!/usr/bin/env bash

basedir=$(dirname "$0")

TOKEN=$("$basedir"/get-token.sh) \
  "$basedir"/translate.py | \
  jq --raw-output '.data.translations[].translatedText'

translate.py

Google Translate API では resouce として html 形式を指定することが出来る (デフォルトはこちら)

Method: translate  |  Cloud Translation API  |  Google Cloud

#!/usr/bin/env python3

# -*- coding: utf-8 -*-

import os, sys, requests, json, fileinput, re

#resource_message = ''
#for text in sys.stdin.readlines():
#  resource_message += re.sub(r'\\n', "\n", text)

resource_message = sys.stdin.read()

from_language = os.environ.get('FROM') if os.environ.get('FROM') else 'ja'
to_language = os.environ.get('TO') if os.environ.get('TO') else 'en'
translate_format = os.environ.get('FORMAT') if os.environ.get('FORMAT') else 'text'

data = {
  'q': resource_message,
  'source': from_language,
  'target': to_language,
  'format': translate_format
}

url = 'https://translation.googleapis.com/language/translate/v2'
token = os.environ['TOKEN']

headers = {
 'Authorization': 'Bearer {}'.format(token),
 'Content-Type': 'application/json',
}

res = requests.post(url, headers=headers, json=data)

print(json.dumps(res.json()))


exe

  • テキストは翻訳され、コードは翻訳されていないのが分かる
  • PHP / Github スタイルのバッククォート複数個での コードブロック記法が、半角スペース4個でのベーシック記法に崩れてしまっているが、良い ruby gem や python module などが見つからなかったのでとりあえず放置
$ redcarpet --parse=fenced_code_blocks ./tmp/example.md | FORMAT=html ./translate.sh | reverse_markdown

ただしGoogle翻訳時にコードブロック内の改行が崩れてしまうようなので、独自対応する必要があるかもしれない

# Amagami header 

_Yes I can not go to Kyoto._

## Quail egg 

- Kamikaze Paradise 
- Mostly okay 

     print('孫氏や老師の楽園') print('一寸先はホタテ') 


Original by Github issue

https://github.com/YumaInaura/YumaInaura/issues/1178

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ポートが既に使われているエラーの場合は、不要なポート番号を削除する。

Address already in use... のエラー

Railsにて$rails sを実行時、下記のようなERRORが発生した。

$ rails s
.
.
.

/Users/kikkutonton/.rbenv/gems/2.6.0/gems/puma-3.12.1/lib/puma/binder.rb:273:in `initialize': Address already in use - bind(2) for "::1" po
rt 3000 (Errno::EADDRINUSE)

エラー原因

エラー文通り、localhost:3000のポートが既に他のポートに使われていることが原因のエラー。

対処法

不要なポートを削除する。

使われているポート番号を確認

$sudo lsof -i:3000
COMMAND     PID  USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME
com.docke 17067 kikkutonton   22u  IPv4 0xeexxxxxxxxxxxxxx      0t0  TCP *:hbci (LISTEN)
com.docke 17067 kikkutonton   23u  IPv6 0xeeyyyyyyyyyyyyyy      0t0  TCP localhost:hbci (LISTEN)

使用ポートを削除

//PID番号
$sudo kill xxxx 
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

#ruby や #python で #markdown を #HTML に #shell のコマンドで変換できるモジュール四種類の簡単な結果比較

Install

gem install [module_name]

or

pip install [module_name]

markdown text

# header 

*あ*

## header2

- list
- list

```
print('ok')
print('yes')
```

ruby redcarpet

$ redcarpet  ./tmp/markdown

single quote HTML escaped

<h1>header</h1>

<p><em></em></p>

<h2>header2</h2>

<ul>
<li>list</li>
<li>list</li>
</ul>

<p><code>
print(&#39;ok&#39;)
print(&#39;yes&#39;)
</code></p>

enable multiple backquotes code block style

$ redcarpet --parse=fenced_code_blocks ./tmp/markdown
<h1>header</h1>

<p><em></em></p>

<h2>header2</h2>

<ul>
<li>list</li>
<li>list</li>
</ul>

<pre><code>print(&#39;ok&#39;)
print(&#39;yes&#39;)
</code></pre>

ruby karmdown

$ kramdown ./tmp/markdown

Indented

<h1 id="header">header</h1>

<p><em></em></p>

<h2 id="header2">header2</h2>

<ul>
  <li>list</li>
  <li>list</li>
</ul>

<p><code>
print('ok')
print('yes')
</code></p>

python markdown

$ python3 -m markdown ./tmp/markdown
<h1>header</h1>
<p><em></em></p>
<h2>header2</h2>
<ul>
<li>list</li>
<li>list</li>
</ul>
<p><code>print('ok')
print('yes')</code></p>

python markdown2

$ python3 -m markdown2 ./tmp/markdown
<h1>header</h1>

<p><em></em></p>

<h2>header2</h2>

<ul>
<li>list</li>
<li>list</li>
</ul>

<p><code>
print('ok')
print('yes')
</code></p>

Original by Github issue

https://github.com/YumaInaura/YumaInaura/issues/1174

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Daruがわかりにくいのはだいたいrecodeのせい

RubyにはDaruというデータフレームがある。
イテレータまわりがわかりにくいと思ったら、半分ぐらいrecodeのせいである。

recode メソッド

これが、Daru::Vectorや、Daru::DataFrame において map と同じ働きをするメソッドである。引数に :row :vector :column をとる。

以上

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

LINEBOT + RailsでWikipediabotを作ってみました。

はじめに

Railsの勉強のためにLINEBOTを作ってみました。
内容はLineメッセージに調べたい単語を送信すれば、Wikipediaの概要とurlを返すものです。

LineBotの設定

下記のリンクを参考に設定しました。ありがとうございます。

今更ながらRails5+line-bot-sdk-ruby+HerokuでLineBot作成してみたら、色々詰まったのでまとめました。

Wikipediaの情報取得

Wikipediaの情報を取得するためにGemがあったので、そちらを利用しました。
wikipedia-client

Gemgile
gem 'wikipedia-client'
$ bundle install

Controllerを編集

linebot_controller.rb
class LinebotController < ApplicationController
  require 'line/bot'
  require 'wikipedia'

  # callbackアクションのCSRFトークン認証を無効
  protect_from_forgery :except => [:callback]

  def client
    @client ||= Line::Bot::Client.new { |config|
      config.channel_secret = ENV["LINE_CHANNEL_SECRET"]
      config.channel_token = ENV["LINE_CHANNEL_TOKEN"]
    }
  end

  def callback
    body = request.body.read

    signature = request.env['HTTP_X_LINE_SIGNATURE']
    unless client.validate_signature(body, signature)
      head :bad_request
    end

    events = client.parse_events_from(body)

    events.each { |event|
      if event.message['text'] != nil
        # LINEで送られてきた文書を取得
        word = event.message['text']
        # 日本語版Wikipediaを設定
        Wikipedia.Configure {
          domain 'ja.wikipedia.org'
          path   'w/api.php'
        }
      end

      # wikipediaから情報取得
      page = Wikipedia.find(word)

      # 概要とURLを返す
      response = page.summary + "\n" + page.fullurl

      case event
      # メッセージが送信された場合
      when Line::Bot::Event::Message
        case event.type
        # メッセージが送られて来た場合
        when Line::Bot::Event::MessageType::Text
          message = {
            type: 'text',
            text: response
          }
          client.reply_message(event['replyToken'], message)
        end
      end
    }

    head :ok
  end
end

あとはherokuにデブロイして、動作確認すれば完成です。

動作イメージ

こんな感じで概要とURLを返してくれるようになります。
2019-04-11 0.53のイメージ.jpg

まとめ

簡単なまとめになりましたが以上になります。
結構簡単に実装できました。APIと組み合わせれば色々使えるんじゃないかなと思いました。
何かご指摘等がございましたらコメントよろしくお願いします。

参考サイト

今更ながらRails5+line-bot-sdk-ruby+HerokuでLineBot作成してみたら、色々詰まったのでまとめました。

Web APIとは? (LINE bot API・グルナビAPI)

wikipedia-client

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む