firebaseを使った静的サイトのデプロイ手順

こんにちは!kossyです!





さて、今回はfirebaseへの静的サイトのデプロイ手順をブログに残したいと思います。
ドットインストールのレッスンを参考にデプロイをしたのですが、驚くほど簡単にできました。

環境
MacOS
Node.js推奨版



firebaseを使ってのデプロイには、Node.jsをインストールする必要があるので、
インストールをしていない方は、
https://nodejs.org/ja/
上記のサイトから推奨版をインストールしてください。

確認方法は、ターミナルで

$ node -v
  => v 10.7.0

バージョンが表示されればインストールされています。

Firebaseは、Googleが提供しているサービスで、いわゆるMBaas / BaaSと呼ばれているものです。
Webアプリに用いられることが多いですが、静的サイトのデプロイもできます。

firebase.google.com




firebase デプロイ手順

アカウント作成

firebase.google.com
上記サイトからconsoleへのログインができます。


まずは左上のログインをクリックしてログインします。
Googleアカウントをお持ちの方はそのアカウントでログインできます。
f:id:kossy-web-engineer:20180930185627p:plain



ログインができたら、コンソールにアクセスします。
f:id:kossy-web-engineer:20180930194055p:plain



コンソールの新しいプロジェクトを作成をクリックし、
プロジェクトを作成します。
f:id:kossy-web-engineer:20180930194359p:plain
プロジェクト名を入力する欄があるので、プロジェクト名を入力します。
その後、アナリティクスの地域がデフォルトではアメリカ合衆国になっているので、
日本に変更します。ロケーションはus-centralを選択します。
一番下のチェックボックスにチェックをし、プロジェクトを作成をクリックします。
その後、次へというボタンが表示されるので、そちらをクリックします。


f:id:kossy-web-engineer:20180930194651p:plain

上記のような画面が表示されれば成功です。





ローカル側での準備

作ったプロジェクトと同じ名前のフォルダを任意のディレクトリに作成し、
デプロイしたいフォルダをコピー&ペーストします。

中のフォルダはpublicに名前を変更します。

publicフォルダの中身は全てデプロイされます。

firebase-toolsのインストール

ターミナルからfirebaseの機能を利用できるようにするfirebase-toolsをインストールします。

$ sudo npm install -g firebase-tools
PASSWORD: (PCのPASSWORDを入力)

firebase-toolsがインストールできたか確認

$ firebase -V

ログイン

$ firebase login
=> Allow Firebase... (Y/n)
Y又はenterキーを押す。
$firebase init

上から4番目のホスティングを選択→エンターキーを押し、
前に作ったプロジェクトを選択しエンターキー。
さらにエンターキーを押す。
SPAにするのはNo。
ファイルの上書きはだめなのでNで対応。

デプロイしたいアプリのディレクトリ $sudo firebase deploy


これで静的サイトのデプロイは終了です。

銃・病原菌・鉄がめっちゃ面白かった

こんにちは!kossyです!



さて、今回は銃・病原菌・鉄という本のレビューを読み漁って、
アホほど面白かったので、ブログに残したいと思います。



スーパーざっくりまとめてしまうと、
Q. なぜスペイン人のピサロは圧倒的に少ない人数でインカ帝国を征服できたのか
A. スペイン人が南米人が持ってなかった銃・病原菌・鉄を持っていたから



タイトルにある銃・病原菌・鉄はここで登場するのですが、

Q. ではなぜスペイン人(ユーラシア大陸の白人)は銃・病原菌・鉄をいち早く持てたのか
この問いに対して、人類の生誕から論理を展開していくという本になってます。

結論を先に申し上げると、
1. たまたま住んだ場所が大量の人を養うことができる栽培に適した植物を育てやすい場所だった
2. たまたま住んだ場所に家畜化しやすい動物が住んでいた
3. 大陸が横つながりで緯度が近い(環境が似通っている)
A つまり白人が銃・病原菌・鉄をいち早く持てたのは遺伝子の優劣ではなく環境要因

って感じです。


本の内容をかいつまんで要約すると、


