niki12260714の日記

フリーランスのITエンジニアの呟き。

親子孫の3つのテーブルを関連付けてデータ取得

 A,B,Cというテーブルがあって、それぞれ親→子→孫という関係とします。

Aモデル:
has_many:bs(複数形)

Bモデル:
belongs_to:a(単数形)
has_many:cs(複数形)

Cモデル:
belongs_to:b(単数形)

ここで、cモデルにあるカラムをwhere句にして、Aモデルの値を取るとします。
やり方としては、

・Cモデルにscopeを定義する
scope :c_scope, ->(id) {where("c_id = ?", id)}

・Bモデルで、Cモデルをマージして、Cのスコープを呼び出すスコープを定義する
scope :b_scope, ->(id){
   joins(:cs).merge(C.c_scope(id))
}

・Aモデルで、Bモデルをマージして、Bのスコープを呼び出すスコープを定義する
scope :a_scope, ->(id){
   joins(:bs).merge(B.b_scope(id))
}

で、Aモデルのスコープ(a_scope)を呼び出すことで、Cスコープまで値を渡す。

……本当に合っているか不明。もうちょっとスマートに書けないものかな?

親子関係にあるテーブルに一度にデータを保存する

親テーブルにデータを作ったら、そのidを使って子テーブルにもデータを入れたい場合がありますよね。
というのをやってくれるのが、buildです。

まず最初に、各モデルに親子関係を記述します。
※Aの子供がB、Bの子供がCとする

Aモデル:
has_many:bs(複数形)

