railsコマンドでファイル名を指定してseedデータを入れる方法
バージョン
テストデータやマスタデータの挿入
Railsにはデフォルトでdb/seeds.rb
というファイルが生成されていて、
ここにインサート文などを書いておくと、
rails db:seed
でデータをDBに挿入してくれます。
指定したseedファイルだけを挿入
ただ、特定のデータだけ挿入したいというときには、
毎回、seeds.rbを書き換えないといけません。
1回だけならまだいいですが、間隔をおいて何回も挿入しなければいけないときは、だいぶめんどくさいです。
そんなときのために、このような
rails db:seed_from_file SEED_FILENAME='seeds/ファイル名'
railsコマンドの引数でファイル名を渡して、seedデータを挿入する方法を書いていきます。
なお、ディレクトリの構成はこんな感じです。
root/ lib/ tasks/ db.rake db/ seeds/ 01_sample_seeds.rb 02_sample_seeds.rb 03_sample_seeds.rb
挿入したいテストデータをdb/seeds配下のファイルに記載している想定です。
タスクファイルを作成する
rails g task ファイル名
でタスクファイルを作成することができます。
今回は、rails g task db
とコマンドを叩き、lib/tasks/db.rake
を作成しました。
どのseedファイルを実行するか記載
タスクファイルが作成できたら、中身を書いていきます。
今回叩きたいコマンドrails db:seed_from_file SEED_FILENAME='seeds/03_sample_seeds.rb'
に合わせて書いていきます。
今回はこのような感じで書いてみました。
namespace :db do desc 'Load the seed data from SEED_FILENAME' task :seed_from_file => 'db:abort_if_pending_migrations' do seed_file = File.join(Rails.root, 'db', ENV['SEED_FILENAME']) if File.exist?(seed_file) puts "seeding -- #{ENV['SEED_FILENAME']}" load(seed_file) else puts "the seed file does not exist." end end end
以下から各メソッドの解説です。
・namespace
apiのルーティングなどでよく使われるnamespaceメソッドですが、
ここではコマンドを叩くときのコマンド名みたいなものです。
これをネストしていくとコマンドもネストされます。
namespace :apple do namespace :banana do namespace :orange do task :eat do #省略 end end end end
であればrails apple:banana:orange:eat
という風なコマンドになります。
・desc
メソッドの説明文になります。
rails -T
でタスクを表示したときに一緒に説明文が表示されます。
・task
実行するメソッド名です。
成功していないマイグレーションがあるとデータを入れるのはよくないので、先に'db:abort_if_pending_migrations'
を実行するようにしています。
・File.join
seedファイルまでのパスを生成するメソッドです。
コマンドの引数であるSEED_FILENAMEからファイル名を受け取り、実行するファイルを特定します。
Rails.root, 'db'
と記載しておくことで、コマンドからの引数であるファイルまでのパスを省略できます。
load(seed_file)で実行しています。
まとめ
僕のカップル専用家計簿アプリでは、
月毎に合計値や前月などを計算しています。
そのため、月が変わると計算する値がなく、
真っ白になってしまうページがあり、
実装するときに不便になるので、
今回のようなテストデータを入れられるタスクを作りました。
(まだ毎月挿入するシードデータを作ってないですがw)
いろんなメソッドを使いますが、どれも単純なものなので、
試してみてください。
改善点あれば是非ご指摘ください。
【Ruby】もっと早く知っていればよかったmapメソッド
mapメソッド
mapメソッドとは、配列やハッシュに対して使えるメソッドで、要素の数だけ繰り返しブロックを実行し、ブロックの戻り値を集めた配列を作成して返します。
↑と、Rubyリファレンスには書かれております。
このメソッドを知った時は、このメソッドを知らないのは罪だと思いましたwww
なぜなら、このメソッドを知らない自分はこんなことをやったらからです。
mapメソッドを知らないとき
半年ほど前から、カップル専用の家計簿アプリを作っているのですが、家計簿には当然カテゴリ分けがあります。
実装していく中で、特定の条件のカテゴリのidを集めたいと思いました。
まず、何回も使わなければいけないと思ったので、モデルにscopeを追加しました。
extract_category, -> {unscope(:order).select(:category_id).distinct.pluck(:category_id)}
すでにこのスコープを作るのにも一苦労しました。
orderが既にかかったものにselectなどがかけられなかったのです。
次に、このメソッドを呼び出すときです。
category_ids = (current_user_expenses.extract_category + partner_expenses.extract_category)
このように、scopeを使ったとしても、何回もそのscopeを呼び出していました。
mapメソッドを知った後
それがmapメソッドを使うとこんなにも簡単に書けます。
category_ids = (current_user_expenses + partner_expenses).map{|i| i.category_id}
scopeなどは必要なかったんです。
mapを使えばすごく簡単に書けました。
エイリアスメソッドとして、collectメソッドもあります。
どちらも同じ挙動ですが単語のニュアンスとして、collectのほうが読んでいてしっくり来るときがあります。
実は上記の場合は、collectのほうが僕は好きですね。
上記とは変わっていますが、実際の改修したコード こちらになります。
mapメソッドのようなブロックを使った便利メソッドは他にもいくつかあるので、しっかり勉強しようと思いました。
Rails5.1にReactを導入
react-railsとwebpackerの場合
インストール
Gemfileに以下を追加して、bundle install
gem 'react-rails' gem 'webpacker'
installコマンド実行
rails webpacker:install rails webpacker:install:react
これでReactに必要なフォルダやファイルが生成されてReactが入る。
webpackerによりapp/javascript/packsにhello_react.jsxが生成されているのがわかる。
これはReactを使って、「Hello React」を表示させる簡単なものである。
そして、webpackerにより使えるようになったを追加していく。
Reactを使って「Hello React」を表示
コントローラー、ビュー、ルーティングを生成
rails g controller sample index
app/views/layouts/application.html.erbに以下のようにjavascript_pack_tagを追加
<!DOCTYPE html> <html> <head> <title>CalculatorReact2</title> <%= csrf_meta_tags %> <%= stylesheet_link_tag 'application', media: 'all' %> <%= javascript_include_tag 'application' %> <%= javascript_pack_tag 'hello_react' %> </head> <body> <%= yield %> </body> </html>
この状態でrailsサーバーを起動すると、「Hello React」が表示される。
react-railsのReactコンポーネントの作成
react-railsではReactコンポーネントは以下のコマンドで作成できる。
rails g react:component コンポーネント名
そうするとapp/javascript/component/ の配下にコンポーネント名.jsが生成される。
例えば、rails g react:component calculator だと
app/javascript/component/calculator.jsが生成される。
あとは好きなviewのそのコンポーネントを使いたいところで
<% react_component 'calculator' %>
というようなview helperを記載しておくと、app/javascript/component/calculator.jsを読み込んでくれる。
app/views/layouts/application.html.erbには<%= javascript_pack_tag 'application' %>
を記載しておけば読み込んでくれる。
react-rails のapplication.js
webpackerと比べて以下が追加されている。
var componentRequireContext = require.context("components", true) var ReactRailsUJS = require("react_ujs") ReactRailsUJS.useContext(componentRequireContext)
rails g react:componet で作成したコンポーネントファイルに以下を書かなくてもいい。
import ReactDOM from 'react-dom'; ReactDOM.render( <Game />, document.getElementById('root') );
webpackerのみ場合
react-railsがないとrailsサーバーを起動しても、Reactは動いてくれない。
railsサーバー起動後、別ターミナルで以下を叩きコンパイルする
./bin/webpack-dev-server
このままではreactを変更するたびにコンパイルしなければいけないので、
package.json
に以下を追加し、
"scripts": { "start": "rails s & bin/webpack-dev-server" },
yarn start
で同時に行ってくれる。
webpackerで読み込むコンポーネント
コンポーネントを入れるフォルダを作成
webpackerのみの場合、app/javascript/配下にはpacksフォルダしか生成されないので、ここで任意のフォルダを作成する。
app/javascript/calculator/
コンポーネントファイルを作成
app/javascript/calculator/calculator.js
import React, { Component } from 'react'; class Calculator extends Component { render() { return ( <div> <h1>Calculator is working!!</h1> </div> ) } } export default Calculator;
app/javascript/calculator/index.js
import React from 'react'; import ReactDOM from 'react-dom'; import Calculator from './calculator'; document.addEventListener('DOMContentLoaded', ()=> { const container = document.body.appendChild(document.createElement('div')); ReactDOM.render(<Calculator/>, container) })
Viewで読み込む
app/javascript/packs/calculator.js
を作成し、その中に読み込むフォルダを記載
import 'calculator'
そうするとapp/javascript/calculator/ 配下のコンポーネントをimportする。
あとはapp/views/layouts/application.html.erb
のHEADタグ内にreact-railsの時と同じようにjavascript_pack_tagを追加し、app/javascript/packs/calculator.js
を指定してあげるとviewで読み込んでくれる。
<!DOCTYPE html> <html> <head> <title>CalculatorReact2</title> <%= csrf_meta_tags %> <%= stylesheet_link_tag 'application', media: 'all' %> <%= javascript_include_tag 'application' %> <%= javascript_pack_tag 'calculator' %> </head> <body> <%= yield %> </body> </html>
HerokuとS3を連携
S3の初期設定
この記事のバケットの作成のところ(Imagemagikの導入の手前)までの通りすればできました。
【Rails】S3へ『CarrierWave+fog』を使って画像アップロードする方法 | vdeep
Gemfile
こちらを追加し、bundle install
gem 'fog-aws', group: :production gem 'carrierwave', '~> 1.0'
○_uploader/rbに以下を追記
if Rails.env.production? storage :fog else storage :file end
carrier_wave.rb
$ touch config/initializers/carrier_wave.rb
でファイル作成
作成したファイルに以下を追記
require 'carrierwave/storage/abstract' require 'carrierwave/storage/file' require 'carrierwave/storage/fog' CarrierWave.configure do |config| if Rails.env.production? config.storage = :fog config.fog_provider = 'fog/aws' config.fog_credentials = { # Amazon S3用の設定 :provider => 'AWS', :region => ENV['S3_REGION'], :aws_access_key_id => ENV['S3_ACCESS_KEY'], :aws_secret_access_key => ENV['S3_SECRET_KEY'] } config.fog_directory = ENV['S3_BUCKET'] else config.storage :file config.enable_processing = false if Rails.env.test? end end
ここの下の画像の人の例を参考にしました。
herokuの環境変数の設定
S3の初期設定で取得できているcredentials を前項のENVの[ ]内の変数を下記コマンドで設定していく。
heroku config:set S3_REGION= heroku config:set S3_ACCESS_KEY= heroku config:set S3_SECRET_KEY= heroku config:set S3_BUCKET=
※credentialsがわからなくなったら、アクセスキーIDとREGIONは次から確認できる。 ルートアカウント認証情報を使用してサインイン→ヘッダーのユーザ名のdropdownからセキュリティ認証情報を選択→左のユーザー→ユーザーを選択→認証情報タブ secret keyはどう確認するかわからないからユーザーを作った時にcredentials.csvをダウンロードしておこう!
デプロイ
これでデプロイしてみるとできている。できなければ、DATABASEのリセットとかを試してみるといいかも。
アコーディオン機能の三角がくるっと回るやつの設定方法
html
<dt><p><img src="./images/triangle.png" class="arrow"> 学歴</p></dt> <dd><p>長岡技術科学大学 環境工学課程卒業</p></dd> <dt><p><img src="./images/triangle.png" class="arrow"> 実績</p></dt> <dd><p>オーストラリアワーキングホリデー<br>6,000kmヒッチハイク旅制覇</p></dd> <dt><p><img src="./images/triangle.png" class="arrow"> SNS</p></dt>
1. クリックファンクションを設定
2. クリックした要素の三角の画像を取り出す$('img', this)
3. アコーディオンを開くと同時に2で取り出した要素にcssのスタイルを設定.toggleClass('dropdown_toggle')
$(function(){ $('.side_menu dd').hide(); $('.side_menu dt').click(function(e){ // toggleClassは開くときにクラスを当てる // thisの子孫要素である'img'を取り出す $('img', this).toggleClass('dropdown_toggle'); $(this).next('dd').slideToggle() }); })
4. 3で設定される、三角を回転させるためのスタイルを設定
.dropdown_toggle { -webkit-transform: rotate(90deg); transform: rotate(90deg); }
バリデーションの日本語表示の仕方
1. 辞書ファイルをダウンロード
まずプロジェクトのトップで下記コマンドを実行して、辞書ファイルをダウンロード。プロジェクトのトップとはアプリ名がsampleであれば「:~/workspace/sample (master) $ 」のようにディレクトリを移動してからという意味
2.モデル用の辞書ファイルを分割して作成
そうするとconfig/locales/に「ja.yml」というファイルが作成されているのがわかる。
このファイルは長いので管理が大変になるため、モデル用のファイルはconfig/locales/下に別で作成する。
ファイル構成例
3. ファイルに辞書を記載していく。
※このときインデントが少しずれているだけで読み込まれないので注意。
上記だとモデルcontactの属性値の辞書を記している。
4. しっかり読み込ませる
辞書が完成したら、このファイルは自動では読み込まれないので、config/application.rb に下記を追加して、起動時に読み込まれるようにしておく。
これで Rails を起動し直すと、validates とかのエラーメッセージが日本語化されている
Rails5 バリデーションの書き方
バージョン
Rails 5.1.4
対象
下図のようなお問い合わせフォームのバリデーションを作成していく。
文法
validates シンボル1,シンボル2, シンボル3,・・・, バリデーションの種類: {オプション: true}
※カラムのシンボル名は→「:」+「カラム名」
※「バリデーションの種類:」の後スペースが必要。presence:trueのようにスペースがないと:trueをシンボルだと認識してしまう。
バリデーションの種類やそのオプションはガイドを参考に
※ガイドに書いてある「%{value}」はコントローラーから送られてくる変数ではなく、バリデーションの種類とそのオプションに応じて使える変数である。too_longの%{count}も同じ
こんな感じ・・・
2行目は名前の欄に記入された文字へのバリデーション。
presence: は空欄の場合、エラーを発生させるバリデーションの種類。
length: は文字数設定。
maximum: や too_long: はlengthのオプション。
8行目の
format: は設定したパターンと同じでないときエラーを返すもの
message: はformatのオプション。エラーが発生したときに
「・(カラム名) (メッサージ)」の形でエラー文を表示
formatだけでなく色んなバリデーションへつけられる。
エラー結果↓↓↓
ただ、上記だけでは上のようにモデルの属性値は日本語になりません。
モデルの属性値の日本語化はこちらにまとめました↓↓↓
フレキシブルなメソッドでの書き方
メソッドであればより柔軟にバリデーションを設定できる。下のコードは上のコードとほぼ同じ結果になる。メソッドを使うことで日本語翻訳設定をしなくても日本語でエラー文を表示できる。
メソッドにするときは「validates」ではなく「validate」と単数形で「:メソッド名」
引数の渡し方は不明。
とりあえず「validate :メソッド」にすればバリデーションするためのパラメーターが渡される。
name, email, contentのようにカラム名を引数のような形で扱う。
バリデーションを書いているときに・・・
バリデーションのコードを書いていて試したいときにはrails cが使える。
rails cで仮にエラーが出るように登録してみる
・変数.vaild? →検証できてるかどうか
・変数.errors.full_messages →エラー内容が確認できる
・変数.errors →エラー発生時どんな内容のエラーか確認できる。
・変数.errors.count →エラーの数
・変数.errors.full_messages →エラーのメッセージ。
また、複数のターミナルを開いて、このターミナルではサーバーを起動。こちらのターミナルではrails cを起動。などにしておくと、いちいちサーバーを落としたりしなくてもいい。