とーますメモ

Ruby on Rails / Goなどの学習メモ

【Rails】Rails4で親モデル用のサブディレクトリを作成し、STI(単一テーブル継承)をやってみる

サブディレクトリの作成

サブディレクトリを配置する場所は
app/models内。

ディレクトリ名はここでは「app/models/parents」とした。

Rails4ではmodels直下しか読み込まれないので
「config/application.rb」内に以下を追加し、models内のサブディレクトリ内のファイルも読み込まれるようにする。

config.autoload_paths += Dir["#{config.root}/app/models/**/"]

STIの設定

STIの説明については、以下のページが詳しい。
Railsでスーパータイプ/サブタイプを表現する方法を比較してみる - Qiita
[Rails]Model/テーブル設計で必ず覚えておきたいSTI | Raccoon Tech Blog [株式会社ラクーンホールディングス 技術戦略部ブログ]
みんなRailsのSTIを誤解してないか!? - Qiita

STIではなく具象クラスで対応する場合は以下の方法も使えそう。
[Rails 5] モデルの継承元がActiveRecord::BaseからApplicationRecordに変更された
[Rails] self.abstract_class = true の意味と挙動 « Codaholic

まずはモデルが参照するテーブルにtypeカラムを追加する。
XXXXXはテーブル名

$ bundle exec rails g migration AddTypeToXXXXX type:string

このtypeには「サブクラス名」が保存される。
サブクラスでnewすると、そのサブクラス名が自動的に保存され
allやfindすると自動的に、条件文にtype IN ('サブクラス名')が指定される。

すごい便利。

[その他参考]
サブディレクトリに配置したモデルクラスの名前を変更する - Ruby1.9とRails3で何か作ってみる
モデルをサブディレクトリに分割する Rails 3.2 - Qiita
https://qiita.com/yebihara/items/9ecb838893ad99be0561

【Laravel】Mac上で環境構築をしてみる

[前提]
※1 homebrewが既にインストールされている
※2 DBはMySQLを使用する

Composerのインストール

Railsでいうgemみたいなパッケージ管理ツールであるComposerをインストールし
ComposerからLaravelをインストール

インストール

$ brew install composer

確認

$ brew info composer

Laravelインストーラのインストール

Composerを利用しインストール

$ composer global require "laravel/installer"

Laravelのインストーラのパスが「$HOME/.composer/vendor/bin」に作成されるので
ここにパスを通す。

~/.bash_profile

export PATH="$PATH:$HOME/.composer/vendor/bin"

.bash_profileの再読込

$ source ~/.bash_profile

確認

$ laravel --version

Laravelで新規プロジェクトの作成

新規プロジェクトを作成したディレクトリに移動し、
そのディレクトリ内で、以下のコマンドでプロジェクトを作成

$ laravel new test_app

※composer経由でインストールする方法もあるが、こちらのほうが覚えやすい。
インストール 5.8 Laravel


しばらくすると、test_appディレクトリが作成され、その中に全てがインストールされるので
test_app内へ移動し、以下のコマンドでWebサーバーを起動させる

$ cd test_app
$ php artisan serve

そしてブラウザで「http://127.0.0.1:8000」にアクセスし、Laravelのトップページが表示されればインストール成功

またLaravel自体のバージョンを確認するには以下のコマンド

$ php artisan --version

各種設定

言語と時刻の設定

config/app.phpで設定

'timezone' => 'Asia/Tokyo',
...
'locale' => 'ja',

DB接続設定

アプリ用のデータベースを予め作成しておく。
※ここでは「test_db」を作成しておく。

ルートディレクトリにある「.env」の以下を編集
※ユーザ名とパスワードは任意

DB_DATABASE=test_db
DB_USERNAME=root
DB_PASSWORD=password

後は以下のコマンドを流して、エラーがでなければOK

$ php artisan migrate

[参考]
Mac OSにLaravelローカル開発環境構築 - Qiita
macOSに Laravel 5.6 をインストールする手順をまとめてみる - Qiita
Laravel ローカル環境構築(for XAMPP) - Laravel学習帳