・人類の広がりが縦に広がるよりも横に広がる方が早かったのは、
緯度が変わると気温・昼夜が変わり、適応するのに時間がかかるようになるから
=> 人の移動や技術の伝播は水平方向は早いが、縦方向には遅い

アメリカ大陸、オセアニア大陸の動物は狩りの技術が進歩した人間に狩り尽くされた
=> 一方、ユーラシア、アフリカでは、700万年前からゆっくりと
人類と主に“疑り深くて人間を恐れる”個体 が淘汰の末生き残り、家畜に向く動物種が残った

・早くから人類が定住したユーラシアは、時間的ボーナスがあった
=> トライアンドエラーの品種改良や、発明、発見などは、
それにどれだけの時間がかけられるかということが重要

・狩猟採集生活から農耕生活に変わったのは、増えた人口を養うため

・栽培に適している植物
=> 小麦や大麦、エンドウマメのように、種がサヤからこぼれたりポロポロ地面に落ちたりしない
こぼれないというのは種を手に入れる際だけでなく、収穫の便利さにも関わってくる

ユーラシア大陸で早くから農耕が始まった理由
=> 地中海性気候で、湿潤な冬と長くて暑く乾いた夏だったため、
そのため、一年草の穀類、豆類の原種がたくさん生息していたことで、種の選別ができた

・なんで家畜は牛、豚、山羊、羊、馬、(あとラクダ)くらいなのか
=> 家畜の条件をクリアしているのが上記くらいだから

・家畜の条件
=> 草食性で、またその餌に極端な偏りがない
=> 成長速度がはやい
=> 繁殖行動に特別な儀式が必要ない
=> 気性が荒くなく穏やか
=> パニックになりにくい
=> 序列性のある集団を形成する

・なんで南米大陸では動物の家畜化が成されなかったのか
=> 狩猟採集の暮らしをしているうちに動物を狩りつくしてしまったから

・病原菌を持てたのは、家畜を飼っていたから
=> 天然痘は牛が媒介、インフルエンザは豚や馬が媒介、風疹や麻疹も家畜由来
これらは一度かかれば抗体ができる

南米大陸の住人は病原菌への耐性を持っていなかった
=> スペインに攻められたときに持ち込まれた病原菌で戦いで死ぬより多くの人が死んだ



この本は2chの創設者として知られるひろゆき氏もオススメしてました。
blogos.com
このサイト内で紹介されてる本も面白そうなので読んで見ようかなーと思ってます。


本のタイトルは厳つくて怖いのですが、内容は目を見張るものがあると思います。
結局は人間は環境が全て、ということを教えてくれます。
文庫本も出てるみたいなので、ネットのレビュー見るだけじゃなくてちゃんと買って読みたいと思ってます。


参考にさせていただいたサイト
togetter.com
note.mu

ソフトバンクがIPアドレスなしで通信できる技術を商用化

こんにちは!kossyです!




こんなニュースが出てました。
www.softbank.jp


以下、引用です。


ソフトバンク株式会社(以下「ソフトバンク」)は、IoTデバイス向けのLTE通信規格であるNB-IoTにおいて、3GPP※1で新たに規格化されたNIDD(Non-IP Data Delivery)技術の商用環境での接続試験に、世界で初めて※2成功しました。これを受けてサービス事業者を募り、商用環境での試験サービスの提供を開始します。

NIDDは、IoTデバイスIPアドレスを割り当てることなくデータ通信を行うことができる新しい通信技術で、通信にインターネットプロトコルを使わないことにより、IoTデバイスを狙った悪意のある攻撃を受けるリスクが低く、高セキュリティーなネットワークを構築することができます。また、従来のデータ通信時に付加的に必要となるヘッダー情報などのデータが削減されることにより、通信に必要な電力を抑えられ、バッテリーを長持ちさせることができるほか、より広いエリアをカバーすることが可能となります。さらに、各サービスプロバイダーが提供するIoTプラットフォームや外部アプリケーションサーバーと閉域網で接続することにより、エンド・ツー・エンドで高セキュリティーネットワークを構築することも可能となります。

IPアドレス無しでどうやって通信するんでしょうか、、、

