お名前.comで取得したnaked domainをherokuのアプリケーションに割り当ててSSLも自動更新で運用する方法
現時点(2017年度9月)でおそらく最短距離で実施する方法だと思います。 昨今SSL接続必須化の流れを鑑み、ドメインを割り当てるだけでなく、SSL接続を可能にし、証明書更新の運用もHerokuに丸投げするように設定してみました。
- お名前.comでドメインを取得する
- HerokuのDynoをHoby($7/month)以上にする
- HerokuのSettings > Domains and certificates
- HerokuのResources > Add-onsでPointDNSを追加
- PointDNSで1.で取得した独自ドメインを登録
- PointDNSで登録したドメインのレコード設定でALIAS、CNAMEに3-2で取得されたDNS Targetを設定
- お名前.comでネームサーバーの変更で6.で一覧表示されているTypeがNSのもの(ネームサーバ おそらく dns12.pointhq.com.など3つほど)を登録
オープンソースのmastodonからみるRails + React構成や採用されているライブラリについて
mastodonについて
mastodonという新興SNSが国内でも流行りだしています。フェーズとしてはまだイノベータからアーリーアダプターが様子を見てるって感じかなと個人的には思います。
mstdn.jpという日本ドメインのインスタンスでは、現時点(2017/4/22)で全インスタンスと比べても世界一のユーザ数を誇っています。ただ、実際に投稿内容を見てみるとユーザもまだテスト投稿したりという感じのようです。(もっとコアなドメインのインスタンスだとそのコンテキストの投稿がもっと盛んにされているのかもしれないですが)
このサービスの面白いところは、分散型ネットワーク+OSSというところなのかなと勝手に解釈しています。つまり、個人もしくは企業がTwitterのようなSNSサービスを(手軽に)独自運営していけてそれが本家の改善にもつながる仕組みになっているところに魅力があります。もう少し具体的に言うと本体のソースコードがOSSなので大抵はForkしたものをデプロイすることになると思うのですが、そのインスタンス特有の機能を入れて本体とは少し違ったアプリケーションにしたり、場合によっては追加した機能や見つかったバグの修正を本体側にPull-Requestするなどサービス自体が分散して成長していく仕組みが取り入れられているのです。
コードを覗いてみてみる
前置きが少し長くなりましたがコードを実際に見てみるとRails+Reactで構成されていることがわかります。流行りのWebアプリケーションの構成だと思うので、参考になるところが多いです。
サーバーサイド構成
Rubyは2.4.1、Railsのバージョンは現時点で5.0.2で比較的新しい構成であることがわかります。
ruby '2.4.1' gem 'rails', '~> 5.0.2'
APIの管理
app/controllers/api_controller.rbにApiControllerと言う基底クラスを定義しています。また、app/controllers/api/v1配下に実際のAPIをApiControllerクラスの具象クラスとして配置しています。これでいわゆるAPIのバージョニング管理をしているようです。
concernの実装
model/concerns配下では以下のような共通の振る舞いが定義されています。
cacheable.rb paginable.rb streamable.rb targetable.rb
paginable.rbを見てみると内部的にarel_tableを使用してqueryを組み立てていることがわかります。
scope :paginate_by_max_id, -> (limit, max_id = nil, since_id = nil) { query = order(arel_table[:id].desc).limit(limit) query = query.where(arel_table[:id].lt(max_id)) unless max_id.blank? query = query.where(arel_table[:id].gt(since_id)) unless since_id.blank? query }
フロントエンド構成
app/assets/javascripts/components配下にReactのコードが配置されています。JavascriptはECMAScirpt 2015記法で書かれています。Gemfileをみると以下の記述が確認できます。
gem 'react-rails' gem 'browserify-rails' gem 'autoprefixer-rails'
React + Redux
reactをrailsに導入するアプローチはいくつかありますが、mastodonではasset_pipline上にReactをのせるためreact-railsを採用しています。また、browserifyでbabelを使ってコンパイルするようにbrowserify-railsを採用しています。Reactでのスタイル適用はインラインでもscssでもどちらにも書かれています。
Ajax
ajax通信ライブラリとしてはaxiosが採用されています。ただし、使用するにはapi.jsxというラッパーモジュールから呼び出しています。
再レンダリング対策
react-addons-pure-render-mixinが採用されています。
途中。気づいたら追記
Azure AppServiceで任意のタイムゾーンを設定する
タイムゾーンを日本に合わせたい人へ
ポータル > AppService > アプリケーション設定 でアプリ設定にWEBSITE_TIME_ZONEを「Tokyo Standard Time」で保存すればアプリが自動的に反映してくれます。
ASP.NET Coreでスクレイピングしたものを表示(HtmlAgilityPackを使用)
概要
SgmlReaderが.NET Core対応していないので.NET Core対応しているHtmlAgilityPackを使うことにしました。 ASP.NET Coreでスクレイピングしたページを表示する簡単なWebアプリケーションを作ってみたいと思います。 おっさんにyoしてWebアプリケーションの雛形ができたところからスタートとしたいと思います。
project.jsonへの登録
dependenceisのところにこんな感じで追加。 するとVSCodeが空気を呼んでrestoreするか聞いてくれるのでやっちゃう。
"HtmlAgilityPack.NetCore": "1.5.0.1"
適当なModelを用意する
public class Availability { public string Title {get; set;} public IEnumerable<DateTime> Dates {get;set;} public string ToString(DateTime date) { return date.ToString("yyyy年MM月dd日(dddd)"); } }
public class IndexViewModel { public List<Availability> Availabilities {get; set;} }
Controllerに処理を書く
SelectNodesしたときは//を入れるルールらしい。 スクレイピング自体はやっつけなのでサイトの構成変わったら動かんと思います。
public async Task<IActionResult> Index() { // service_category var rootUrl = new Uri("https://as.its-kenpo.or.jp/service_category/index"); var serviceCategoryDom = await GetHtmlAsync(rootUrl); var serviceGroupUrl = serviceCategoryDom.DocumentNode.SelectNodes("//a") .Where(x => x.InnerText == "直営・通年・夏季保養施設(空き照会)") .Select(x => x.Attributes["href"].Value) .Select(x => $"{rootUrl.Scheme}://{rootUrl.Host}" + x) .Select(x => new Uri(x)) .First(); // service_group var serviceGroupDom = await GetHtmlAsync(serviceGroupUrl); var serviceApplyUrls = serviceGroupDom.DocumentNode.SelectNodes("//li") .SelectMany(x => x.Descendants("a")) .Select(x => x.Attributes["href"].Value) .Select(x => $"{rootUrl.Scheme}://{rootUrl.Host}" + x) .Select(x => new Uri(x)); // service_apply var availabilities = new List<Availability>(); foreach (var serviceApplyUrl in serviceApplyUrls) { var serviceApplyDom = await GetHtmlAsync(serviceApplyUrl); var applyUrls = serviceApplyDom.DocumentNode.SelectNodes("//li") .SelectMany(x => x.Descendants("a")) .Select(x => x.Attributes["href"].Value) .Select(x => $"{rootUrl.Scheme}://{rootUrl.Host}" + x) .Select(x => new Uri(x)); // apply foreach (var applyUrl in applyUrls) { var applyDom = await GetHtmlAsync(applyUrl); var title = applyDom.DocumentNode.SelectNodes("//table") .Where(x => x.Attributes["class"] != null) .Where(x => x.Attributes["class"].Value == "tform_new") .Select(x => x.Descendants("tr").First()) .Select(x => x.Descendants("td").Last().InnerText) .First(); var dates = applyDom.DocumentNode.SelectNodes("//select") .Where(x => x.Attributes["id"] != null) .Where(x => x.Attributes["id"].Value == "apply_join_time") .SelectMany(x => x.Descendants("option")) .Select(x => x.Attributes["value"].Value) .Where(x => !string.IsNullOrEmpty(x)) .Select(x => Convert.ToDateTime(x)); var availability = new Availability(); availability.Title = title; availability.Dates = dates; availabilities.Add(availability); } } var model = new IndexViewModel(); model.Availabilities = availabilities; return View(model); }
Viewにモデルをバインド
@model Kenpo.Models.HomeViewModels.IndexViewModel <ul> @foreach(var availability in Model.Availabilities) { <li> <span>@availability.Title</span> <ul> @foreach(var date in availability.Dates) { <li>@availability.ToString(date)</li> } </ul> </li> } </ul>
結果
勘の良い人ならわかるかもしれませんがこんな感じでIT健保の(使いにくい)サイトから空き日を一覧にしてくれるWebアプリケーションが完成します。
直営・通年・夏季保養施設 トスラブ箱根ビオーレ 2016年度9月分申込 2016年09月29日(木曜日) 直営・通年・夏季保養施設 トスラブ箱根ビオーレ 2016年度10月分申込 2016年10月24日(月曜日) 2016年10月26日(水曜日) 2016年10月31日(月曜日) 直営・通年・夏季保養施設 トスラブ箱根和奏林 2016年度9月分申込 2016年09月20日(火曜日) 直営・通年・夏季保養施設 トスラブ箱根和奏林 2016年度10月分申込 2016年10月06日(木曜日) 2016年10月20日(木曜日) 2016年10月24日(月曜日) 直営・通年・夏季保養施設 トスラブ湯沢 2016年度9月分申込 2016年09月19日(月曜日) 2016年09月20日(火曜日) 2016年09月22日(木曜日) 2016年09月26日(月曜日) 2016年09月28日(水曜日) 2016年09月29日(木曜日) 直営・通年・夏季保養施設 トスラブ湯沢 2016年度10月分申込 2016年10月02日(日曜日) 2016年10月03日(月曜日) 2016年10月04日(火曜日) 2016年10月05日(水曜日) 2016年10月06日(木曜日) 2016年10月12日(水曜日) 2016年10月13日(木曜日) 2016年10月17日(月曜日) 2016年10月18日(火曜日) 2016年10月19日(水曜日) 2016年10月20日(木曜日) 2016年10月24日(月曜日) 2016年10月25日(火曜日) 2016年10月26日(水曜日) 2016年10月27日(木曜日) 2016年10月31日(月曜日) 直営・通年・夏季保養施設 トスラブ館山ルアーナ 2016年度9月分申込 2016年09月29日(木曜日) 直営・通年・夏季保養施設 トスラブ館山ルアーナ 2016年度10月分申込 直営・通年・夏季保養施設 中沢ヴィレッジ 2016年度9月分申込 2016年09月29日(木曜日) 直営・通年・夏季保養施設 中沢ヴィレッジ 2016年度10月分申込 2016年10月03日(月曜日) 2016年10月04日(火曜日) 2016年10月05日(水曜日) 2016年10月06日(木曜日) 2016年10月11日(火曜日) 2016年10月12日(水曜日) 2016年10月13日(木曜日) 2016年10月17日(月曜日) 2016年10月18日(火曜日) 2016年10月19日(水曜日) 2016年10月20日(木曜日) 2016年10月24日(月曜日) 2016年10月25日(火曜日) 2016年10月26日(水曜日) 2016年10月27日(木曜日) 2016年10月31日(月曜日) 直営・通年・夏季保養施設 ホテルハーヴェスト那須 2016年度9月分申込 2016年09月27日(火曜日) 直営・通年・夏季保養施設 ホテルハーヴェスト那須 2016年度10月分申込 2016年10月31日(月曜日) 直営・通年・夏季保養施設 ホテルハーヴェスト斑尾 2016年度9月分申込 2016年09月23日(金曜日) 2016年09月26日(月曜日) 2016年09月27日(火曜日) 2016年09月28日(水曜日) 2016年09月29日(木曜日) 2016年09月30日(金曜日) 直営・通年・夏季保養施設 ホテルハーヴェスト斑尾 2016年度10月分申込 2016年10月02日(日曜日) 2016年10月03日(月曜日) 2016年10月04日(火曜日) 2016年10月05日(水曜日) 2016年10月06日(木曜日) 2016年10月07日(金曜日) 2016年10月11日(火曜日) 2016年10月12日(水曜日) 2016年10月13日(木曜日) 2016年10月16日(日曜日) 2016年10月17日(月曜日) 2016年10月18日(火曜日) 2016年10月19日(水曜日) 2016年10月20日(木曜日) 2016年10月21日(金曜日) 2016年10月23日(日曜日) 2016年10月24日(月曜日) 2016年10月25日(火曜日) 2016年10月26日(水曜日) 2016年10月27日(木曜日) 2016年10月30日(日曜日) 2016年10月31日(月曜日) 直営・通年・夏季保養施設 ブルーベリーヒル勝浦 2016年度9月分申込 2016年09月19日(月曜日) 2016年09月20日(火曜日) 2016年09月21日(水曜日) 2016年09月28日(水曜日) 2016年09月29日(木曜日) 直営・通年・夏季保養施設 ブルーベリーヒル勝浦 2016年度10月分申込 2016年10月02日(日曜日) 2016年10月03日(月曜日) 2016年10月04日(火曜日) 2016年10月05日(水曜日) 2016年10月06日(木曜日) 2016年10月11日(火曜日) 2016年10月12日(水曜日) 2016年10月13日(木曜日) 2016年10月16日(日曜日) 2016年10月18日(火曜日) 2016年10月19日(水曜日) 2016年10月20日(木曜日) 2016年10月23日(日曜日) 2016年10月24日(月曜日) 2016年10月25日(火曜日) 2016年10月26日(水曜日) 2016年10月27日(木曜日) 2016年10月30日(日曜日) 2016年10月31日(月曜日) 直営・通年・夏季保養施設 ホテルハーヴェスト伊東 2016年度9月分申込 2016年09月30日(金曜日) 直営・通年・夏季保養施設 ホテルハーヴェスト伊東 2016年度10月分申込 2016年10月03日(月曜日) 2016年10月04日(火曜日) 2016年10月05日(水曜日) 2016年10月06日(木曜日) 2016年10月11日(火曜日) 2016年10月12日(水曜日) 2016年10月13日(木曜日) 2016年10月17日(月曜日) 2016年10月18日(火曜日) 2016年10月19日(水曜日) 2016年10月20日(木曜日) 2016年10月24日(月曜日) 2016年10月25日(火曜日) 2016年10月26日(水曜日) 2016年10月27日(木曜日) 直営・通年・夏季保養施設 ホテルハーヴェスト スキージャム勝山 2016年度9月分申込 2016年09月25日(日曜日) 2016年09月26日(月曜日) 2016年09月27日(火曜日) 2016年09月28日(水曜日) 2016年09月29日(木曜日) 2016年09月30日(金曜日) 直営・通年・夏季保養施設 ホテルハーヴェスト スキージャム勝山 2016年度10月分申込 2016年10月01日(土曜日) 2016年10月02日(日曜日) 2016年10月03日(月曜日) 2016年10月04日(火曜日) 2016年10月05日(水曜日) 2016年10月06日(木曜日) 2016年10月07日(金曜日) 2016年10月10日(月曜日) 2016年10月11日(火曜日) 2016年10月12日(水曜日) 2016年10月13日(木曜日) 2016年10月14日(金曜日) 2016年10月15日(土曜日) 2016年10月16日(日曜日) 2016年10月17日(月曜日) 2016年10月18日(火曜日) 2016年10月19日(水曜日) 2016年10月20日(木曜日) 2016年10月21日(金曜日) 2016年10月23日(日曜日) 2016年10月24日(月曜日) 2016年10月25日(火曜日) 2016年10月26日(水曜日) 2016年10月27日(木曜日) 2016年10月28日(金曜日) 2016年10月30日(日曜日) 2016年10月31日(月曜日) 直営・通年・夏季保養施設 琵琶レイクオーツカ 2016年度9月分申込 2016年09月28日(水曜日) 直営・通年・夏季保養施設 琵琶レイクオーツカ 2016年度10月分申込 2016年10月02日(日曜日) 2016年10月03日(月曜日) 2016年10月04日(火曜日) 2016年10月05日(水曜日) 2016年10月06日(木曜日) 2016年10月07日(金曜日) 2016年10月11日(火曜日) 2016年10月12日(水曜日) 2016年10月13日(木曜日) 2016年10月14日(金曜日) 2016年10月16日(日曜日) 2016年10月17日(月曜日) 2016年10月18日(火曜日) 2016年10月19日(水曜日) 2016年10月20日(木曜日) 2016年10月21日(金曜日) 2016年10月24日(月曜日) 2016年10月25日(火曜日) 2016年10月26日(水曜日) 2016年10月27日(木曜日) 2016年10月31日(月曜日) 直営・通年・夏季保養施設 ホテル日航プリンセス京都 2016年度9月分申込 2016年09月26日(月曜日) 2016年09月27日(火曜日) 直営・通年・夏季保養施設 ホテル日航プリンセス京都 2016年度10月分申込 2016年10月31日(月曜日) 直営・通年・夏季保養施設 ホテルハーヴェスト南紀田辺 2016年度9月分申込 2016年09月23日(金曜日) 2016年09月25日(日曜日) 2016年09月26日(月曜日) 2016年09月27日(火曜日) 2016年09月28日(水曜日) 2016年09月29日(木曜日) 2016年09月30日(金曜日) 直営・通年・夏季保養施設 ホテルハーヴェスト南紀田辺 2016年度10月分申込 2016年10月02日(日曜日) 2016年10月03日(月曜日) 2016年10月04日(火曜日) 2016年10月05日(水曜日) 2016年10月06日(木曜日) 2016年10月07日(金曜日) 2016年10月10日(月曜日) 2016年10月11日(火曜日) 2016年10月12日(水曜日) 2016年10月13日(木曜日) 2016年10月14日(金曜日) 2016年10月16日(日曜日) 2016年10月17日(月曜日) 2016年10月18日(火曜日) 2016年10月19日(水曜日) 2016年10月20日(木曜日) 2016年10月21日(金曜日) 2016年10月23日(日曜日) 2016年10月24日(月曜日) 2016年10月25日(火曜日) 2016年10月26日(水曜日) 2016年10月27日(木曜日) 2016年10月28日(金曜日) 2016年10月30日(日曜日) 2016年10月31日(月曜日) 直営・通年・夏季保養施設 角間温泉 岩屋館 2016年度9月分申込 2016年09月26日(月曜日) 2016年09月27日(火曜日) 2016年09月30日(金曜日) 直営・通年・夏季保養施設 角間温泉 岩屋館 2016年度10月分申込 2016年10月03日(月曜日) 2016年10月04日(火曜日) 2016年10月05日(水曜日) 2016年10月06日(木曜日) 2016年10月11日(火曜日) 2016年10月12日(水曜日) 2016年10月13日(木曜日) 2016年10月17日(月曜日) 2016年10月18日(火曜日) 2016年10月19日(水曜日) 2016年10月20日(木曜日) 2016年10月25日(火曜日) 2016年10月26日(水曜日) 2016年10月27日(木曜日) 直営・通年・夏季保養施設 ホテルハーヴェスト旧軽井沢 2016年度9月分申込 直営・通年・夏季保養施設 リゾートホテル蓼科 2016年度9月分申込 2016年09月28日(水曜日) 2016年09月29日(木曜日) 直営・通年・夏季保養施設 鎌倉パークホテル 2016年度9月分申込
ASP.NET Core でFacebook連携
基本的にはここ
Enabling authentication using Facebook, Google and other external providers — ASP.NET documentation
開発時点では環境をDevelopmentモードで起動する
本番ではUserSecretのファイルではなく環境変数を使用することになるのでDevelopmentモードで起動しなくてはいけない。やり方はふた通り
- dotnet runのオプションとして渡す場合
dotnet run ASPNETCORE_ENVIRONMENT=Development
- マシンの環境変数にあらかじめ設定しておく
export ASPNETCORE_ENVIRONMENT=Development dotnet run
ruby2.0とrails4.0をrvmでインストールした
最近は、とてもとても忙しくてなかなかお家で開発作業を進めることができなかったけど、
手がけていたアプリがとりあえずリリースできて少しだけ落ち着いたので早速rubyを導入する。
ということで、ruby2.0、ails4.0(beta1)をインストールしてみた。
opensslのバージョンが古いとダメっぽいのでそこのupdateから始める。
(環境はmaxos10.7.5)
全部で結構時間かかったけどとりあえずできた。
brewのupdate
$ brew update $ brew install openssl
rvmのupdateからのruby2.0インストール
$ rvm get stable $ rvm reload $ rvm install 2.0.0 $ rvm use 2.0.0 --default
rails4.0 beta1のインストール
$ gem install rails -v 4.0.0.beta1
rails の seeds.rbの使い方について
連休だったので、久しぶりにC#から離れてRailsのお勉強。
もうすぐRuby2.0&Rails4.0がリリースされるみたいなので、もう一度参入するチャンス!
で、今回はRailsのseeds.rbの簡単な使い方をまとめる。
概要
- マスタデータの投入。つまり初期データの投入に使える。
コマンド
rake db:seed
使い方
seeds.rbの編集
コマンドを呼び出すたびにseeds.rbの中身が追加されてしまうので、一回全部消去してidのautoincrementもクリアして入れなおす。
例えばBlogというモデルがあった場合は、一回delete_allを読んで
Blog.delete_all # 一回全部消して
Blog.connection.execute("delete from sqlite_sequence where name='blogs'") # autoincrementをクリアして
Blog.create(:name => "hoge blog") # データ投入
sqlite3で確認
コマンド呼び出したら実際にデータが投入されているか確認する
sqlite3 db/development.sqlite3
> select * from blogs;