- 投稿日:2020-03-18T23:32:12+09:00
【12日目】jQuery(animate) Ruby(表示,変数,if)
はじめに
こんばんは。
progate jQuery終了しました!さっそくRubyに入っています。
では、本日のまとめをしたいと思います。本日の学び
- progate jQuery 上級 ページ内の移動
- progate Ruby1
jQuery
animateメソッド
$('.social-icon').hover( //マウスを乗せた時 function(){ $(this).animate({ //アニメーションを付ける 'font-size':'30px' //どうなるのか },300); },scrollTopメソッド
$('#top-btn').click(function(){ //クリックしたとき $('html, body').animate({ //htmlとbody 'scrollTop':0 //ページ最上部 }, 500); }); $('header a').click(function(){ //クリックしたとき var id = $(this).attr('href'); //クリックしたhrefを変数idとし、 var position = $(id).offset().top; //idのとび先の最上部を変数positionとし $('html, body').animate({ //htmlとbodyの 'scrollTop':position //positionの位置に移動 },500);Ruby
コンソール
puts "hellow World" #putsの後は半角スペース #文字列は""で囲う puts "こんにちは#{name}さん" #変数を文字列に入れ込む場合変数
name = "John" #変数の後に書いたコードに反映される #前のコードには影響無し #2単語以上は_で区切る数式
X = X + 10 X += 10 #同意味if文 真偽値
score=94 if score >= 80 puts "頑張ったね" elsif 条件2 処理2 else 処理3 end puts score > 80 #真偽 true #結果所感
Rubyに初めて触れましたが、コードがシンプルで分かりやすい印象を受けました。
まだ単純なコードですが、コードのルールが他の言語より覚えやすいですね。ここからどのような使い方をするか言語の役割を意識しつつ、
勉強していこうと思います。
- 投稿日:2020-03-18T22:54:40+09:00
ローカルで行った変更点が本番環境に反映されない時の対処法
せっかくローカルで変更して上手くいっても、本番環境で変化がなければなんの意味もありません。
今回、ローカルホストではしっかり変わっているにも関わらず、本番環境(capistranoで自動デプロイ時)に反映されない時の対処法を書いていきます。
結論「unicornをkill」しましょう。
unicornをkillする手順
1.ターミナル
[ec2-user@本番環境 <リポジトリ名>]$ ps aux | grep unicornこちらをしていただくと
ec2-user 17877 0.4 18.1 588472 182840 ? Sl 01:55 0:02 unicorn_rails master -c config/unicorn.rb -E production -D ec2-user 17881 0.0 17.3 589088 175164 ? Sl 01:55 0:00 unicorn_rails worker[0] -c config/unicorn.rb -E production -D ec2-user 17911 0.0 0.2 110532 2180 pts/0 S+ 02:05 0:00 grep --color=auto unicornこのように表記されると思います。
一番上の行の5桁の数字(PID)をkillします。
kill -9 上記で確認したPIDあとはもう一度デプロイ するだけ
でも、毎回デプロイ のたびにこれをするのは手間ですよね。
なので、デプロイ 時に自動でunicornをkillしてstartしてくれる記述を書きましょう。
config/deploy.rb after 'deploy:publishing', 'deploy:restart' namespace :deploy do task :restart do invoke 'unicorn:stop' invoke 'unicorn:start' end desc 'upload master.key' task :upload do on roles(:app) do |host| if test "[ ! -d #{shared_path}/config ]" execute "mkdir -p #{shared_path}/config" end upload!('config/master.key', "#{shared_path}/config/master.key") end end before :starting, 'deploy:upload' after :finishing, 'deploy:cleanup' endこちらの
namespace :deploy do task :restart do invoke 'unicorn:stop' invoke 'unicorn:start' endこのように記述することで、デプロイ 時に自動でunicornを再起動してくれます。
私のような誰かの助けになれば幸いです!!!
それではまたどこかで^^
- 投稿日:2020-03-18T21:22:30+09:00
Mysql2::Error
MySQLが起動しない。
エラー内容
Mysql2::Error::ConnectionError (Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)):前日まで問題なくRailsの勉強をしていました。作成したアプリケーションを確認するために
rails sするとエラーがでました。
仮説
MySQLへアクセスするためのsockファイルを見つけれずアクセスできない。
トラブル解決手順
1.ターミナルに下記のコードを入力しデータベースの中身を見る。
$ ls -la /usr/local/var/mysql/すると
total 380944 drwxr-xr-x 66 _mysql _mysql 2112 3 17 23:50 . drwxrwxr-x 4 user admin 128 12 12 00:27 .. drwx------ 11 _mysql _mysql 352 1 26 17:54 DataBaseDesignSample_development drwx------ 3 _mysql _mysql 93 1 26 17:15 DataBaseDesignSample_test drwx------ 9 _mysql _mysql 283 2 11 19:28 ajax_development drwx------ 3 _mysql _mysql 36 2 11 19:27 ajax_test -rw-rw---- 1 _mysql _mysql 56 12 12 00:30 auto.cnf -rw-r----- 1 _mysql _mysql 0 2 15 15:53 binlog.index上記のような感じで表示される。
2.次に下記のコードを入力
$ ls -la /usr/local/var/実行すると下記のような表示が出る。問題なさそう.....
drwxrwxr-x 4 user admin 128 12 12 00:27 . drwxr-xr-x 13 root wheel 430 1 31 21:15 .. drwxrwxr-x 4 user admin 128 12 12 00:03 homebrew drwxr-xr-x 36 _mysql _mysql 3112 3 17 23:50 mysql3.このコードを入力するとエラーが解決!
$ sudo mysql.server start Starting MySQL ... SUCCESS!ちなみに下記のコードではエラーの解決にはいたりませんでした。
$ mysql.server restart最後に
同じ初学者の方は似たようなエラーで悩まされてると思います。
restartではなくstartと入力すること、初めにsudoと入力することでもっと強力な指令となるみたいです。
同じエラーで困る人のお役に立てればと思い投稿しました。
初学者の皆さん一緒に頑張りましょう!
- 投稿日:2020-03-18T19:47:45+09:00
Kinx プレビュー版リリース
Kinx プレビュー版のリリース
はじめに
「見た目は JavaScript、頭脳(中身)は Ruby、(安定感は AC/DC)」でお送りするスクリプト言語 Kinx。まだまだ途中だがリリースするのも意味があるだろうとの想定から、実行可能な形でパッケージングし、まずはプレビュー・リリースすることにしました。Windows 版の実行ファイルはアイコンもつけていい感じ。Linux は /usr/bin にインストールしてしまうので、一応気にしておいてください。
本題
↓ここです。
もちろん、git clone して make もできます。
本題、おしまい。
振り返り
元々はこの記事での「プログラマに馴染むシンタックスってのは C 系だよね、でも何で Ruby も Python も全然違うのでしょう」というところから始まった今回のプロジェクト。プロジェクト自体は去年末くらいから実質スタートしてたので、約 5 ヶ月くらいか。
元々からしてほぼ JavaScript な文法なので、作りながらではあるものの、既にすっかり私の手には馴染んでます。
まだ初版にはできませんが(おっとさっき気づいたのだが標準入力がない...)、結構色々試せるとは思います。
ほんのちょっと興味があれば
何か試してみてフィードバック貰えると非常に嬉しい。まぁ、既存の何かを置き換えるようなたいそうなモノではないので、ちょっとした提案とかこんなんあるといいんじゃない、とか、そういうライトな感じのご意見ください。
すみません、見返りはあまり無いと思います…。そういうの楽しめる方か、面白そうだと思ってくださる方向け。
おわりに
最後はいつもの以下の定型フォーマットです。
- 最初の動機は スクリプト言語 KINX(ご紹介) を参照してください(もし宜しければ「
いいねLGTM」ボタンをポチっと)。- リポジトリは ここ(https://github.com/Kray-G/kinx) です。こちらももし宜しければ★をポチっと。
- 投稿日:2020-03-18T18:49:33+09:00
【rails db:createエラー】dependent dylib '/usr/local/opt/mysql/lib/libssl.1.1.dylib' not found for '/Library/Ruby/Gems/2.6.0/gems/mysql2-0.5.3/lib/mysql2/mysql2.bundle'
エラーをいろいろ試して解決しました。(めちゃくちゃな解決法ですが初心者なのでご容赦ください)
エラー内容
$ rails db:createしたところ
LoadError: dlopen(/Library/Ruby/Gems/2.6.0/gems/mysql2-0.5.3/lib/mysql2/mysql2.bundle, 0x0009): dependent dylib '/usr/local/opt/mysql/lib/libssl.1.1.dylib' not found for '/Library/Ruby/Gems/2.6.0/gems/mysql2-0.5.3/lib/mysql2/mysql2.bundle' - /Library/Ruby/Gems/2.6.0/gems/mysql2-0.5.3/lib/mysql2/mysql2.bundleのエラーが発生。
'/usr/local/opt/mysql/lib/libssl.1.1.dylib'のファイルが無い?と書いてありました。解決方法
他の方の参考にはあまりならないかもしれません。。。
homebrewでmysqlをインストールすれば、/usr/local/opt/mysql/lib/libssl.1.1.dylibファイルができると思い、
https://qiita.com/narikei/items/cd029911597cdc71c516
を参考に$ brew install mysql $ mysql.server start $ bundle init $ bundle install --path=vendor/bundleを実施しました。
その後、アプリ内で改めて
$ rails db:createしたら、
Could not find mysql2-0.5.3 in any of the sources Run `bundle install` to install missing gems.というエラーが出たので、
$ bundle installしたら、
An error occurred while installing mysql2 (0.5.3), and Bundler cannot continue. Make sure that `gem install mysql2 -v '0.5.3' --source 'https://rubygems.org/'` succeeds before bundling.のエラーが出ました。
https://qiita.com/fukuda_fu/items/463a39406ce713396403
を参考に$ bundle config --local build.mysql2 "--with-cppflags=-I/usr/local/opt/openssl@1.1/include" $ bundle config --local build.mysql2 "--with-ldflags=-L/usr/local/opt/openssl@1.1/lib" $ bundle installしたところ、成功しました。改めて、
$ rails db:createしたところ、
Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)のエラーが出たので、
https://qiita.com/carotene4035/items/e00076fe3990b9178cc0
を参考に$ touch /tmp/mysql.sock $ mysql.server restartをした後
$ rails db:createで無事にデータベースが作成できました。
- 投稿日:2020-03-18T14:41:48+09:00
Psych::SyntaxErrorの対処法
エラーの内容
s3に画像をアップさせる関係で、secrets.ymlを書き換えたら、rails sで以下のエラーが出た。
`parse': (<unknown>): did not find expected key while parsing a block mapping at line 13 column 1 (Psych::SyntaxError)解決した方法
上記のエラーについて調べたところ、検索で上位表示される記事のほとんどで、ymlファイルのインデントがずれていることによるエラーが出ると書いてあった。
そこで、筆者はVScodeを利用していることから、(command)+Pを用いて、.ymlのつくファイルを検索しインデントのずれを探した。
まあ、.ymlファイルをいじったことは記憶に新しかった(s3関連でいじってる)ので、secrets.ymlをまず確認したところ、development、test、productionが全てずれていた。
これを戻し、rails sをし直すと、、、
できた!!!!!
- 投稿日:2020-03-18T13:07:33+09:00
【Rails】URLテキストにaタグを自動でつける
はじめに
ユーザーがフォームに投稿したURLテキストに自動でaタグをつけて表示できたらなーーと調べていたら、uriライブラリーのおかげでとても簡単にできたので、備忘録としてまとめます。
uriライブラリーを読み込む
Rubyの標準ライブラリーとして'uri'というURIを扱う標準ライブラリ-があるので、読み込みます。
https://docs.ruby-lang.org/ja/latest/class/URI.htmlapp/helpers/application_helper.rbrequire "uri"ヘルパーメソッドを作成
uriライブラリーを読み込んだapplication_helper.rbでメソッドを作成します。
app/helpers/application_helper.rbrequire "uri" #追加 def text_url_to_link(text) URI.extract(text, ['http', 'https']).uniq.each do |url| sub_text = "" sub_text << "<a href=" << url << " target=\"_blank\">" << url << "</a>" text.gsub!(url, sub_text) end return text end
URI.extract
で、http
もしくはhttps
で始まるtextをurl
として取り出し、sub_text
という変数に代入2.
gsub!
メソッドで textをsub_textに変換3.
変換したtextを返す該当のviewに表示させる
URLテキストにaタグをつけて表示させたい部分に、以下のように先ほど作成したメソッドを使用して、表示させます。
app/views/sample.html.erb<%= text_url_to_link(h(該当する変数)).html_safe %>これで、無事にURLテキストに自動でaタグをつけて表示してくれるようになります。
- 投稿日:2020-03-18T12:08:04+09:00
railsで学ぶテスト処理(rails チュートリアルで学んだことをまとめてみました)
この記事の説明について
この記事ではrails チュートリアルで学んだことを私なりにまとめてみました。
理解の浅い部分がありますので、間違いがある場合はどうぞご教授ください。テストとは
開発をしながら、動作するかテストすること
テストの種類
・モデルテスト→モデルが機能している
・機能テスト→コントローラーとビューの連携
・統合テスト→ユーザー目線でうまく動作するか、全体的にテストって感じ?それぞれ別のテストファイルにテストを書く
assert 内容 →内容通りならば成功、でなければ失敗 assert not 内容 →内容通りでなければ成功、内容通りならば失敗assertに関してはこちらのサイトがわかりやすかったです。
Rails チュートリアル 【初心者向け】 テストを10分でおさらいしよう!主な流れ
まず開発する前にテストの内容をtestfileに記述する
(ここで書くテスト内容はまだやっていない開発内容に関する事→開発しないとテストは成功しない)
↓
開発をする(テストが成功する予定)
↓
自動でテストor手動でコンソール内でrails test補足
全てのtestはtest_helperを導入している
test_helperはtestディレクトリーの中にある。
test_helperの中にはtestで使う関数を書いている。
またapplication_helperをtest _helperの中に導入することで、実際の開発環境で使っている関数(例 login関数)をtestで使用できるようになる。自動テスト
その中でも開発と同時並行で自動でテストする方法がある。開発で変更を加えるたびに自動でテストを子なってくれる。
自動テストを導入するためには
テストを自動でやってくれるGuardを取り入れる
↓
Guard fileに自動テストするように指示を書く
詳しくはRuby on Rails チュートリアル注意
Guardを使うときにspringという機能を使う
しかしspringがgitとの競合をしないように、.git ignoreファイルに、springを書きgitリポジトリに保存されないようにするモデルテスト
モデル名test.rbに記述するテスト。(例 test/models/usertest.rb)
rails g model ~でモデルが作られると
testディレクトリにそのモデルのためのテストができる書き方
まずモデルのインスタンスを作成する(主にseup関数で行う)
↓
そのインスタンスが機能しているかや、複数のインスタンスの関係性が機能しているかなど確認する。test/models/user_test.rbrequire 'test_helper' class UserTest < ActiveSupport::TestCase def setup #インスタンス作成 @user = User.new(name: "Example User", email: "user@example.com") end test "name should be present" do @user.name = " " assert_not @user.valid? #このテストの場合Userファイルで書いたvalidateが発動しているかテストしている end end機能テスト
controller_test.rbに記述するテスト。
rails g controller ~でコントローラーが作られると
testディレクトリにそのコントローラーのためのテストができる書き方
まず必要な処理をsetupで書く
↓
どのアクションを発動させるためにどのURLを発信するかを書き、assert関数でテスト内容を書くtest/controllers/users_controller_test.rbrequire 'test_helper' class UsersControllerTest < ActionDispatch::IntegrationTest def setup ・ ・ end test "should get new" do get users_new_url assert_response :success end end統合テスト
test/integration/統合テスト名_test.rbに記述するテスト。
rails g integration_test 〜でtestディレクトリに作られる。
書き方
まず必要な処理をsetupで書く
↓
どのアクションを発動させるためにどのURLへ発信するかを書き、assert関数でテスト内容を書く
様々なURLへ発信して、如何にも実際に手で動かしているテストのように行う。test/integration/microposts_interface_test.rbrequire 'test_helper' class MicropostsInterfaceTest < ActionDispatch::IntegrationTest def setup ・ ・ end test "micropost interface" do get root_path assert ... ・ ・ post microposts_path ... assert ... ・ ・ end機能テストとの違いは一つのコントローラー内でのテストではなく、いろんなコントローラーに繋いでどうなるかなどをテストできる?
以下のサイトでいう結合テスト(内部)が機能テストで結合テスト(外部が)統合テスト?
単体テスト・結合テスト・総合テストの違い、観点や注意点を簡単に説明するデバッグとは
デバッグとはバグをとる事
どんなバグが起きているか実行結果から知りたい場合
↓
開発環境のみで、全てのレイアウトでparamsの中身が見れるようにする。
debug(params)とする→これでparamsの中身を見るという指示になる
applicationHTMLで共通レイアウトを作るときに、if文で開発環境にのみバクの内容が見れるようにする
詳しくはRuby on Rails チュートリアル補足
fixturesとは
テストで使うためのデータベースにあるデータとして記述される。
ログインを実践する統合テストをしたい時
test.fixturesファイルに、ログインユーザーの情報を置く。ここにはテストで使用するユーザーの情報を置く
↓
統合テスト
詳しくはRuby on Rails チュートリアルでfixtureで検索テストで作ったインスタンスの値を知りたい時
テスト内で
assigns(インスタンス変数).データカラムとするとアクセスできる。
詳しくはRuby on Rails チュートリアルでassignsで検索参考文献
参考文献:
Rails チュートリアル
Railsガイド
Ruby on Rails5 アプリケーションプログラミング
単体テスト・結合テスト・総合テストの違い、観点や注意点を簡単に説明する
Rails チュートリアル 【初心者向け】 テストを10分でおさらいしよう!
- 投稿日:2020-03-18T12:08:04+09:00
railsで学ぶテスト処理(rails チュートリアル)
この記事の説明について
この記事ではrails チュートリアルで学んだことを私なりにまとめてみました。
理解の浅い部分がありますので、間違いがある場合はどうぞご教授ください。テストとは
開発をしながら、動作するかテストすること
テストの種類
・モデルテスト→モデルが機能している
・機能テスト→コントローラーとビューの連携
・統合テスト→ユーザー目線でうまく動作するか、全体的にテストって感じ?それぞれ別のテストファイルにテストを書く
assert 内容 →内容通りならば成功、でなければ失敗 assert not 内容 →内容通りでなければ成功、内容通りならば失敗assertに関してはこちらのサイトがわかりやすかったです。
Rails チュートリアル 【初心者向け】 テストを10分でおさらいしよう!主な流れ
まず開発する前にテストの内容をtestfileに記述する
(ここで書くテスト内容はまだやっていない開発内容に関する事→開発しないとテストは成功しない)
↓
開発をする(テストが成功する予定)
↓
自動でテストor手動でコンソール内でrails test
で成功する
↓
必要ならばリファクタリング
↓
リファクタリングしてもエラー出ないかテスト補足
全てのtestはtest_helperを導入している
test_helperはtestディレクトリーの中にある。
test_helperの中にはtestで使う関数を書いている。
またapplication_helperをtest _helperの中に導入することで、実際の開発環境で使っている関数(例 login関数)をtestで使用できるようになる。
詳しくはRuby on Rails チュートリアル自動テスト
その中でも開発と同時並行で自動でテストする方法がある。開発で変更を加えるたびに自動でテストを行ってくれる。
自動テストを導入するためには
テストを自動でやってくれるGuardを取り入れる
↓
Guard fileに自動テストするように指示を書く
詳しくはRuby on Rails チュートリアル注意
Guardを使うときにspringという機能を使う
しかしspringがgitとの競合をしないように、.git ignoreファイルに、springを書きgitリポジトリに保存されないようにするモデルテスト
モデル名test.rbに記述するテスト。(例 test/models/usertest.rb)
rails g model ~でモデルが作られると
testディレクトリにそのモデルのためのテストができる書き方
まずモデルのインスタンスを作成する(主にseup関数で行う)
↓
そのインスタンスが機能しているかや、複数のインスタンスの関係性が機能しているかなど確認する。test/models/user_test.rbrequire 'test_helper' class UserTest < ActiveSupport::TestCase def setup #インスタンス作成 @user = User.new(name: "Example User", email: "user@example.com") end test "name should be present" do @user.name = " " assert_not @user.valid? #このテストの場合Userファイルで書いたvalidateが発動しているかテストしている end end機能テスト
controller_test.rbに記述するテスト。
rails g controller ~でコントローラーが作られると
testディレクトリにそのコントローラーのためのテストができる書き方
まず必要な処理をsetupで書く
↓
どのアクションを発動させるためにどのURLを発信するかを書き、assert関数でテスト内容を書くtest/controllers/users_controller_test.rbrequire 'test_helper' class UsersControllerTest < ActionDispatch::IntegrationTest def setup ・ ・ end test "should get new" do get users_new_url assert_response :success end end統合テスト
test/integration/統合テスト名_test.rbに記述するテスト。
rails g integration_test 〜でtestディレクトリに作られる。
書き方
まず必要な処理をsetupで書く
↓
どのアクションを発動させるためにどのURLへ発信するかを書き、assert関数でテスト内容を書く
様々なURLへ発信して、如何にも実際に手で動かしているテストのように行う。test/integration/microposts_interface_test.rbrequire 'test_helper' class MicropostsInterfaceTest < ActionDispatch::IntegrationTest def setup ・ ・ end test "micropost interface" do get root_path assert ... ・ ・ post microposts_path ... assert ... ・ ・ end機能テストとの違い
違いは一つのコントローラーのアクション内でのテストではなく、rootingを通して様々なコントローラーに繋いでどうなるかなどをテストできる?
以下のサイトでいう結合テスト(内部)が機能テストで結合テスト(外部が)統合テスト?
単体テスト・結合テスト・総合テストの違い、観点や注意点を簡単に説明する単体テスト
上記のテストでは実施しにくいテスト
helpersの中で書くことが多い?
例: 関数で読み出された文字列に誤字がないかとかデバッグとは
デバッグとはバグをとる事
どんなバグが起きているか実行結果から知りたい場合
↓
開発環境のみで、全てのレイアウトでparamsの中身が見れるようにする。
debug(params)とする→これでparamsの中身を見るという指示になる
applicationHTMLで共通レイアウトを作るときに、if文で開発環境にのみバクの内容が見れるようにする
詳しくはRuby on Rails チュートリアル補足
fixturesとは
テストで使うためのデータベースにあるデータとして記述される。
ログインを実践する統合テストをしたい時
test.fixturesファイルに、ログインユーザーの情報を置く。ここにはテストで使用するユーザーの情報を置く
↓
統合テスト
詳しくはRuby on Rails チュートリアルでfixtureで検索テストで作ったインスタンスの値を知りたい時
テスト内で
assigns(インスタンス変数).データカラムとするとアクセスできる。
詳しくはRuby on Rails チュートリアルでassignsで検索テストファイルのsetup関数で変数を作り、テストに採用したいときには変数は@が頭についておかないといけない。
test/controllers/static_pages_controller_test.rbrequire 'test_helper' class StaticPagesControllerTest < ActionDispatch::IntegrationTest def setup @base_title = "Ruby on Rails Tutorial Sample App" end test "should get home" do get static_pages_home_url assert_response :success assert_select "title", "Home | #{@base_title}" end参考文献
参考文献:
Rails チュートリアル
Railsガイド
Ruby on Rails5 アプリケーションプログラミング
単体テスト・結合テスト・総合テストの違い、観点や注意点を簡単に説明する
Rails チュートリアル 【初心者向け】 テストを10分でおさらいしよう!
- 投稿日:2020-03-18T11:57:13+09:00
Docker環境にSystem Specを導入する
はじめに
Docer環境でRSpecのSystem Specを導入しようとしたところ、結構ハマったので、備忘録としてまとめます。
まず、Docer環境にSystem Specを実行するためには、いくつか方法があるらしい。
調査をしていると、メジャーな方法は以下の二つ(もっとあるかもしれませんが、、、)1. Railsが動いているimageにchromeをインストールする方法
2. chrome用コンテナを立ち上げる方法今回は2の方法でやってみました。
前提
Quickstart: Compose and Railsの通りに、Rails on Dockerの環境構築が済んでいる状態とします。
筆者の環境は
- Ruby 2.5.7
- Rails 5.2.4
です。docker-compose.ymlを編集する
selenium_chromeのコンテナが立ち上がるようdocker-compose.ymlに追加していきます。
Dockerイメージにはselenium/standalone-chromeを使用します。docker-compose.ymlversion: '3' services: db: image: postgres volumes: - ./tmp/db:/var/lib/postgresql/data web: build: . command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'" volumes: - .:/myapp ports: - "3000:3000" depends_on: - db #追加 - chrome #追加 chrome: image: selenium/standalone-chrome:3.141.59-dubnium ports: - 4444:4444gemを追加する
Gemfilegroup :development, :test do gem 'rspec-rails' end group :test do gem 'capybara', '>= 2.15' gem 'selenium-webdriver' enddockerをbuildして、bundle installします。
$ docker-compose build $ docker-compose up -drspecの設定
rspecをインストールします。
$ docker-compose run web rails g rspec:installheadless chromeの設定
spec/rails_helper.rbにheadless chromeの設定を追加していきます。
/spec/rails_helper.rbrequire 'capybara/rspec' # headless chrome 設定① Capybara.server_host = Socket.ip_address_list.detect { |addr| addr.ipv4_private? }.ip_address Capybara.server_port = 3001 ※ Capybara.register_driver :selenium_remote do |app| url = "http://chrome:4444/wd/hub" opts = { desired_capabilities: :chrome, browser: :remote, url: url } Capybara::Selenium::Driver.new(app, opts) end # headless chrome 設定② RSpec.configure do |config| config.before(:each, type: :system) do driven_by :rack_test end config.before(:each, type: :system, js: true) do driven_by :selenium_remote host! "http://#{Capybara.server_host}:#{Capybara.server_port}" end endポイント:
後半部分(# headless chrome 設定②)で、
js: true
を記述した場合のみ、seleniumドライバーが立ち上がるように設定しています。ハマったポイント:
js: true
のテストを走らせたとき、Capybaraがseleniumサーバーを立ち上げて、先ほど設定したchromeコンテナで起動しているchromeを操作します。
しかし、Capybara.server_portを指定する部分(*)で、webコンテナで指定したポートと同じ3000を指定してしまうと、js: true
のテストを走らせたときに、webコンテナで指定したポートと競合してseleniumサーバーが立ち上がらずエラーとなってしまいます。
そこで、Capybara.server_port =30003001
とすることで、競合することなく、無事サーバーが立ち上がり、テストが通るようになりました。これで準備は整いました。
あとは、テストを実際に走らせるだけです。実際にテストを走らせてみる
spec/system/test_spec.rbrequire "rails_helper" RSpec.describe 'Test', type: :system, js: true do example 'サンプルテスト' do #ここにテスト内容を記述 end end$ docker-compose exec web bundle exec rpsecこれで、テストが通るはずです。
参考記事
下記の記事を参考にさせていただきました。
ありがとうございます。
- Docker で RSpec の System Spec を実行するための設定メモ
- Rails + Selenium + DockerでSystemSpecの環境構築
- Rails on Dockerにて、Headless ChromeでSystem Testをやってみた。
- 投稿日:2020-03-18T11:43:44+09:00
休日ならtrue、平日ならfalseを返すrubyメソッド
今日は、平日ならfalse、休日ならtrue値をとして返すメソッドを書いていきたいと思います。
呼び出し方:
sleep_in(weekday, vacation)出力例:
sleep_in(false, false) → True
sleep_in(true, false) → False
sleep_in(false, true) → Trueこちらを作っていきます。
まずはコードから
def sleep_in(is_weekday, is_vacation) if (is_weekday != true) || (is_vacation == false) puts "True" else puts "False" end end is_weekday = true is_vacation = false sleep_in(is_weekday,is_vacation)細かくみていきます。
def sleep_in(is_weekday, is_vacation) if (is_weekday != true) || (is_vacation == false) puts "True" else puts "False" end endこちらで、メソッドsleep_inを定義しています。
引数にis_weekdayと、is_vacationをとっています。メソッド内では、if文により条件分岐をしており、is_weekdayがtrueではないまたはis_vacationがfalseの時となっています。
つまり
is_weekdayがtrueの時もしくは
is_vacationがfalseの時にこのif文はtrueを返すようになっています。is_weekday = true is_vacation = falseこちらでは引数にtureとfalseを代入しています。
sleep_in(is_weekday,is_vacation)ここでメソッドを呼び出しています。
以上で、weekdayつまり平日(ここではtrueを代入)がtrueでない時、vacationつまり休日(ここではfalseを代入)がfalseの時にTrueを返すメソッドが完成します。
今日はここまでで、失礼します^^
- 投稿日:2020-03-18T11:14:39+09:00
Gemfileにおける「>= 」と「~>」の違い
背景
Rails初心者の備忘録のため
基礎情報
gem 'sqlite3'gemコマンドで特定のバージョン番号を指定しない限り、Bundlerは自動的に最新バージョンのgemを取得してインストールする
「>=」について
gem 'uglifier', '>= 1.3.0'uglifierのバージョンが1.3.0以上であれば最新バージョンのgemがインストールされる。(uglifierはAsset Pipelineでファイル圧縮を行うgem)
「~>」について
gem 'coffee-rails', '~> 4.0.0'coffee-railsのバージョンが4.0.0より大きく、4.1より小さい場合にインストールされる。 (これもAsset Pipelineで使うgem)
使い分けの理由
マイナーアップグレードですら問題を引き起こすことがあるから。
すべてRailsチュートリアルからの抜粋。完全に備忘録です
参照
https://railstutorial.jp/chapters/beginning?version=5.1#cha-beginning
- 投稿日:2020-03-18T09:26:19+09:00
rails検索機能追加
はじめに
今回は投稿されたマイクロポストを入力された文字からあいまい検索する機能を追加します。
作るもの
railsのform_withヘルパーを利用した投稿の検索機能。(題材は自分のポートフォリオ)
対象読者
railsチュートリアル終了後等に何か機能を追加したい人等。
作成の流れ
1.対応するビューの作成
2.コントローラーの編集1.対応するビューの作成
今回は検索フォームをroot_path上に設けます。(自分のポートフォリオがマイクロポストの一覧をroot_path(static_pages/home)に設けているため)
app/views/static_pages/home.html.erb<%= form_with( url: root_path, class: 'search_form', method: :get, local:true) do |f| %> <%= f.text_field :search,class: 'field',value: params[:search]\ placeholder: "スレ・コメント検索"%> <%= f.submit '検索', class: "btn" %>form_withを利用して検索フォームを作ります。各値は
url:root_path検索後に表示するページ
method:get(httpメゾット。今回はページの取得なのでget)
local:true(ajax処理(非同期通信)を無効にする。デフォルトではajaxで処理する。)
text_field: search 入力フォームになります。
value: params[:search]と値を設定しておくことで検索後も値を保持します。(URLのクエリから取得。)
あとはget動作を開始させるsubmitを配置します。検索ボタンを押せばurlのページを表示しようとするので検索の処理は対応するコントローラーのアクション内に書きます。
2.コントローラーの編集
コントローラーで送られた値を処理しますが、コントローラー内に処理を全て書くとごちゃごちゃしてしまいますのでDBとやりとりをする箇所はmodel側で記述します。
app/controller.rb@microposts = params[:search].present? ? Micropost.micropost_serach(params[:search]) : Micropost.all@microposts = params[:search].present?で値がsearchに値が入っているか(検索ボタンが押されているか)
値が入っていればmicropost_serachを動作させます。(中身は後ほどmodelに記載)値が入ってなければ、Micropost.allで全てのマイクロポストを表示させます。(そのあとは適宜ページネーション等に渡してください。)
ではmicropost_serachの中身です。app/model/micropost.rbdef self.micropost_serach(search) Micropost.where(['title LIKE ?', "%#{search}%"]) endwhereメゾットとLIKE旬でマイクロポストの中からあいまい検索をします。
モデル名.where([カラム名前 LIKE ?, "検索したい文字列"])検索したい文字列の両サイドにある「%」は任意の複数の文字列を表しています。
上記のは一つしかカラムを指定していませんが複数指定することもできます。app/model/micropost.rbdef self.micropost_serach(search) Micropost.where(['title LIKE ? OR content LIKE ?', "%#{search}%", "%#{search}%"]) end複数のカラムを指定する場合はカラム数に応じてORやANDで繋ぎ、検索したい文字列を増やしてあげると検索できます。
今回はさらに、マイクロポストにコメントされた文章も含めて検索してみます。
コメント機能についてこちら
https://qiita.com/E6YOteYPzmFGfOD/items/ef776d34908872ea19f7app/model/micropost.rbdef self.micropost_serach(search) Micropost.includes(:comments).where(['microposts.title LIKE ? OR microposts.content LIKE ? OR comments.content LIKE ?', "%#{search}%", "%#{search}%", "%#{search}%"]).references(:comments) endこれでコメント内も合わせて検索できるようになりました
#終わりに
最後までお読みいただきありがとうございました。検索文はいろいろパターンがあるので今後も新しい物を書いたときには記事にしてみようと思います。
ありがとうございました。
- 投稿日:2020-03-18T07:07:41+09:00
ツイッター風Railsアプリ最短復習(忙しい人の流し読みで開発シリーズ)
はじめに
こんにch… え?忙しい?? んじゃぁスタート!!!
具体的な手順
①アプリ立ち上げ
Terminal$ cd Desktop $ rails _5.2.4.1_ new cheaptweet -d mysql $ cd cheaptweet $ rails db:create $ rails swebBrowserlocalhost:3000②テーブル作成
Gemfile# 省略 gem 'devise'Terminal$ bundle install $ rails g devise:install control + c $ rails s $ rails g devise userdb/migrate/2020xxxxxxxxx_devise_create_users.rb# 省略 t.string :nickname, null: false # 省略Terminal$ rails db:migrateTerminal$ rails g model tweet
db/migrate/2020xxxxxxxxxxxx_create_tweets.rb# 省略 t.string :text, null: false t.references :user, foreign_key: true, null: false # 省略Terminal$ rails db:migrate
app/models/user.rb#省略 validates :nickname ,presence: true has_many :tweets #省略app/models/tweet.rb#省略 validates :text ,presence: true belongs_to :user #省略③会員登録・ログイン・ログアウトのみの基本循環構築
app/controllers/application_controller.rbclass ApplicationController < ActionController::Base before_action :configure_permitted_parameters, if: :devise_controller? protected def configure_permitted_parameters devise_parameter_sanitizer.permit(:sign_up, keys: [:nickname]) end endTerminal$ rails g devise:views
app/views/devise/registrations/new.html.erb<!--省略--> <div class="field"> <%= f.label :nickname %><br /> <%= f.text_field :nickname, autofocus: true %> </div> <!--省略--> <!-- 他の autofocus: true を削除 -->Terminal$ rails g controller tweets index
config/routes.rb# get 'tweets/index' # | # v resources :tweets, only: [:index] root 'tweets#index' #省略app/views/layouts/application.html.erb<!--省略--> <body> <!--↓追記↓-----------------------------------------------> <header style="height: 50px; background-color: grey;"> <% if user_signed_in? %> <%= current_user.nickname %> <%= link_to "ログアウト", destroy_user_session_path, method: :delete %> <% else %> <%= link_to "ログイン", new_user_session_path %> <%= link_to "会員登録", new_user_registration_path %> <% end %> <%= link_to "トップへ", root_path, style:"float: right;" %> </header> <!--↑追記↑----------------------------------------------> <%= yield %> </body> <!--省略-->app/views/tweets/index.html.erb<div>※確認用</div>④投稿(new→create)
config/routes.rb# resources :tweets, only: [:index] # | # V resources :tweets, only: [:index, :new, :create] #省略app/controllers/tweets_controller.rbclass TweetsController < ApplicationController def index end ####↓追記↓################################################ def new @tweet = Tweet.new end def create @tweet = Tweet.new(tweet_params) if @tweet.save redirect_to root_path else render action: :new end end private def tweet_params params.require(:tweet).permit(:text).merge(user_id: current_user.id) end ####↑追記↑################################################# endnew.html.erb<%= form_with(model: @tweet, local:true) do |f| %> <%= f.text_area :text %> <%= f.submit '投稿' %> <% end %>app/views/layouts/application.html.erb<!--省略--> <body> <header style="height: 50px; background-color: grey;"> <% if user_signed_in? %> <%= current_user.nickname %> <!--↓追記↓-----------------------------------> <%= link_to "投稿", new_tweet_path %> <!--↑追記↑-----------------------------------> <%= link_to "ログアウト", destroy_user_session_path, method: :delete %> <% else %> <%= link_to "ログイン", new_user_session_path %> <%= link_to "会員登録", new_user_registration_path %> <% end %> </header> <%= yield %> </body> <!--省略-->⑤一覧(index)
app/controllers/tweets_controller.rb#省略 def index ####↓追記↓##################################################### @tweets = Tweet.all.includes(:user).order("created_at DESC") ####↑追記↑##################################################### end #省略app/views/tweets/index.html.erb× <div>※確認用</div> <!-- | --> <!-- V --> <% @tweets.each do |t| %> <div><span style="color: red;"><%= t.user.nickname %></span><%= t.text %></div> <% end %>⑥詳細(show)・編集(edit→update)・削除(destroy)
config/routes.rb# resources :tweets, only: [:index, :new, :create] # | # V resources :tweets #省略app/controllers/tweets_controller.rb#省略 def show @tweet = Tweet.find(params[:id]) end #省略app/views/tweets/index.html.erb× <div><span style="color: red;"><%= t.user.nickname %></span><%= t.text %></div> <!-- | --> <!-- V --> <div><%= link_to tweet_path(t.id) do %><span style="color: red;"><%= t.user.nickname %></span><%= t.text %><% end %></div>app/views/tweets/show.html.erb<div><span style="color: red;"><%= @tweet.user.nickname %></span><%= @tweet.text %></div> <%= link_to "編集", edit_tweet_path(@tweet.id) %><%= link_to "削除", tweet_path(@tweet.id),method: :delete %>app/controllers/tweets_controller.rb#省略 def edit @tweet = Tweet.find(params[:id]) end def update @tweet = Tweet.find(params[:id]) if @tweet.update(tweet_params) redirect_to tweet_path(params[:id]) else render action: :edit end end def destroy @tweet = Tweet.find(params[:id]) @tweet.delete redirect_to root_path end #省略app/views/tweets/edit.html.erb<%= form_with(model: @tweet, local:true) do |f| %> <%= f.text_area :text %> <%= f.submit '投稿' %> <% end %>削除後確認画面が欲しければ、
app/controllers/tweets_controller.rb#省略 def destroy @tweet = Tweet.find(params[:id]) @tweet.delete # redirect_to root_path end #省略app/views/tweets/destroy.html.erb<div>削除しました</div> <%= link_to "トップに戻る", root_path %>⑦編集・削除の権限設定
app/views/tweets/show.html.erb× <%= link_to "編集", edit_tweet_path(@tweet.id) %><%= link_to "削除", tweet_path(@tweet.id),method: :delete %> <!-- | --> <!-- V --> <% if user_signed_in? && current_user.id == @tweet.user_id %> <%= link_to "編集", edit_tweet_path(@tweet.id) %><%= link_to "削除", tweet_path(@tweet.id),method: :delete %> <% end %>app/controllers/tweets_controller.rbclass TweetsController < ApplicationController ####↓追記↓############################################### before_action :unless_signin, only: [:new, :create,] before_action :unless_mytweet, only: [:edit, :update, :destroy] ####↑追記↑############################################### #省略 private #省略 ####↓追記↓############################################### def unless_signin redirect_to tweets_path unless user_signed_in? end def unless_mytweet redirect_to tweets_path unless user_signed_in? && current_user.id == Tweet.find(params[:id]).user.id end ####↑追記↑############################################### end⑧一覧ページネーション
Gemfile#省略 gem 'kaminari'Terminal$ bundle installTerminalcontrol + c $ rails s
# @tweets = Tweet.all.includes(:user).order("created_at DESC") # | # V @tweets = Tweet.includes(:user).order("created_at DESC").page(params[:page]).per(5)app/views/tweets/index.html.erb<!--省略--> <%= paginate(@tweets) %>⑨コメント機能
Terminal$ rails g model comment
db/migrate/2020xxxxxxxx_create_comments.rb#省略 t.string :text, null: false t.references :user, foreign_key: true, null: false t.references :tweet, foreign_key: true, null: false #省略Terminal$ rails db:migrate
app/models/user.rb#省略 has_many :comments #省略app/models/tweet.rb#省略 has_many :comments #省略app/models/comment.rb#省略 validates :text, presence: true belongs_to :user belongs_to :tweet #省略config/routes.rb# resources :tweets # | # V resources :tweets do resources :comments, only: :create endapp/controllers/tweets_controller.rb#省略 def show @tweet = Tweet.find(params[:id]) ####↓追記↓############################################# @comment = Comment.new @comments = Comment.where(tweet_id: params[:id]).order("created_at DESC").page(params[:page]).per(5) ####↑追記↑############################################# end #省略Terminal$ rails g controller comments
app/controllers/comments_controller.rbclass CommentsController < ApplicationController def create redirect_to tweets_path unless user_signed_in? @comment = Comment.new(params_comment) @comment.save redirect_to tweet_path(params[:tweet_id]) end private def params_comment params.require(:comment).permit(:text).merge(user_id: current_user.id, tweet_id: params[:tweet_id]) end endapp/views/tweets/show.html.erb<!--省略--> <% if user_signed_in? %> <%= form_with(model: [@tweet, @comment], local: true) do |f| %> <%= f.text_area :text %> <%= f.submit 'コメント'%> <% end %> <% end %> <% if @comments %> <% @comments.each do |c| %> <div><span style="color: blue;"><%= c.user.nickname %></span><%= c.text %></div> <% end %> <%= paginate(@comments) %> <% end %>⑩ユーザー投稿一覧
Terminal$ rails g controller users showconfig/routes.rb# devise_for :usersより下に #省略 resources :users, only: :show #省略app/controllers/users_controller.rbclass UsersController < ApplicationController def show @tweets = Tweet.where(user_id: params[:id]).order("created_at DESC").page(params[:page]).per(5) @nickname = User.find(params[:id]).nickname end endapp/views/layouts/application.html.erb× <%= current_user.nickname %> <!-- | --> <!-- V --> <%= link_to user_path(current_user.id) do %><%= current_user.nickname %><% end %>app/views/tweets/index.html.erb× <div><%= link_to tweet_path(t.id) do %><span style="color: red;"><%= t.user.nickname %></span><%= t.text %><% end %></div> <!-- | --> <!-- V --> <div><%= link_to user_path(t.user.id),style:"color: red;" do %><%= t.user.nickname %><% end %><%= link_to tweet_path(t.id) do %><%= t.text %><% end %></div>app/views/tweets/show.html.erb× <div><span style="color: red;"><%= @tweet.user.nickname %></span><%= @tweet.text %></div> <!-- | --> <!-- V --> <div><%= link_to user_path(@tweet.user.id),style:"color: red;" do %><%= @tweet.user.nickname %><% end %><%= @tweet.text %></div>app/views/users/show.html.erb<p><%= @nickname %>の投稿一覧</p> <% @tweets.each do |t| %> <div><%= link_to tweet_path(t.id) do %><%= t.text %><% end %></div> <% end %> <%= paginate(@tweets) %>⑪検索機能
Terminalrails g controller tweets::searchesconfig/routes.rb#省略 namespace :tweets do resources :searches, only: :index end #省略 # resources :tweets do より上にapp/models/tweet.rb#省略 def self.search(search) if search Tweet.where('text LIKE(?)', "%#{search}%").includes(:user) else Tweet.all.includes(:user) end end #省略app/controllers/tweets/searches_controller.rbclass Tweets::SearchesController < ApplicationController def index @tweets = Tweet.search(params[:keyword]).order("created_at DESC").page(params[:page]).per(5) end endapp/views/tweets/index.html.erb<%= form_with(url: tweets_searches_path, local: true, method: :get) do |f| %> <%= f.text_field :keyword %> <%= f.submit "検索" %> <% end %> <!-- 省略 -->app/views/tweets/searches/index.html.erb<%= form_with(url: tweets_searches_path, local: true, method: :get) do |f| %> <%= f.text_field :keyword %> <%= f.submit "検索" %> <% end %> <% @tweets.each do |t| %> <div><%= link_to user_path(t.user.id),style:"color: red;" do %><%= t.user.nickname %><% end %><%= link_to tweet_path(t.id) do %><%= t.text %><% end %></div> <% end %> <%= paginate(@tweets) %>まとめ
網羅的でいい教材ですね。
これで難しい場合は以下をまわってみてください。
・超最低限のRailsアプリを丁寧に作る(もう一度きちんと復習して初心者を卒業しよう)
・『メッセージを投稿』できる最低限のRailsアプリを丁寧に作る(これで初心者完全卒業!)次のレベルに行きたければ以下に行ってみてください。
・『メッセージと複数画像の投稿』ができる最低限のRailsアプリを丁寧に作る
・『2ページ遷移して会員登録』できる最低限のRailsアプリを丁寧に作る(deviseをウィザード形式に拡張)
・『非同期でのメッセージ投稿』が理解できる最低限のRailsアプリを丁寧に作る(Ajax苦手の自分とお別れしよう)
- 投稿日:2020-03-18T07:02:21+09:00
RspecでProcess.fork内のメソッドを検証したい
fork内のメソッドコールを単純に検証するとうまくいかない
こんなクラスがあるときに
class Dog def crow(str) p str end def walk Process.fork do crow('bowbow!') end end endwalkメソッド内でcrowメソッドが呼び出されていることを検証しようとしてこんなspecを書いてみるとうまく通りません
let(:dog) { Dog.new } it { expect(dog).to receive(:crow).with('bowbow!').once dog.walk }Failures: 1) Dog is expected to receive crow("bowbow!") 1 time Failure/Error: expect(dog).to receive(:crow).with('bowbow!').once (#<Dog:0x00005571aad36820>).crow("bowbow!") expected: 1 time with arguments: ("bowbow!") received: 0 timesforkブロック内は別プロセスなので検証できないのですね。
結論
こういう場合はProcessをmock化してしまうのが手っ取り早いようです。
let(:dog) { Dog.new } it { expect(Process).to receive(:fork) do |&block| expect(dog).to receive(:crow).with('bowbow!').once block.call end dog.walk }
expect_any_instance_of
も利用できますlet(:dog) { Dog.new } it { expect(Process).to receive(:fork) do |&block| expect_any_instance_of(Dog).to receive(:crow).with('bowbow!').once block.call end dog.walk }引数の検証がちゃんとできているのか確認するためにあえて間違った引数を検証してみます。
let(:dog) { Dog.new } it { expect(Process).to receive(:fork) do |&block| expect(dog).to receive(:crow).with('purrr').once block.call end dog.walk }Failures: 1) Dog is expected to receive crow("purrr") 1 time Failure/Error: crow('bowbow!') #<Dog:0x00005588d1a8ed78> received :crow with unexpected arguments expected: ("purrr") got: ("bowbow!")ちゃんと検証してくれているようです。
参考
- 投稿日:2020-03-18T00:09:20+09:00
[Rails]hamlでのform_with/form_for/form_tagの書き方
はじめに
hamlでのformの書き方がまとまっていなかったのでまとめる
※
form_tag
とform_for
はRails5.1
で非推奨となっており、将来的にform_with
に置き換えられる予定です。
極力、Rails5.1以上
とform_with
の使用を推奨します。Railsのformの種類
1. form_tag
- 関連するモデルがない時に使用する(検索機能など)
- inputタグを用いる(ビルドヘルパーを用いない)
<%= form_tag users_path do %> <%= text_field_tag :email %> <%= submit_tag %> <% end %>2. form_for
- 関連するモデルがある時に使用する(投稿機能など)
- ビルドヘルパー(
form.xxxx
)を用いる<%= form_for @user do |form| %> <%= form.text_field :email %> <%= form.submit %> <% end %>3. form_with
- Rails5.1以上は問答無用で ###form_tag/form_forとの違い
- form_withで自動でパスが選択されるので、HTTPメソッド(
get
やpost
など)を指定する必要が無い- コントローラーから渡されたActiveRecordを継承するモデルのインスタンスが利用できる
- form_withは、form_forとform_tagの機能を組み合わせたもの、とイメージすると分かりやすい
#関連するモデルがない場合 → urlの指定のみで、modelの記述がない <%= form_with url: users_path do |form| %> <%= form.text_field :email %> <%= form.submit %> <% end %>#関連するモデルがある場合 → modelの記述のみで、urlの指定は不要 <%= form_with model: @user do |form| %> <%= form.text_field :email %> <%= form.submit %> <% end %>hamlでの書き方
この記事のメインはこちら
form_tag
ビルドヘルパー(
f.text_field
など)は記述しない点に注意= form_tag users_path do = text_field_tag :email = submit_tagform_for
= form_for @user do |f| = f.text_field :email = f.submitform_with
#関連するモデルがない場合 → urlの指定のみで、modelの記述がない = form_with url: users_path do |f| = f.text_field :email = form.submit#関連するモデルがある場合 → modelの記述のみで、urlの指定は不要 = form_with model: @user do |f| = form.text_field :email = form.submit参考記事
【Rails】form_for/form_tagの違い・使い分けをまとめた
【Rails 5】(新) form_with と (旧) form_tag, form_for の違い