デバック用ツール(laravel-debugbar)のインストール

インストール

$ composer require barryvdh/laravel-debugbar

config/app.phpの編集

'providers' => [
    ...
    Barryvdh\Debugbar\ServiceProvider::class,
    ...
],

...

'aliases' => [
    ...
    'Debugbar' => Barryvdh\Debugbar\Facade::class,
    ...
],

ルートディレクトリの.envを編集

APP_DEBUG=true

キャッシュをクリア

$ php artisan config:cache

ブラウザで127.0.0.1:8000にアクセスし、ブラウザ下部にデバックバーが出ればOK

アプリ作成の基本

基本的には以下の流れ

1)artisanコマンドでモデル、コントローラ、マイグレーションファイルを作成
2)マイグレーションの定義を記述し、migrate
3)モデルを作成
4)ルーティング設定
5)コントローラとVIEW(resources)を紐づけ
6)画面表示及びデバッグ

モデル作成は以下のサイトを参考に1行ブログを作成するときの例
Webアプリ開発入門 Laravel編のレッスン一覧 | プログラミング学習サービス【paizaラーニング】

1)記事を保存するテーブル作成のためのmigrationファイル
2)記事情報にCRUDに関するDB操作を行うためのmodelファイル
3)モデルにアクセスするためにリクエストを行うcontrollerファイル

を以下のコマンドで一気に作成。

$ php artisan make:model Article -m -c -r
  • m ... migrationも同時作成
  • c ... controllerも同時作成
  • r ... controllerを作成する場合、CRUD用のアクションもコントローラ内に作成される

ルーティングはこんな感じ。以下ではリストページと詳細ページを作成し
後でリンクで呼び出せるように、name関数を使用している。
routes/web.php

Route::get('/articles', 'ArticleController@index')->name('article.list');
Route::get('/article/{id}', 'ArticleController@show')->name('article.show');

【CakePHP2.x】メンテナンスページを作成する方法

今更だが、古いCakePHP2.x系のソースを修正する必要があり、
メンテナンスモードを簡単に実装するため、以下のプラグインを使用。

github.com

ただ、TOPページはCakePHP3.x系のものっぽいので、
branchesをたどり、以下の2.x系のソースをダウンロードして使用する。
GitHub - fusic/maintenance at master

ソースコード一式をダンロードし、解凍後のフォルダを「Maintenance」とリネームして
app/Pluginに入れる。また自分の場合は、メンテナンス用のレイアウトも使用したかったため
以下のようにソースを修正または追加した。

[修正] app/Config/bootstrap.php

<?php
// メンテナンスモードプラグインの導入
CakePlugin::load('Maintenance');
// trueにするとメンテナンスモードになる
Configure::write('Maintenance.enable', false);

[修正] app/Controller/AppController.php

詳細は後述するが、
・メンテナンス用のコントローラ
・メンテナンス用のビュー
・メンテナンス用のレイアウト
を作成し、自分の開発環境からのIPを除外する前提で、AppController.phpを編集する。
controllerに「メンテナンス用のコントローラ」、actionに「メンテナンス用のビュー」を設定
そして自分の開発環境IPを「xxx.xxx.xxx.xxx」に設定する。

<?php

        class AppController extends Controller {
            public $components = array(
               'Maintenance.Maintenance' => array(
                  'maintenanceUrl' => array(
                     'controller' => 'maitenance',
                     'action' => 'index'
                  ),
                  'allowedIp' => array('xxx.xxx.xxx.xxx', '127.0.0.1'), // allowed IP address when maintanance status
                  # 'allowedAction' => array('posts' => array('index'), 'users' => array('*')) // allowed action when maintanance status
                )
             );
        }

[追加] app/Plugin/Maintenance/Controller/MaintenanceController.php

<?php
App::uses('AppController', 'Controller');

class MaintenanceController extends AppController {
	public function index() {
		$this->autoLayout = false;
		$this->layout = 'maintenance';
	}
}

