【rails】railsでよく使うメソッドまとめ その1
勉強する中で出てきたrailsメソッドを忘れないようにメモ。
最終的にはtopページの検索から楽に調べられるようにしたい。。。
【ruby】rubyでよく使うメソッドまとめ その1
勉強する中でわからなくてググったメソッドをガンガンまとめておく。
続きを読む【rails】複数のjsonデータを返す方法
発生経緯
railsアプリを作る時、Vue.jsを使うと基本的にrailsのデータはAPIで返すことになる。 ということは最後の出力をjson形式で返すことになるわけだが、ここでかなりつまづいたので忘れないようにメモしておく。
単体jsonデータの場合
class QuestionsController < ApplicationController def index @question = Question.new @questions = Question.all.order(created_at: "DESC") respond_to do |format| format.html format.json end end end
QuestionテーブルはUserテーブルと紐づいており、Questions(多):User(1)の関係になっている。この時 index.json.jbuilder
を使うとこんな感じになる。
json.array! @questions, :title, :content, :user
一応これで@questionsに関連したUserもjson形式で送ることはできた。が、これだけのためにjbuilderを使うのはもったいない。
そこで、Controllerの方でまとめてみる。
class QuestionsController < ApplicationController def index @question = Question.new questions = Question.all.order(created_at: "DESC") respond_to do |format| format.html format.json { render json: questions, include: [:user] } end end end
include
を使うことで、関連したテーブルのデータも送ることができるようになる。jsonの中身を確認すべくhtml端子を .json
にしてみる。
[{"id":1,"title":"hoge","content":"huga","user_id":1,"created_at":"2019-10-14T10:33:14.247+09:00","updated_at":"2019-10-14T10:33:14.247+09:00","user":{"id":1,"email":"hoge@gmail.com","created_at":"2019-10-13T16:58:27.516+09:00","updated_at":"2019-10-13T16:58:27.516+09:00","name":"foo"}}]
ちょっと見辛いが、questionのuser_idに紐づいたUserのデータが一緒に入っているのがわかる。
複数のjsonデータの場合
では、showメソッドでquestionに紐づいたanswerも一緒に送るにはどうすれば良いか?
class QuestionsController < ApplicationController def show @question = Question.find(params[:id]) @answers = Answer.where(question_id: params[:id]).order(created_at: "DESC") @answer = Answer.new respond_to do |format| format.html format.json end end end
ここで得たいのはquestionのデータとanswersのデータ。
ひとまず show.json.jbuilder
に書いてみる。
json.question @question, :title, :content, :user json.answers do json.array! @answers, :text, :user end
複数の時も上のようにcontrollerにまとめるには .to_json
を使うとできなくはないが、Vueで受け取ったデータに \
が死ぬほど入ってきた…
まとめ
単体jsonデータはcontrollerにまとめることができたけど、複数のデータのまとめかたがいまいちわからなかった…ここは忘れずに改善する必要がある。
【heroku】railsをデプロイした時に出たエラー
発生経緯
Vueの勉強がてらローカルで作っていたrailsアプリをherokuにデプロイしようとコマンドを叩いた。
$ git push heroku origin
すると見たことのないエラーが発生
remote: -----> Detecting rake tasks remote: remote: ! remote: ! Could not detect rake tasks remote: ! ensure you can run `$ bundle exec rake -P` against your app remote: ! and using the production group of your Gemfile. remote: ! Activating bundler (2.0.1) failed: remote: ! Could not find 'bundler' (2.0.1) required by your /tmp/build_6b1f695b994476ef74ee9e7d5cc6b6f0/Gemfile.lock. remote: ! To update to the latest version installed on your system, run `bundle update --bundler`. remote: ! To install the missing version, run `gem install bundler:2.0.1` remote: ! Checked in 'GEM_PATH=vendor/bundle/ruby/2.5.0', execute `gem env` for more information remote: !
出てくることは少ないかもしれないけど、忘れないようにメモ。
とりあえずエラーの中身確認
どうもbundlerをインストールせいと言っているので、先ずはバージョン確認。
$ bundler -v Bundler version 2.0.1
あれ?あってる… ってことはrailsのバージョンとbundlerのバージョンがheroku推奨とアンマッチの可能性がある。
解決手法
というわけで、railsとbundler両方ともアップデートをかけることにする。
$ brew update && brew upgrade ruby-build $ rbenv install 2.6.3 # railsは他でも使っているので、ひとまず適用させたいフォルダのみバージョン変更 $ rbenv local 2.6.3 # bundlerも最新のやつを入れておく $ gem install bundler -v 2.0.2 # このまま入れるとgemfileが書き変わらないので、一旦削除 $ rm Gemfile.lock $ bundle install
ここまで行うと .ruby-version
が新たに作られるので、忘れずに .gitignore
に追加しておく。
gitにpushし終えたら再びデプロイトライ。
$ git push heroku origin remote: Verifying deploy... done. * [new branch] master -> master
無事デプロイ完了!
デプロイまでしたら
DBを作るのを忘れがちなので、気をつける!
$ heroku run rails db:migrate
これで、無事にサイトが表示できるようになった。
【rails】PostgreSQLを使った環境構築
PostgreSQL Accountの作成
仕事でPostgreSQLを使っていたので、Accountを作るところから。
$ sudo -u postgres psql PASSWORD= <PCのパスワード> postgres=# create role <username> with createdb login password '<password>'; # usernameとpasswordはあとで使う postgres=# \q $ rails new <appname> -d postgresql # オプションでpostgresqlを指定 $ cd <appname>
これでPostgreSQLを使ったRailsができた。
dotenv-railsの追加
PostgreSQLのdatabse.ymlを編集する前にgemを追加しておく。
gem 'dotenv-rails'
追加したら bundle install
でgemを適用させる。
$ bundle install $ touch .env.local #今回はローカル作業用にlocalファイルを作成
今回は .env.local
を作ったが、これをコピーしたければ
cp .env.local .env.<好きな名前>
で作れる。
config/database.ymlの編集
default: &default adapter: postgresql encoding: unicode pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> # この下に3行追加していく username: <%= ENV['USER'] %> password: <%= ENV['PASSWORD'] %> host: <%= ENV.fetch('HOST', 'localhost') %>
続いて先ほど作った .env.local
に必要な情報を追加していく。
USER=<username> PASSWORD=<password> HOST=localhost # 別環境で使うことがあればそれを指定
.gitignoreに追加
.env.local
を作って環境変数を指定してあげているので、GitHub上にファイルを上げないように設定してあげる。
# dotenv .env*
これで、.env
から始まるファイルはGitHub上に上がらない。
リモートリポジトリの作成
ここまで出来たらGitHubにデータを転送していく。
$ git init # GitHubと接続 $ git add -A # 一回ファイルをコミットできる状態にしておく $ git rm --cached .env.local #さっき作った.env.localは上げないように削除 $ git commit -m"first commit" # コメントはなんでも良い
GitHubでリポジトリを作ったら、SSHのURLをコピーしておく
$ git remote add origin <コピーしたURL> $ git push -u origin master
これで、localで使ったPostgreSQLのusernameとpasswordをGitHub上に公開しないで住むようになった。
【Vue.js】クラスのデータバインディング
クラスのデータバインディング
クラスのデータバインディングの基本の書き方はこうなる。
例えば文字を大きくする場合
JavaScript
var vm = new Vue({ el: '#vm', data: { isLarge: true } })
HTML
<div id="vm"> <p> Hello <span v-bind:class="{large: isLarge">Vue.js!</span> </p> </div>
CSS
.large { font-size: 36px; }
isLargeがtrueの時はVue.js!は大文字になる。
また、v-bind:classは複数適用が可能でカンマで繋げれば良い。
JavaScript
var vm = new Vue({ el: '#vm', data: { isLarge: true, hasError: true } })
HTML
<div id="vm"> <p> Hello <span v-bind:class="{large: isLarge, 'text-danger': hasError}">Vue.js!</span> </p> </div>
CSS
.large { font-size: 36px; } .text-danger { color: red; }
配列構文での記述
cssの内容をdataの中に記述して、配列構文でv-bindを書くことができる。
JavaScript
var vm = new Vue({ el: '#vm', data: { largeClass: 'large', // cssのクラス名 dangerClass: 'text-danger' } })
HTML
<div id="vm"> Hello <span v-bind:class="[largeClass, dangerClass]">Vue.js!</span> </div>
クラスの数が増えるとわかりづらくなるので、dataオプションにclassObjectのプロパティを作ってまとめて管理する。
JavaScript
var vm = new Vue({ el: '#vm', data: { classObject: { large: true, // クラス名 'text-danger': true } } })
HTML
<div id="vm"> Hello <span v-bind:class="classObject">Vue.js!</span> </div>
随分とみやすくなった。
三項演算子を使ってみる
三項演算子を使ってクラスの条件を分けてみる。
JavaScript
var vm = new Vue({ el: '#vm', data: { largeClass: { large: true, 'bg-gray': true }, dangerClass: { 'text-danger': true }, isLarge: true } })
HTML
<div id="vm"> <p> Hello <span v-bind:class="[isLarge ? largeClass : '', dangerClass]">Vue.js!</span> </p> </div>
CSS
.large { font-size: 36px; } .text-danger { color: red; } .bg-gray { background-color: gray; }
isLargeがtrueの時、largeClassが適用される。
falseの時は三項演算子で''となっているので適用から外れる。
また、dangerClassは常に適用される。