まぁネットに繋がっているだけで攻撃のリスクはあるわけなので、
閉域網で通信できればマルウェアの侵入もほぼ防げる(閉域網の利用者側に悪意がある場合はたぶん無理)と思うので、
IoT技術のセキュリティ面の課題はある程度改善の方向に前進したのではないでしょうか。


IoT界隈の今後の動きに注目したいですね。




参考にさせていただいた記事
・IoTのセキュリティ課題について
IoTのセキュリティ課題 | マルウェア情報局
IPアドレスとセキュリティ
IPアドレスとセキュリティ – ネットワークの仕組み - 道すがら講堂




* 筆者はIoTに関してはど素人です

Railsにおけるmemberとcollection

こんにちは!kossyです!



日経平均株価が久しぶりに24000円台に回復したようです。



ここ数年はだいたい9-11月に回復する傾向がありますね。
2014年には黒田日銀総裁の追加緩和で上昇、
2016年にはトランプさん当選で上昇、
2017年には選挙での与党の圧勝などで上昇、
というような感じですね。

ちなみに下落するのは2月が多いです。






さて、今回はrailsにおいて、7つのアクション以外のアクションをルーティングで定義するときに使う、
memberとcollcectionの使い方について、ブログに残したいと思います。


環境
Ruby 2.5.1
Rails 5.1.6
MacOS





7つのアクションってなに?
memberとcollectionの説明に移る前に、7つのアクションについて解説してみます。

7つのアクションの役割分担はこちらの記事が詳しかったです。
qiita.com


railsでは、ルーティング定義の際に、

config/routes.rb

get 'URL', to: 'コントローラ名#アクション名'

と記述するか、

config/routes.rb

resources : コントローラ名

と記述すると、ルーティングが設定されます。

ここでresourcesでルーティングを定義すると、
index, new, create, show, edit, update(put/patch), destroyの8つのパスが自動的に定義されます。

rails routesで確認してみましょう。

config/routes.rb

resources :products


$ rails routes

products     GET    /products(.:format)          products#index
             POST   /products(.:format)          products#create
new_product  GET    /products/new(.:format)      products#new
edit_product GET    /products/:id/edit(.:format) products#edit
product      GET    /products/:id(.:format)      products#show
             PATCH  /products/:id(.:format)      products#update
             PUT    /products/:id(.:format)      products#update
             DELETE /products/:id(.:format)      products#destroy

上記のようにアクションが生成されました。




他のアクションはどうすんの?

7つのアクションについては自動で生成されるので構いませんが、
それ以外のアクションはどのように定義すればいいのでしょうか。

ここで登場するのが、memberとcollectionです。

memberの使い方
member は特定のデータ(users/:id/likesのように:idが入るアクション)に対するアクションに利用します。

以下のルーティングはmemberを使ったあるユーザーのお気に入り一覧のルーティングです。

resources :users, only: [:likes] do
    member do
      get 'likes'
    end
  end

$ rails routes
likes_user GET /users/:id/likes(.:format) users#likes

これをmemberを使わずに書くと、

get 'users/:id/likes', to: 'users#likes'

$ rails routes
GET /users/:id/likes(.:format) users#likes

となります。これでも問題なく動作するのですが、
prefixが自動で生成されないという事象が発生します。
Railsではprefixを用いたり、各種オプションを用いて可読性の高いコードを書くことがよしとされているので、
便利なオプションやメソッドはガンガン使いましょう。


collectionの使い方
対してcollectionですが、
collectionはユーザー検索や商品検索等、全てのデータを対象とするアクションに利用します。

以下のルーティングはcollectionを使った商品検索のルーティングの例になります。

config/routes.rb

resources :products, only: [:show] do
    collection do
      get 'search'
    end

$ rails routes

search_products GET /products/search(.:format) products#search

上記のようなprefixが定義されます。


とりあえず便利なオプションは使っとけ!



getやpostだらけのルーティングでは可読性も下がってしまうので、
resourcesやmember、collectionを用いて、読みやすいルーティングを定義するように心がけます、、、


参考にさせていただいたサイト
Railsで自動生成以外のrouteを追加する - Qiita
【Ruby on Rails】ルーティング member と collection の違い - きゃまなかのブログ
collectionとmemberのルートのちがい rails - Prog-me.