Bモデル:
belongs_to:a(単数形)
has_many:cs(複数形

Cモデル:
belongs_to:b(単数形)

※1:1の場合はhas_one:単数形になることに注意。そしてこの場合、buildではなく、build_xxになる。
参考:http://codenote.net/ruby/rails/1778.html

で、親のインスタンスを作成したら、子供のインスタンスをbuildする。

oya = A.new
child = oya.bs.build
childchild = child.cs.build

※親から見た子供は複数形で記述

※親から孫の生成はできない(例:oya.bs.cs.buildみたいにはできない)

※子供のインスタンスに固定値を入れておきたい場合は引数に記述する
参考:build - リファレンス - - Railsドキュメント

実際にDBに保存する場合は、親だけを保存すれば、一緒に子供のテーブルにも保存してくれるし、親のIDも自動的に取得して入れてくれる。

oya.save

AWS Cloud9でPostgreSQLに対しrake db:migrateが失敗する

ここら辺、自動でやってくれるDBとかで開発していたんで、知らないから躓いたところでした。
前回の記事の続きです。

niki12260714.hatenablog.com

ここの記事で、「confファイルが見つからなかった」とありますが、ここが問題でした。

migrateのファイルを作り、「rake db:migrate」を打つと、「FATAL: Ident authentication failed for user」というエラーが出て、rakeが失敗します。
調べてみると、見つからなかった「pg_hba.conf」というのが認証ファイルで、ここのデフォルト値が「OSのユーザーIDとpostgreのユーザーIDが一致していれば受け入れる(ident)」になっているのが問題ということ。
なので、ここを「パスワード認証(md5)」か「無条件で信頼(trust)」に書き換える必要があります。
しかしどうにも見当たらないので、ここは講師の人に聞いたところ

sudo vim /var/lib/pgsql94/data/pg_hba.conf

でいけますよ、ってことで、行けました!
※sudoでやらないと拒否されるフォルダの中にあるから、「vim」だけで打っていった時に見当たらなかったのだと思われる

で、md5に書き換えたのですが、そうすると今度は「sudo -u postgres psql」が効かなくなりました。
正確には、これを打つとパスワードを聞かれるのですが、postgresロールのパスワードを入れても拒否される。
ここは調べてもちょっと分からなかったんですが、Unixのroot権限が通らなくなったのが原因らしい?
仕方ないってことで、先ほどの「pg_hba.conf」を全てtrustに変更するとpsqlを打てるようになりました!
ここでrake db:migrateを実行し、無事に通りました。

※ちなみにconfを書き換えたら「sudo /etc/init.d/postgresql94 restart」でポスグレを再起動する必要があります
※Cloud9は暫く触っていないとポスグレを止めちゃうので、通らなくなったと思ったら「sudo /etc/init.d/postgresql94 start」で開始する必要があります

AWS Cloud9でPostgreSQLを使ったrailsプロジェクトを立ち上げる

画面設計、DB設計に着手したんで、本格的に開発環境を整えていきます。
ということで、sqliteではなく、PostgreSQLを使って開発することになりましたので、その設定。
例によって、自分メモです。
参考にしたのはこちら。

qiita.com

お手本通り、コマンドを打っていきます。
PostgreSQLの本家サイトに行くと、最新バージョンが「10.4」になっているので、それを入れるべきだと思ったんですが、「sudo yum -y install postgresql94」青字のバージョン指定の番号が「104」だと「そんなパッケージ無いよ」って怒られたので、書き方分からずに、お手本に従いました。
まぁ必要になればアップデートすればよい話!

「sudo yum -y install postgresql94」←ポスグレのインストール
「sudo yum -y install postgresql94-devel」←ポスグレの開発環境のインストール
「sudo yum -y install postgresql94-server」←ポスグレサーバーのインストール
psql --version」←ポスグレが入ったか、ポスグレのバージョン確認

「sudo /etc/init.d/postgresql94 initdb」←ポスグレの初期化
「sudo /etc/init.d/postgresql94 start」←ポスグレの開始

「sudo -u postgres psql」←ポスグレに接続
  「postgres=# alter role postgres with password 'hogehoge';」←青字のところはポスグレに入ってますよの表示、実際に打つのはalterから。postgresロールのパスワードを任意に変更
  「postgres=# create database [database_name] owner [user_name];」←DB作成
        「postgres=# \q」←ポスグレから抜ける

※お手本だと次にconfファイルを書き換えていますが、これが見つからなかったので一旦棚上げ
→2018/5/21追記:ここを書き換えていないとrake dbが失敗します。リカバリーについてはこちら。

AWS Cloud9でPostgreSQLに対しrake db:migrateが失敗する - niki12260714の日記

次にRailsアプリを作成します

rails new myapp -d postgresql

出来たフォルダの中から「/config/database.yml」を開くと、「adapter:postgresql」となっているので、ポスグレ接続設定はできている模様。
なので、デフォルト接続のところに、DB接続のロール名とパスワードを記載しておきました。
以上終了。
あとは実際に作っていきます。

Gemfile編集後のbundle updateでコンフリクト発生時の対応

Gemfileに新しいgemを追加して、「bundle update」を叩くとエラーが出ました。

『Bundler could not find compatible versions for gem "actionview"』

ググってみると、バージョンが競合してますよ、ってことらしい。
「gem list」で今入っているgemのリストを見てみると、

actionview (5.1.6, 5.1.5, 5.1.4)』

となっており、確かに3つのバージョンが混在している。
なんでこうなっているのかを調べた結果、追加しようとしたgemのバージョンと既に入っているバージョンが合わないから、らしい。
入れようとしたgemは、以下のように書いていました。

『gem 'bootstrap-sass', '3.3.1'』

バージョン3.3.1を入れようとすると、既存のgemと衝突してしまう。
ならばどうするかというと、「このバージョン以上のものを」と指定してあげれば、bundle updateが適切なバージョンを入れてくれるとのこと。
なので、

『gem 'bootstrap-sass', '>= 3.3.1'』

という風に書き換え、bundle updateを実施、エラーが無くなりました!

AWS Cloud9で編集してからgithubへpushするまでのコマンド

gitを使い慣れていない自分のコマンドメモとして。

1.ブランチを切る
AWS Cloud9のbashで、今自分がいるブランチがmasterブランチであることを確認してから実施
「git checkout -b "ブランチ名"」
→実行すると指定したブランチ名に切り替わる

※この後にコード編集を行う。
編集して、ステージに乗せられるようになったファイルは「git status」で確認できる

2.ステージに乗せる
「git add.」

3.コミットする
「git commit -m "編集コメント"」
※編集メッセージが無いとハマって抜け出せないので注意。
→もしかしたら抜け出す方法があるかもしれないけどコメントは絶対に書いた方がいいので、コメント無しにする方法を探すメリットはないと思われる

4.masterブランチにマージする
「git checkout master」
「git merge "ブランチ名"」
→マスターブランチに入り、マスターからマージするイメージ
→この後に編集したブランチは削除する(しなくてもいい、どっちでも)
 「git branch -d "ブランチ名"」

5.githubにpushする
「git push -u origin master」
→ここでIDとパスワードを聞かれるので、入力する

以上!

AWS Cloud9でgithubからcloneしたRuby on Railsを動かす

当然っていえば当然なんですが、cloneしてきただけだと動かないわけで。
こちらを参考にして、動作させるべく四苦八苦。

tyoshikawa1106.hatenablog.com

こちらにある通り、「gem install bundler」を実施。
こっちは成功。
なので、次に「bundle install 」を実施したところ、「could not locate gemfile」というエラーが出ました。
gemfileはちゃんとあるんだけどなぁ……と思って、さらにググったところ、gemfileがあるフォルダに移動してからコマンドを叩かないと行けなかった模様。
cdコマンドでgemfileがあるディレクトリに移動してからコマンドを叩くと成功しました。
で、AWS Cloud9ではrailsの起動は「rails start」ではなく、「rails s -b $IP -p $PORT」というなんか長いオプションが必要になります。
bundle installが成功すると、これが効くようになります。
※やっていないと、そんなコマンド無いよ、と怒られます
サーバーを起動してから画面上部にあるPreviewを見てみると、「ActiveRecord::PendingMigrationError」というエラーが発生しています。
参考にしたページにもあり、またエラーをググると同じ現象が出ていますが、つまりはdbをmigrateしてないよ、っていうことらしい。
なので、「rails db:migrate」を実行しましたが、私の環境だとあるテーブルが存在しないよ、というエラーが出てしまいます。
つらつらエラーを眺めていたんですが、どうやらmigrateフォルダに入っている、作成中にmigrateしたなにかが足りなくなっている模様。
ぬーん、ならば更新履歴なんていらないんだから消しちゃえ。
ってことで、/db/migrateフォルダに入っている奴を全消ししたのに、再度「rails db:migrate」を実行、エラーなし。
再び「rails s -b $IP -p $PORT」を実行し、previewを押すとエラーは無くなり、白い画面になりました。
なので、ログイン画面に移動すべく、末尾に「/login/index」と足してEnterを押したら真っ白……
あれ?
ターミナル見ると、ちゃんと動いているっぽいけど……
でもまぁ、動かすところまではできました!