[追加] app/Plugin/Maintenance/View/Maintenance/index.ctp

※任意の文字を設定

現在システムメンテナンス中です。今しばらくお待ち下さい。

[追加] app/Plugin/Maintenance/View/Layouts/default.ctp

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>メンテンナンス</title>
</head>
<body>
  <?php echo $this->fetch('content'); ?>
</body>
</html>


これで準備は完了。
メンテナンスモードにするには、
app/Config/bootstrap.phpの以下をtrueにすればOK

<?php
Configure::write('Maintenance.enable', true);

タイマー設定もでき、「app/tmp/maintanance」のファイルを作成し、
ファイル内に以下のように設定できることでタイマー設定ができる。

例1: Maintenance 2011/1/1 ~ 2011/1/3

2011-01-01 00:00:00,2011-01-03 23:59:59

例2: Maintenance 2011/12/28 ~

2011-12-28 00:00:00,

例3: Maintenance ~ 2011/3/31 12:00

,2011-03-31 12:00:00

[参考]
GitHub - fusic/maintenance at master
メンテナンスモードを簡単実装できるMaintenance plugin | CakePHPクッキング
Maintenance plugin for CakePHPの組み込み : 儲かる気がしないスマホアプリ開発日誌

【Python】Pythonを学習してみて思ったこと

自分用メモ。

普段はRubyを使っているので、
以下の本を読みながら思ったことをメモしていく。
なにかの言語を既に触っているんだったら、1日あれば十分読める。

独学プログラマー Python言語の基本から仕事のやり方まで

独学プログラマー Python言語の基本から仕事のやり方まで

Rubyとの違い

・bool値がtureやfalseの小文字ではなく、先頭の文字を大文字にしたTrueとFalseが使用される。
Pythonは大文字と小文字を識別するので、tureやfalseと書いた場合エラーになる。
・nilではなく、None
・定数がない。慣習的に大文字とアンダーバー(_)で定数であることを表現する場合が多い。
・論理演算子で「&&」「|| 」「!」が使用できない。「and」「or」「not」を使用する。
・elsifではなくelif。elseは同じ。
・関数宣言のキーワードは、rubyと同じdef。
・if、elif、else、for、関数宣言の前などの最後にコロン(:)を書く。
・例外処理はtry - except - finally
・リストへの作成はlist = []で同じだが、追加はlist.appendという文法を使う。(<<できない)
・タプルというRubyでいう配列要素をfreezeしたようなものが使える。
・穴埋め文字列はPythondだとこんな感じ。"{}は{}年に生まれました。".format(author, year_born)。{}が文字が埋まる場所になる。
・Pythonのクラスでは、プライベート変数はない。Pythonの変数全てパブリックなので、アンダーバーを変数につけて名前規約でカバーする。
・x.nil?ではなくx is None

【Python】簡単な開発環境構築

Pythonの基本環境構築は前回の記事で書いたので、その続き。
thoames.hatenadiary.jp

アプリの起動を逐一「pipenv shell」=> 「python app.py」とかするのが面倒くさいので
Pipfileに以下のように書いておけば、「pipenv run start」とすることでアプリを一発で起動できる。
何度の入力するコマンドなので、登録しておいたほうが良い。

[scripts]
start = "python app.py"

1)静的解析

他のツールであるpep8やpyflakesなどを包括している便利なラッパーなのでflake8を使用。
開発環境のみでしようするので「--dev」オプションを付けてインストール

$ pipenv install --dev flake8

flakeの設定ファイル(setup.cfgまたは.flake8)に以下の設定を追加
ここでは、Lint対象から除外するファイル及びディレクトリの設定、
1行あたりの文字数を設定、それとインデントをPEP8デフォルトの4にするルールを無視し、
インデント幅を2にしている。これは完全に好み。