railsバリデーション正規表現集

こんにちは!kossyです!


今日の気になったニュースはこちら
news.yahoo.co.jp

原油価格の高騰は後々自分たちの財布を痛めつけることになるので今後の動向に注意したいです。







さて、今回は正規表現のサンプルを見つけたのでブログで紹介できればと思います。


こちらです。
Railsのバリデーション用正規表現集 · GitHub


電話番号の項は少し簡素な表現になっていると思いましたので、
akinov.hatenablog.com

こちらのブログが参考になりました。

Railsで日本語でのバリデーションエラーメッセージの出し方

こんにちは!kossyです!

日本株式の売買単位の統一のニュースが出てました。

昔から株持ってる方なんかは、自分の株数が減ってると言って怒る方もいるんですよね。。。
1000株→100株になれば株数は減っても株価は10倍になるわけですから。(詳しくは「株式併合」でググってみてください)
まぁ、それぐらい自分の資産に興味ないってことなのかもしれませんが。





さて、今回はRailsで日本語でのエラーメッセージの出し方をブログに残したいと思います。



環境
Rails 5.1.6
Ruby 2.5.1
haml
MacOS Yosemite





まずは日本語化対応

i18nというプラグインrailsに入っているかどうかを

アプリ名 $ bundle list

コマンドで確認します。

その中に、

* i18n (1.1.0)
(バージョンは環境によって異なります)

とあれば大丈夫です。


各モデルにバリデーションを設定
バリデーションの設定の仕方については
下記の記事が詳しかったです。
qiita.com




application.rbを編集
config/application.rbに、

class Application < Rails::Application
  config.i18n.default_locale = :ja
  config.i18n.load_path += Dir[Rails.root.join('config', 'locales', '**', '*.yml').to_s]
end

と記載します。



ja.ymlファイルをgithubからダウンロード
github.com

ファイルの置き場所は、config/locales下に置きます。


htmlへの記載

エラーメッセージを表示したいファイル
    %ul
    - @変数名.errors.full_messages.each do |message|
      %li= message

errors.full_messagesで全てのエラーメッセージを配列で取得します。
そして、each文を用いて全て表示するようにしています。


ja.ymlファイルの編集

ja:
  activerecord:
    models:
      モデル名: "モデル"
    attributes:
      モデル名:
        カラム名: 日本語のカラム名
(以下は例)
ja:
  activerecord:
    models:
      review: "レビュー"
    attributes:
      review:
        bookname: "本のタイトル"
        language: "言語"
        level: "レベル"
        content: "本文"

日本語化したいモデルのカラム名を記述しています。



開発環境で確認!
英語表記だった箇所が日本語になっていれば対応完了です。


参考にしたサイト
Railsで日本語化対応にする方法 - Qiita
【Rails】バリデーションのエラーメッセージを表示する - イソップブログ
[初学者]Railsのi18nによる日本語化対応 - Qiita

XSS対策とはなんぞや

こんにちは!kossyです!


なんぞやシリーズ第3弾ということで、XSS対策について、
参考になったサイトをブログにまとめてみたいと思います。



そもそもクロスサイトスクリプティングって?

クロスサイトスクリプティング - Wikipedia



対策ってどうすればいいの?

cybersecurity-jp.com




Railsの場合は?
qiita.com



Railsの場合は基本的には安全のようですが、
JavaScriptを使ってユーザー入力をさせる箇所や、html_safeを使う箇所は
安全性を担保できないようです。

だいぶ手抜きエントリで申し訳ないです。。。

いいねの削除機能実装するときはmethod: :deleteにする必要があった話

こんにちは!kossyです!


いいね周り実装する時に、
めっちゃハマったのでブログに残したいと思います。。。



話を簡潔にするために一部ロジックを省いて記載しています。











前提情報


User, Product, Likeというモデル定義で、

User has_many products
User has_many likes
Product has_many likes

という構成にしていました。

また、投稿詳細画面からいいねの登録、削除ができるように実装しました。


いいね周りのコードは、

config/routes.rb

