git cloneしたあとに--recursiveを付け忘れたことに気づいた。あとからsubmoduleをcloneしたい。
submoduleで管理しているライブラリをcloneし忘れた
いつもなら
git clone --recursive {gitリポジトリurl}
でcloneしてsubmoduleで管理しているライブラリもcloneしてくるのだが、
git clone {gitリポジトリurl}
としてしまった。
対処法
git submodule update --init --recursive
とすればsubmoduleで管理しているリポジトリも落としてこれる。
Docker for Macが重いので、VagrantでcoreOSをたててDocker Composeを導入する
Docker for Macが重い
Docker for Macを立ち上げると、Macのファンがとてもうるさくなる。
Docker for Macはハイパーバイザ型の仮想化をしているらしいが、
そのハイパーバイザがとてもCPUを枯渇させることがある。
冬だと暖かいからいいけど夏だと熱いから困る(・ω・)
対処法としては
1. docker-syncを使う 2. cachedオプションを使う 3. Vagrant + coreOS
の3つがあるみたい。今回は3をやってみようと思う。
これでMac上でDockerを動かさず、VM(coreOS)上で動かすことができる。
噂によるとDocker for Macより軽いらしいので導入してみる。
手順
VagrantでVM(coreOS)をたてる
$ git clone https://github.com/coreos/coreos-vagrant.git $ cd coreos-vagrant $ vagrant up $ vagrant ssh
git cloneすると、Vagrantfileと諸々が落ちてくるので、
通常と同じようにvagrant upすればcoreOSが立ち上がる。
こういうところでVagrantはまだまだ便利だなと感じる。
dockerのバージョン確認
$ docker --version $ Docker version 17.09.0-ce, build afdb6d4
おお。ほんとにDockerが入ってる。
Docker Composeを入れる
coreOSにはDocker Composeが入っていないので、別途installする必要がある。
基本上記に従ってinstallする。
現在1.17.0が最新だが、公式サイトにて最新バージョンを確認の上installしてください。
$ sudo -i $ mkdir -p /opt/bin $ curl -L https://github.com/docker/compose/releases/download/1.17.0/docker-compose-`uname -s`-`uname -m` -o /opt/bin/docker-compose $ chmod +x /opt/bin/docker-compose
Docker Composeのバージョン確認
$ docker-compose -v docker-compose version 1.17.0, build ac53b73
やったね。いろいろ動かしてみよう。
データベースの「データ型」とは何か?(その1)
はじめに
皆さん、データベースのデータ型について意識した事はありますか?
「データ型って何?」って思ったそこのRails使いの方!
rails db
postgres=# \d table_name
を叩いてみましょう。
※ table_nameは存在する適当なテーブル名
すると、以下のテーブルがあらわれます。
Column | Type | Modifiers ------------+-----------------------------+---------------------------------------------------- id | integer | not null default nextval('blogs_id_seq'::regclass) title | character varying | content | text | created_at | timestamp without time zone | not null updated_at | timestamp without time zone | not null user_id | integer |
この「integer」「character varying」「text」などが、
「データ型」です。
データ型とは
データ型は、
「テーブルのカラムにどういうデータが入るか」を指定します。
先ほどの例では、
* idカラムにはinteger(整数) * titleカラムにはcharacter varying(制限付き可変長文字列) * contentカラムにはtext(制限なし可変長)
という感じですね。
なので、idカラムに文字列を入れようとするとエラーがおきます。
データ型は、想定していない変なデータがカラムに入ることを防いでくれる
なんだか厳格なヤツなのです。
データ型にもいろいろある
先ほど上げたのはpostgresqlのデータ型ですが、
MySQLやOracle Database、SQL Serverなど使用するRDMSによって若干異なります。
MySQLの場合はintegerじゃなくてint型だったり、
smallint, tinyint, bigintなんて型があったりします(格納可能な数値の範囲が異なる)
データ型を知っておくと良いこと
DB設計をするときには必須の知識です。
データ型の決定時にミスすると、
サーバのディスク容量を無駄に使用しすぎてしまったり、
本来入れたい値を入れることができなくなったりします。
これはなかなか困ります。
また、アプリケーション開発中、
データベース側でエラーが起きたときに直ぐに原因が特定でき、
デバッグが早くなります(多分)。
これから
気が向いたときにMySQLやpostgresqlのデータ型について
まとめていこうと思います。お待ち下さいm( )m
MySQLにて外部キーが貼れない。エラーは出ていない(MySQLのストレージエンジン・InnoDBとMyISAMの違い)
MySQLにて外部キーを貼ろうとした
table_aのidがtable_bのidを外部キーとして参照するように、
以下のようなSQLを流した。
alter table `table_a_name` add constraint table_a_name_ibfk_1 foreign key (table_a_id) references table_b_name(table_b_id) on delete cascade on update cascade;
特にエラーは起きなかったのに、なぜか外部キーが貼れていない。
解決方法
MySQLのストレージエンジンをMyISAMからInnoDBに変えればOK.
ALTER TABLE dbname.tablename ENGINE=InnoDB;
MySQLでMyISAMからInnoDBに変更させる – Simple IT Life
解説
ストレージエンジンがMyISAMだと外部キーが貼れず、
InnoDBだと外部キーが貼れる。
今回扱っていたテーブルはMyISAMだったので、InnoDBに変更した。
ストレージエンジンとは
ストレージエンジンとは、公式サイトで以下のように紹介されている。
ストレージエンジンは、さまざまなテーブル型に対する SQL 操作を処理する MySQL コンポーネントです。
…よくわからない。
が、要するにMySQLの機能の中で、
データの読み書きを担当している部分がストレージエンジンなのだろう。
MySQLは以下の2つのストレージエンジンを持っている。
の2つのストレージエンジンから選ぶことができる。
これらのストレージエンジンはテーブルごとに設定できる。
tableAはMyISAM、
tableBはInnoDBという感じ。
MyISAMとInnoDBの違い
MyISAMは外部キーが使えない
InnoDBは使える。
今回はMyISAMが使われていたので、外部キーが貼れなかった。
他にも、
速度の遅速
行ロックできるか出来ないか
トランザクションが効くか効かないか
の違いがある。
MyISAMとInnoDBの使い分け
基本InnoDBで問題なさそう。
トランザクションと外部キーはデータの整合性を保つには必須なので。
複雑な親子関係がなく、トランザクションのようなまとまった処理がなく、
かつ速度が要求される場合はMyISAMを選ぶ感じかな
(あまり思いつかないけど)
おまけ
alter table `table_a_name` add constraint table_a_name_ibfk_1 foreign key (table_a_id) references table_b_name(table_b_id) on delete cascade on update cascade;
外部キー名によく使われる「ibfk」は、
InnoDB Foreign key
の略らしい。
そりゃInnoDBでしか外部キー使えないわな。
名は体を表すとはこういうことか。
Angular2/4とgoogle maps apiを使って、緯度経度から住所を取得してみた(逆ジオコーディング)
やりたいこと
google mapのある地点をクリックした際に、
その地点の緯度経度・住所を取得する必要がありましたので、
google maps apiを使って逆ジオコーディングを実現してみました。
ジオコーディング / 逆ジオコーディングとは
- ジオコーディング
住所の情報から、緯度経度などの地理的情報を取得すること。
- 逆ジオコーディング
緯度経度から、住所等の情報を取得すること。
google mapをクリックした時点で緯度経度情報が取得できるので、
今回は逆ジオコーディングを行いました。
準備
まずはこちらでAGMを導入してmapを表示するところまでやっておきます。
手順
mapをクリックしたときのイベント取得ができるようにする
逆ジオコーディングを行うためのサービスを定義する
mapをクリックしたときに逆ジオコーディングが行われるようする
1 mapをクリックしたときのイベント取得ができるようにする
1-1. app.component.htmlにて、mapのクリックイベントを設置する
<agm-map [latitude]="lat" [longitude]="lng" [zoom]="zoom" (mapClick)="mapClicked($event)" > </agm-map>
1-2. app.component.tsにて、クリックイベントが起こった時の処理を記述する
export class AppComponent { /** ここから */ mapClicked($event) { let lat = $event.coords.lat; let lng = $event.coords.lng; console.log('緯度: ' + lat); console.log('経度: ' + lng); } /** ここまで追加 */ }
1の結果
2 逆ジオコーディングを行うためのサービスを定義する
2-1. サービスクラスを生成
ng g service geocoder
2-2. サービスクラスに必要モジュールを読み込む
/** geocoder.service.ts */ import { Injectable, NgZone } from '@angular/core'; import { AgmCoreModule, GoogleMapsAPIWrapper, MapsAPILoader } from '@agm/core';
2-2. コンストラクタの記述
// GoogleMapsAPIWrapperを継承する export class GeocoderService extends GoogleMapsAPIWrapper { constructor( private __loader :MapsAPILoader, private __zone :NgZone ) { super(__loader, __zone); } }
2-3. google maps apiの読み込み処理の記述
export class GeocoderService extends GoogleMapsAPIWrapper { getAddress(lat, lng) { this.__loader.load().then(() => { /** * google maps scriptsがloadしおわると、 * この中でgoogle maps apiが使える * (new google.maps等) */ let geocoder = new google.maps.Geocoder(); /** 以下に逆geocode処理を記述 */ } } }
2-4. 逆ジオコーデングの処理を記述
export class GeocoderService extends GoogleMapsAPIWrapper { getAddress(lat, lng) { this.__loader.load().then(() => { /** * google maps scriptsがloadしおわると、 * この中でgoogle maps apiが使える * (new google.maps等) */ let geocoder = new google.maps.Geocoder(); /** 以下に逆geocode処理を記述 */ let latlng = new google.maps.LatLng(lat, lng); geocoder.geocode( { 'latLng': latlng }, function(results, status) { if (status == 'OK') { console.log(results); console.log(results[0]); } else { alert('Geocode was not successful for the following reason: ' + status); return false; } } } }
3. mapをクリックしたときに逆ジオコーディングが行われるようする
3-1. app.module.tsにgeocoderサービスをDI
import { GeocoderService } from './geocoder.service'; @NgModule({ providers: [ GeocoderService ] })
3-2. app.component.tsにgeocoderサービスをコンストラクタに追加
import { GeocoderService } from './geocoder.service'; export class AppComponent { constructor( private geocoderService :GeocoderService ) {}
3-3. app.component.tsにてgeocoderサービスの住所取得関数を呼び出す
export class AppComponent { mapClicked($event) { let lat = $event.coords.lat; let lng = $event.coords.lng; console.log('緯度: ' + lat); console.log('経度: ' + lng); this.geocoderService.getAddress(lat, lng); // 追加 } }
結果
apiからは複数の逆ジオコーディング候補が返ってきます。
そのなかからいろいろな条件を指定したり、整形するなどして目的の情報を手に入れる必要があります。
今回の例では1件目(results[0])を取得してみました。
Rubyの配列を集合として扱った時の操作がとてもわかりやすい(共通集合・和集合・集合の差)
配列の準備
ary1 = %w(a b c) # ["a","b","c"] ary2 = %w(b c d) # ["b","c","d"]
%wというのはパーセント記法と言うやつです。
これを使うと配列の定義が簡単にできます。
今回の場合は文字列を要素に持つ配列を作成しています。
共通集合
p (ary1 & ary2)
#=> ["b", "c"]
和集合その1
p (ary1 | ary2)
#=> ["a", "b", "c", "d"]
和集合その2
p (ary1 + ary2)
#=> ["a", "b", "c", "b", "c", "d"]
その1と違って重複を許してます。
単純に集合をくっつけている感じ。
差分
p (ary1 - ary2)
#=> ["a"]
これはほぼ見たまんま。
感想
すごく直感的にかけるので良い。
Rubyのmoduleとmodule_functionについて
moduleを定義する
module MyModule def hello puts 'hello' end end MyModule.hello #=> undefined method `hello' for MyModule:Module (NoMethodError)
これだけだと使えない。
moduleを定義 + module_functionを定義
module MyModule def hello puts 'hello' end module_function :hello end MyModule.hello #=> hello
使える。