k01ken’s b10g

He110 W0r1d!

CakePHP3でAjaxを使う

開発環境は、Windows 7 Professional(32bit)+XAMPP v3.22+CakePHP 3.5.8。

JavaScript内で、Ajaxを使うときに、ローカル環境だと、パスを指定する際は、絶対パスだと、なぜか通信エラーになるので、例えば、Apacheを使っていて、htdocsディレクトリ内に、CakePHPのルートディレクトリを作成した
場合は、/アプリケーション名/コントローラ名/アクション名で指定すること。
組み込みサーバーを使っている場合は、/コントローラ名/アクション名で指定すること。

・通信すると、結果をコントローラ側でprintやechoで出力したときに『headers already sent』のようなエラーが出現することがあるので、その場合は、通信先のコントローラのuseの直後に、ob_start();を入れておくことで、エラーが消える。

参考リンク
jQueryのajaxでphpを呼び出す。(cakephp3) - Qiita
PHP: ob_start - Manual
PHP の `headers already sent` エラーはどう直したらいいですか? - スタック・オーバーフロー

Windows上にてRuby 2.3でBCryptを使う方法

開発環境はWindows 7 Professional(32bit)+Ruby 2.3.3p222+Rails 4.2.1。

Railsのログイン処理にBCryptを使いたかったのですが、どうも、うまくいくのが、Ruby 2.2までらしくて、Ruby 2.3以降はWindows環境でやる場合は、自分でビルドしなければならないみたいです。ruby2.3だとDevKit, 2.4以降だとMSYS2によって可能。
(MacLinuxの場合は、インストールと同時にビルドするので問題なくできるようです。)ビルドというのは、おそらく.soファイル(Windowsでいう.dllファイル)を作ることでしょう。

そこで、Rubyのファイルを色々、いじっていると、予想外なことにできたので、書いておきます。他のサイトだと、ここまで具体的な手順で書いてなかったので、もし、同じ問題を抱えている人がいれば、何か助けになると思います。

1.gem install bcryptでインストール
bcryptがすでにインストールされている場合は、gem uninstall bcryptで削除しておく。
これで、bcrypt-3.1.11-x86-mingw32が作られます。
2.コマンドプロンプトにて、cd c:\devkit(devkitのあるディレクトリをカレントディレクトリにする)と入力し、続けて、ruby dk.rb init、続けて、ruby dk.rb installを入力。
3.gem install bcrypt --platform rubyを入力。これでビルドされる。
これで、bcrypt-3.1.11が作られます。
4.C:\Ruby23\lib\ruby\gems\2.3.0\gems\へ移動する。
5.bcrypt-3.1.11/bcrypt/libフォルダからbcrypt_ext.soをコピーする。
6.bcrypt-3.1.11-x86-mingw32/libフォルダ内に、2.3というフォルダを作成する。
そして、その中に、先ほど入れたbcrypt_ext.soをペーストする。

簡単なスクリプトを書く。

require "bcrypt"
pass = "password"
puts BCrypt::Password.create(pass)

これで60文字分、生成される。

BCryptの代替案として、digest::SHA512をやっていたのも、ついでに書いておく。
1.コマンドプロンプトにて、gem install digestと入力し、digestをインストール。
2.コードを書く。

require "digest/sha2"
pass = "password"
puts Digest::SHA512.hexdigest(pass)

16進数の文字列が、128文字分、生成される。

今回の得られた教訓として、
1.Windowsは開発環境として向いていない(環境を整えるという本質とは関係ないところに手間がかかることが多い)
2.Railsで実行するまえに、簡単なrubyスクリプトを書いて、動くのか検証すること
3.こうやって苦労した経験は後々、役に立つのだろうか?

参考リンク
【Rails】bcryptインストール時の"cannot load such file -- bcrypt_ext"エラー対応【Windows】 - Qiita
・ここのサイトのコメント欄が参考になりました。
SHA-256ハッシュ値 - Qiita
class Digest::Base (Ruby 2.5.0)

Railsでマイグレーションをする方法

マイグレーションスクリプトで作ったデータベースの値を変更したい場合、

カラムの追加
Modify + 大文字から始まるテーブル名のマイグレーションスクリプトを作る
ruby bin/rails g migration ModifyMembers
例えば、membersテーブルに、phoneカラムを追加したい場合、changeメソッド内に、add_columnメソッドを用いる。
add_column :members, :phone, :string
add_columnは、テーブル名、カラム名、カラムの型の順番で指定する。

class ModifyMembers < ActiveRecord::Migration
  def change
	add_column :members, :password, :string
  end
end

そして、
ruby bin/rake db:migrate
を実行すると、カラムが追加している。

ruby bin/rake db:migrate:status
現在のマイグレーションのバージョンを知ることができる。
up印がついているのが実行済みのマイグレーション
古いバージョンに戻すためには、
ruby bin/rake db:rollback
が使える。直前に行われたマイグレーションを1つだけ取り消す。
これをマイグレーションの「ロールバック」という。
一度に複数個のマイグレーションロールバックしたい場合は、
ruby bin/rake db:rollback STEP=3
とSTEPオプションを付加する。

他にも、
カラム名の変更
rename_column(テーブル名,カラム名,新しい名前)
カラムの型の変更
change_column(テーブル名,カラム名,型,オプション)
カラムの削除
remove_column(テーブル名,カラム名)

change_columnとremove_columnはchangeメソッド内に入れてロールバックするとエラーになる。
ロールバックを行うなら、upメソッドとdownメソッドに2つを記述する。
upメソッドにマイグレーションを進める処理を書き、downメソッドに取り消す処理を書く。