Rails.application.routes.draw do
  devise_for :users

  post "likes/:product_id/create" => "likes#create"
  post "likes/:product_id/destroy" => "likes#destroy"

  resources :products, only: [:show]
end


/views/products/show.html.haml

  = link_to("お気に入りから削除", "/likes/#{@product.id}/destroy", method: :post)
  = link_to("お気に入り登録", "/likes/#{@product.id}/create", method: :post)


/controller/products_controller.rb

  def show
    @product = Product.find(params[:id])
  end


/controller/likes_controller.rb

  def create
    @like = current_user.likes.build(product_id: params[:product_id])
    if @like.save
      redirect_to product_path(@like.product_id)
    else
      flash[:notice] = "お気に入りの登録に失敗しました"
    end
  end

  def destroy
    like = current_user.likes.find_by(product_id: params[:product_id])
    if like.destroy
      redirect_to likes_user_path(current_user)
    else
      flash[:notice] = "お気に入りの削除に失敗しました"
    end
  end

という感じにしていました。











リファクタリング


ここでメンターさんから、
「resourcesを使って実装しましょう」と指令が出たため、

routes.rb

Rails.application.routes.draw do
  devise_for :users

  resources :products, only: [:show] do
    resources :likes, only: [:create, :destroy]
  end
end

/views/products/show.html.haml

= link_to("お気に入りから削除", product_like_path(@product), method: :post)
= link_to("お気に入り登録", product_likes_path(@product), method: :post)

という記述に変更。
これで大丈夫かと思ってました。









しかし、、、


ここで動作確認をしたところ、
いいねの登録はできたものの、削除になると、

localhost:3000/products/1/likes/1

Routing Error
No route matches [POST] "/products/1/likes/1"

と怒られてしまいました。
likesのidが正しく取得できていないと思い、
ローカル変数としてlikeを定義し、pathの引数にlikeを入れて再チャレンジしたものの、

localhost:3000/products/1/likes/10


Routing Error
No route matches [POST] "/products/1/likes/10"

と怒られてしまいました。









rails routesちゃんと見ようね。


likesの値は取得できているのになんで削除できないんだろうと考え、
method: :postとなっていた部分をmethod: :deleteに変えたところ、
ようやく削除に成功しました。。。

rails routesで確認すると、

product_likes POST   /products/:product_id/likes(.:format)     likes#create
product_like DELETE /products/:product_id/likes/:id(.:format) likes#destroy

ちゃんとDELETEを指定しろって書いてありました。。。









みなさん絶対マネしちゃダメ


このようなくだらないミスをする人を一人でも減らすために本エントリを書きました。
みなさん、いいねの削除機能を実装するときはmethod: :deleteにするのを忘れないようにしましょう(棒)

お手軽!Vue.js導入手順

こんにちは!kossyです!


さて、今回は流行りのJavaScriptライブラリである、Vue.jsをCDNで導入する手順と、簡単な使い方だけご紹介します。
(この記事では、まずは導入して動かし体感する、ということに重きを置いているため、細かい機能の説明は割愛しています。)



Vue.jsってなに?何ができるの?


Vue.jsはJavaScriptのライブラリで、Evan Youという方が開発し2014年に初版がリリースされています。
てっきり2年くらい前にリリースされたのかと勝手に思っていましたが、既に世に出てから4年が経過しているライブラリになります。

ちなみに、同じJavaScriptのライブラリとして比較されるReact.jsは、2013年に初版がリリースされています。


Vue.jsは、一部のページを動的に切り替えることができる、SPA(シングルページアプリケーション)を実装することができます。
React.jsもSPAを構築することができますが、Vue.jsと比べ、学習コストが高いと言われているようです。
また、他のライブラリを組み合わせて自分好みで自由に実装できる点も、React.jsとは異なっていると言えそうです。

参考にしたサイト:
Vue.jsとは?人気急上昇のJavaScriptフレームワークを解説 | 侍エンジニア塾ブログ | プログラミング入門者向け学習情報サイト
他のフレームワークとの比較 — Vue.js




Vue.jsの導入

Vue.jsはCDNで導入することが可能なので、
jQueryのようにお手軽に導入することができます。