[flake8]
exclude = .git, .tox, .venv, .eggs, build, dist, docs, tests/*
max-line-length = 120
ignore = E111, E114
indent-size = 2

普通に使う方法は「pipenv run flake8」を打つだけ。
自分の場合は「--show-source」オプションを付けて、ソースコードのどの部分を修正すればよいか詳しく
知りたいので、Pipfileの編集しショートカットを登録。

[scripts]
 :
lint = "flake8 --show-source ."
 :

以下のコマンドでflake8を起動

$ pipenv run lint

flake8には他にも便利なプラグインがあるので使用する。

[flake8-todo]: ソース内のTODO、FIXME、XXXを検出してくれる。
[flake8-quotes]: ダブルクオーテーションを使用しているかをチェックする。
※flake8-double-quotesも使用してみたが、動作しなかった。。。※python 3.7.2で検証
[flake8-print]: printデバックしてる箇所を見つける。(使用しないようにする)

flake8のプラグインは「pip search flake8-」で検索すると大量に表示される。

以下ではflake8-todoをインストールする例を示す。

インストール

$ pipenv install --dev flake8-todo

確認

$ pipenv run flake8 --version

後は普通にflake8を実行すれば、TODO箇所を抽出してくれる。

2)コードフォーマット

autopep8を使用する。

インストール

$ pipenv install --dev autopep8

インデント幅などの設定を書きたいときは、setup.cfg, tox.ini, .pep8または.flake8に書く。
また設定セクションはpep8, pycodestyleまたはflake8をセクションとして使用できる。
自分は以下のように設定

[pycodestyle]
indent-size = 2

Pipfileにショートカットを登録(i: 上書き, v: 実行時の詳細情報を表示, r: 再帰実行)

[scripts]
 :
fix = "autopep8 -ivr ."
 :

実行

$ pipenv run fix

備考:
Atomを利用している場合で、[atom-beautify]プラグインを入れている場合は、
autopep8と連動し、Ctrl + Option + bで自動整形してくれる。
また[atom-beautify]の設定画面でPythonを選ぶと、「保存時に自動整形」してくれるオプションがあるので
それにチェックを入れると、保存時に自動整形してくれるようになる。
※注意点としては、setup.cfgにインデントや無視するPEP8ルールの設定を書いていても、
それとは別にatom-beautify独自に別に設定を書く必要があること。

※ 追記 2019/04/04
pipenvのような仮想環境を使用し、atom-beautifyを使用している場合、
「Could not find 'autopep8'. The program may not be installed.」と表示される場合がある。
以下URL内のようなもの。
https://github.com/hhatto/autopep8/issues/363

この場合は、エラー内の説明にあるように
「Atom Beautify」 => 「Settings」 => 「Executable」=> 「autopep8」内に
仮想環境内のautopep8のパスを実行パスとして設定すれば良い。

仮想環境内のautopep8のパスの確認方法

$ pipenv run which autopep8

表示されたパスを、実行パスに設定すれば動作するようになる。






[参考]
Pythonのパッケージ周りのベストプラクティスを理解する - エムスリーテックブログ
Pythonのスタイルガイドとそれを守るための各種Lint・解析ツール5種まとめ! - Sider Blog
Pythonでインデントをスペース2つにした際の周辺ツールの設定 | タロスカイ公式ブログ
[Python] コードの自動整形でインデントレベルを2に設定する - Qiita
Python の Lint (文法チェッカ) まとめ - flake8 + hacking を使う - - Qiita
2018年のPythonプロジェクトのはじめかた - Qiita

【Python】Python初心者がMac上で環境構築をしてみる

homebrewが既に入っており、Python3環境を作成するのが前提。

新しい言語を使用するときに、自分がまず調べることは以下の2つ。

1)デバック方法の把握
2)グローバル環境を汚染せず「プロジェクト毎の環境(バージョン及びパッケージ)」が構築できるツールの使用法

1)については以下で書いたので、2)ついて今回はまとめる。
thoames.hatenadiary.jp

① Pythonバージョンを自由に変更して使用する方法

「pyenv」を使う方法が一般的みたい。
複数の異なるバージョンのPythonを利用したいときに使用する。
3.3.0と3.3.1といった細かいバージョンわけまで管理可能。
2系と3系との切り替えにも便利。

インストール

$ brew install pyenv

パスを通す

$ echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bash_profile
$ echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bash_profile
$ echo 'eval "$(pyenv init -)"' >> ~/.bash_profile
$ source ~/.bash_profile

バージョン確認

$ pyenv --version

インストール可能なバージョンを確認

$ pyenv install --list

現時点(2019/02/10)での最新の2系(2.7.15)と3系(3.7.2)の安定版バージョンをインストール

$ pyenv install 2.7.15
$ pyenv install 3.7.2

pyenvを通してインストールされたバージョンの確認

$ pyenv versions

※ちなみにアンインストールしたい場合は以下。簡単。

$ pyenv uninstall <version>

[変更前] 現在のPythonのバージョン確認

$ python -V

3.7.2をグローバル環境で使用する例

$ pyenv global 3.7.2

現在いるディレクトリ内だけで特定バージョンを使用したい場合は、globalではなくlocalコマンドを利用する。
localコマンドを利用すると、そのディレクトリ内にPythonバージョンが記載された.python-versionファイルが作成される。
またglobal及びlocalの両方が設定されている場合、localのPythonバージョンが優先される。
なので、まずは普段使いするバージョンをglobalで設定し、
プロジェクト毎にバージョン変更する場合は、localを使用するという使い方になる。

2.7.15をローカル(現在のディレクトリ内だけ)で使用する例

$ pyenv local 2.7.15

[変更後] 現在のPythonのバージョン確認

$ python -V

この時点で、pyenvで指定したバージョンに変更されていればOK。
変更されていない場合は、以下の記事を参照
pyenvのインストール、使い方、pythonのバージョン切り替えできない時の対処法 - Qiita

② [簡易版・小規模] Pythonパッケージをプロジェクトごとにインストール/使用する方法

Python2では「virtualenv」という仮想環境ツールを別途インストールし使用するが
Python3.3からはこのツールの機能が「venv」という名前で標準ライブラリに取り込まれたので
この記事では「venv」を使用する。

「project-hoge」という名前の仮想環境を作成する例
※ 「-m」オプションを使うと、インストールされているモジュールをスクリプトとして実行できる。

$ mkdir ~/Python/env
$ cd ~/Python/env
$ python -m venv project-hoge

※仮想環境作成時に、どの仮想環境内でどのPythonバージョンを使用するかを決めることができるので
pyenv localコマンドを使用する必要がないとのこと。詳細は以下の記事より。
Rubyist が pyenv を使うときに知っておいてほしいこと - Qiita


「project-hoge」仮想環境を有効化

$ cd ~/Python/env
$ source hoge/bin/activate

上記のコマンドを打つことで、仮想環境を有効化するとコマンドプロンプトの頭に仮想環境名が
入り、現在どの仮想環境内で作業しているのかがわかるようになる。
仮想環境有効化した状態で、パッケージなどを好きにインストールすると、インストールしたパッケージは
仮想環境内だけで適用されるため、他の仮想環境内からは見えなくなる。

「project-hoge」仮想環境を無効化

(project-hoge) ユーザ名$ deactivate

③ [中規模以上] Pythonパッケージをプロジェクトごとにインストール/使用する方法

簡単なパッケージをインストールするぐらいなら、②で紹介した方法でも良いが
パッケージが複雑に絡み合うようなプロジェクトを作成する場合などでは
「パッケージ管理」を滞りなく行ってくれるツールを使ったほうがよい。
記事を書いている時点で、「Pipenv」と「Poetry」というツールが候補に上がったが
以下の理由で最終的に「Pipenv」を使用することにした。

1)単純にGithubのスター数が圧倒的に、Pipenvが多かった
2)日本語情報がPipenvの方が多そうだった
3)PipenvからPoetryへの以降はそれほど難しそうではない

インストール

$ pip install pipenv

プロジェクトのディレクトリを作成し、初期ファイルを作成
サンプル用のflaskプロジェクトを作成

$ mkdir ~/Python/projects/flask
$ cd ~/Python/projects/flask

# 以下のようにしてしまうと、「~/.local/...」で仮想環境がまとめられてしまう。
# 自分の場合は、プロジェクトディレクトリ内に、仮想環境を作成してほしかったので
# 
# $ pipenv install

次に「pipenv install」を行って、初期ファイルの「Pipfile」と「Pipfile.lock」を作成するのだが
そのままコマンドを入力してしまうと、「~/.local/...」で仮想環境がまとめられてしまう。
自分の場合は、プロジェクトディレクトリ内に、仮想環境を作成してほしかったので
PIPENV_VENV_IN_PROJECTという環境変数を以下のように設定する。

またpipenvのコマンドを補完をサポートしてくれる「pipenv --completion」の設定も追加

パスを通す

$ echo 'export PIPENV_VENV_IN_PROJECT=true' >> ~/.bash_profile
$ echo 'eval "$(pipenv --completion)"' >> ~/.bash_profile
$ source ~/.bash_profile

初期ファイル作成

$ pipenv install  

上記のようにすることで、仮想環境は、プロジェクト内の「.venv」というディレクトリ内に作成される。

仮想環境を有効化

$ pipenv shell

仮想環境外から仮想環境内のコマンドを叩くときは以下のようにする。
仮想環境外からpythonコマンドを叩く例

$ pipenv run python

仮想環境内で「exit」コマンドを使用すれば、仮想環境から抜けられる。

次にflaskをインストール

$ pipenv install flask

flaskがインストールされていることを確認

$ pipenv shell
(flask) bash-x.x$ pip list

または

$ pipenv run pip list

app.pyを作成

# coding: utf-8

from flask import Flask
app = Flask(__name__)

@app.route('/')
def hello_world():
    return 'Hello World!'

@app.route('/ja')
def hello_world_ja():
    return 'こんにちは 世界!'

if __name__ == '__main__':
    app.run()

※ 初期状態だと、flaskの実行環境(Environment)が「production」になっているので
「WARNING: Do not use the development server in a production environment.」というエラーがでる。
このエラーを消すために、FLASK_ENV環境変数にdevelopmentを指定する。

$ echo 'export FLASK_ENV=development' >> ~/.bash_profile
$ source ~/.bash_profile

flaskを起動

$pipenv run python app.py

起動に成功したら、「http://127.0.0.1:5000/」にアクセスすることで
「Hello World!」が表示される。

備考

元々、Pythonを使おうと思ったのは単純に簡単なFlaskを使用したWebサービスを作ってみたかったから。
FlaskについているWebサーバはあくまでも開発用っぽいので、実際に大量のアクセスをさばくような
Webサービスを開発するとなると、ApacheなりNginxなりを使用する必要がありそう。

検索してみたら、いい感じのuwsgi + Nginx + flaskのdockerイメージが合ったので
本番環境を構築するときは、これを使ってみたい。
uwsgi-nginx-flask-dockerでFlaskを楽々Docker運用 - Qiita



[参考]
pyenvのインストール、使い方、pythonのバージョン切り替えできない時の対処法 - Qiita
pyenv を用いた Python3 インストール - Qiita
Python 仮想環境 | pyenv と vertualenv による Python の開発環境の構築
Pythonの環境管理ツール良し悪し - Zopfcode
Rubyist が pyenv を使うときに知っておいてほしいこと - Qiita
Python3 Pipenvの導入メモ - ikap
[Flask] Flaskの基本的な構成(を思い出す) | Today's Commit

【Python】デバック方法について

自分用メモ。

Rubyのbyebugみたいなやり方を探していたら、
以下の一行を入れれば良いだけ。

import pdb; pdb.set_trace()

でも長すぎる・・・

JetBrainsのPyCharmやVSCode入れれば、上記のコード入れなくても
ブレークポイントをエディタ上でつけられるので良さげ。

まずは無料のVSCodeで試してみたい。

[参考]
Pythonでデバッグしたい - Qiita