def up
	rename_column :members, :name, :nickname
	change_column :members, :gender, :integer, null: false, default: 1
end

def down
	rename_column :members, :nickname, :name
	change_column :members, :gender, :integer, null: false, default: 0
end

Railsでテストする方法

■テストスクリプトを用いる

test/models/member_test.rbコメントアウトを外して、
ruby bin/rake db:migrate RAILS_ENV=test
というコマンドを実行。テーブルが加えられるのデータベースは、テスト用になる。
ruby bin/rake test test/models/member_test.rb
というコマンドを実行するとエラーが発生。
f:id:k01ken:20180116030944p:plain
Gemfile内の、

group :development, :test do
  # Call 'byebug' anywhere in the code to stop execution and get a debugger console
  gem 'byebug'

  # Access an IRB console on exception pages or by using <%= console %> in views
  gem 'web-console', '~> 2.0'
end

group :development do
  # Call 'byebug' anywhere in the code to stop execution and get a debugger console
  gem 'byebug'

  # Access an IRB console on exception pages or by using <%= console %> in views
  gem 'web-console', '~> 2.0'
end

に変更した。

Railsでメッセージを日本語化する方法

開発環境はWindows 7 Professional(32bit)+Ruby 2.3.3p222+Rails 4.2.1。

config/application.rbで、config.i18n.default_localeのコメントを外して、値を、:jaに変更する。サーバー起動中の時は、終了して、再起動すること。

Gemfileを表示して、gem 'sqlite3'の次の行に、
gem 'rails-i18n'
を追加して、
bundle install
を実行。

rails-i18n/ja.yml at master · svenfuchs/rails-i18n · GitHub
上記のサイトから、右上の『Raw』ボタンを押して、Ctrl+A→Ctrl+Cで全文コピーし、テキストファイルに貼り付けて、ja.ymlという名称で、config/localesフォルダに保存する。

これによって、モデルは日本語用のロケールテキストからエラーメッセージを読み込むようになる。

後は必要に応じて、YAMLファイルに英語と対になった日本語を追加していくだけ。

参考リンク
Railsで日本語化対応にする方法 - Qiita
Rails で I18n を使って日本語化 - Qiita
Railsで日本語サービスを作るときのテンプレート - Qiita

Railsでルーティング設定を行う

開発環境はWindows 7 Professional(32bit)+Ruby 2.3.3p222+Rails 4.2.1。

ルーティングの設定は、config/routes.rb内で行う。
Rails.application.routes.draw do ~ endの間に加えたコードがルーティングの設定になる。

例えば、『ルート/about』というパスを実現したければ、TopControllerのaboutアクションと結び付けます。
また、about_pathメソッドが、『ルート/about』を返すようになります。
config/routes.rb

Rails.application.routes.draw do
	root "top#index"
	get "about" => "top#about", as: "about"
end

app/controllers/top_controller.rbでaboutアクションを追加します。

class TopController < ApplicationController
	def index
	end

	def about
	end
end

app/views/topフォルダに、about.html.erbを作成します。
以下はその中身。

<h1>このサイトについて</h1>

これで、ruby bin/rails sでサーバーを立ち上げて、http://localhost:3000/aboutにアクセスすれば、今作ったページが表示されることになります。
f:id:k01ken:20180115182344p:plain

ルーティング設定をしていないページにアクセスすると、ルーティングエラーが発生します。他にも、ルーティング設定を書き間違えたり、HTTPメソッドが合わない場合や、app/assetsやpublicの下に存在しないファイルにアクセスしようとしてもエラーになります。
例えば、http://localhost:3000/abooutにアクセスすると、
f:id:k01ken:20180115185138p:plain
となります。

rootメソッドに「"コントローラ名#アクション名"」を指定すると、パスが「/」の場合のルーティングを指定できます。
特定のパスに対応するアクションをGETメソッドで呼び出すには、
get "パス" => "コントローラ名#アクション名"
例えば、GETメソッドでTopControllerのaboutアクションを呼び出したいときは、

get "about" => "top#about"

『ルート/login』というパスでPOSTメソッドでSessionsControllerのloginアクションを呼び出したいときは、

post "login" => "sessions#login"

『ルート/info/company』というパスのように、"info/company" => "info#company"と指定する場合は、次のように省略できます。

get "info/company"

また、ルーティングにはasオプションが使える。例えば、helpという名前のルーティングを作ると、コントローラやビューでhelp_pathというメソッドを呼び出すと、/helpという文字列が返ってきます。また、link_toメソッドやredirect_toメソッドで、:helpのように、シンボルでパスを指定します。これは、パスを返すメソッドから_pathを覗いたものを指定します。

get "help" => "documents#help", as: "help"

パラメータをパスに埋め込みたい場合は、:yearのように、「コロン+パラメータ」のようにします。例えば、『articles/2015/04』というパスによってArticlesControllerのshowアクションが呼び出され、params[:year]で「2015」、params[:month]で「04」が取り出せるようにします。

get "articles/:year/:month" => "articles#show"

CakePHPで、生成されたSQLクエリを見る方法

開発環境は、Windows 7 Professional(32bit)+XAMPP v3.22+CakePHP 3.5.8。

開発段階で、debugkitを使うならば、データベースに接続したページで、debugkitのSql Logを見ること。

使わないなら、config/app.php内のDatasourcesのlogをfalseからtrueにするだけ。そうすると、logs/queries.logファイルが生成されている。
f:id:k01ken:20180108232911p:plain

参考サイト
CakePHP3でファイルにSQLのログを出力する方法 | ハックノート