より高度なアプリケーションを構築する場合は、別のツールを使って環境構築をする必要がありますが、
APIを使ってデータを取得しブラウザに表示するくらいであれば、CDNでも問題ないと思います。


CDNのソースは、以下のページのCDNの項に記載されています。
https://jp.vuejs.org/v2/guide/installation.html


コピーしたソースを、index.html (ファイル名は任意)のbodyタグの終了の直前で読み込んで、
Vue.jsのコードを記載するmain.js(ファイル名は任意)も読み込めば導入は終了です。


Vue.jsのざっくりとした使い方

コードを書いていきます。


Vue.jsでは、Vue 関数で新しい Vue インスタンスを生成することによって起動します。

main.js

var app = new Vue ({
 el:"#app"
})

ここで生成したVueインスタンスをHTMLに渡すことで、
Vue.jsが動作する領域を生成することができます。

index.html

<div id="app">

</div>

div id="app"~/divの領域以外のところにVue.jsの処理を記述しても、
領域外になり、動作しませんので、気をつけましょう。

あとはmain.jsに処理を記述し、index.htmlに表示するという流れが基本になります。

例えば、

main.js

var app = new Vue ({
  el:"#app",
  data: {
    message: "lorem ipsum"
  }
})

index.html

<div id="app">
  {{ message }}
</div>

と記述し、ブラウザで開くと、

f:id:kossy-web-engineer:20180921055215p:plain

通常のHTMLであれば、{{}}が表示されそうですが、表示されていません。
これは、マスタッシュ(口ひげ)構文と呼ばれ、messageプロパティで生成したlorem ipsumというテキストを、
HTML上でデータバインディングし展開するために用いられるものです。




また、フォームに入力した値を、リアルタイムで変更することもできます。

index.html

<div id="app">
    <input type="text" v-model="message">
    <p>
      {{ message }}
    </p>
  </div>

と記述し、ブラウザで動作を確認してみます。
f:id:kossy-web-engineer:20180921062607g:plain


リアルタイムで値を変更することができています。
これは、inputタグに追記したv-modelディレクティブによって実現できています。
inputタグやtextareaタグにv-modelディレクティブを用いることによって、
フォーム入力の値をデータバインディングすることができます。


まとめ

導入もお手軽でコードも簡潔なので、
コードを書いて動作させる喜びを知るにはうってつけだと思います。




参考にしたサイト
Vue.js 公式ガイド
https://jp.vuejs.org/

Vue JS入門決定版!jQueryを使わないWeb開発 - 導入からアプリケーション開発まで体系的に動画で学ぶ(有料)
https://www.udemy.com/learn-vuejs/

ぼっち演算子&.が便利だった

こんにちは!kossyです!





さて、今回はRuby2.3.以降に使えるぼっち演算子についてブログに残してみます!



使い方

ぼっち演算子はobject&.idのように用います。
上記のように記述すると、メソッドがnilでなかった場合のみメソッドが実行されます。
objectの中身がnilなら、idの戻り値はnilになります。

ぼっち演算子を用いることで、nilに対してメソッドを使おうとする際にエラーが出ないようにすることができます。
いわゆるnilガードですね。


例えば、deviseを導入している場合に、

if object.user_id == current_user.id 

という条件式があった場合、
ログインしていないと、nilに対してメソッドを使うことになりエラーが出てしまいます。

これを、

if object.user_id == current_user&.id

とすることで、ログインしていなくてもエラーが出ずに条件式を使用することができます。






try!となにが違うの?

調べてみたら、try!と&.は同じだそうです。
以下のブログが参考になりました。
sakurawi.hateblo.jp







なんでぼっち演算子って言うの?

気になって調べてみました。
どうやら、&の記号が、人が膝を抱えてふさぎ込んでいるように見えることから、
ぼっち演算子という俗称になったようです。
正式名称?はsafe navigation operatorと言うそうなので、
SNO演算子と覚えるよりも、ぼっち演算子の方が覚えやすいですね。






普通に便利

No method Errorにビビらずに実装できるようになるので、
開発がスムーズになるかと思います。