- 投稿日:2019-10-04T23:28:29+09:00
railsでscopeがnilを返すとallが返る
railsのscope
- 文字通り、そのクラスの一部のインスタンスを返します
- 意外と知られてないですが、nilを返すとallが返ります
- クラスメソッドと全く同じ挙動ではない。classメソッドはnilを返せばnilが返る
scope
[1] pry(main)> class User < ApplicationRecord [1] pry(main)* scope :nil_scope, ->() { [1] pry(main)* nil [1] pry(main)* } [1] pry(main)* end => :nil_scope [2] pry(main)> User.nil_scope User Load (4.0ms) SELECT `users`.* FROM `users` => [#<User id: 1, email: "xxx@gmail.com", created_at: "2018-04-14 12:05:50", updated_at: "2019-09-05 01:01:24", provider: "facebook", uid: ...] pry(main)> User.nil_scope.size (0.9ms) SELECT COUNT(*) FROM `users` => 355class method
[1] pry(main)> class User < ApplicationRecord [1] pry(main)* def self.nil_scope [1] pry(main)* nil [1] pry(main)* end [1] pry(main)* end => :nil_scope [2] pry(main)> User.nil_scope => nil
- 投稿日:2019-10-04T22:51:12+09:00
turbolinksをfalseのページとtrueのページに分ける
こんばんは!
ポートフォリオ作成中にハマったエラーの簡単な解決方法を備忘録として。いいね機能をremote: trueで動かす
railsチュートリアルにて学習した
remote: true
を使ったajax通信。jsが苦手な私にぴったり!turbolinksが必要みたい
Uncaught ReferenceError: Turbolinks is not defined
application.js/=require turbolinks動きます。
次はこっちが動かないのね
<%= link_to "新規投稿", new_meal_path, class:'hoge'%>
に遷移してfile_field
に画像添付したらimageがpreview表示されなくなったリロードすれば正常に動作します
解決方法
index.html.erb<%= link_to "新規投稿", new_meal_path, class:'hoge',data: {"turbolinks"=>false} %>
data: {“turbolinks" => false}
は遷移先ページのみturbolinksを切ることが出来ますまとめ
jsファイルにajax通信を記述すればturbolinksがtrueでも問題ないみたいです
remote: true
を使ったajax通信とjsイベントを両方実装している時にどちらかのイベント発火しない場合があればdata: {"turbolinks"=>false}
が役立ちます終わり
- 投稿日:2019-10-04T20:33:47+09:00
[Rails]動画プレビュー機能
はじめに
今回以下の様な動画のプレビュー機能を追加したのでその方法について、説明します。
環境
Rails 5.2.3
Ruby 2.5.1導入方法
ビューファイル
気を付ける点は、
file_field
にid: "upload-image"
をjQueryを使用する為に記述します。new.html.haml= form_for @video do |f| 省略 .movie-group-form__field--right--mask = f.label :image, for: "upload-image", class: "movie-group-form__movie" do = fa_icon "cloud-upload fa-spin", class: "icon" = f.file_field :image, class: "hidden", id: "upload-image" = f.label :動画を選択してください , class: "movie-group-form__choice" = f.submit "投稿する", class: "btn btn-dark"jQuery
次にJSファイルに動画プレビューをさせる記述をします。
$fileField
にビューのid
に記述したupload-image
に#
を付けて記述します。
$preview
には動画をプレビュー表示させたい部分(今回は.movie-group-form__choice
)に記述します。
$preview.append($('<video>').attr({
内にCSSを記述してます。autoplay: "autoplay"
、loop: "loop"
で動画のプレビューをオート再生させています。
playsinline: "true"
はスマホで動画を投稿した際に、オート再生するのに使用します。preview.js$(document).on('turbolinks:load', function() { $fileField = $('#upload-image') $($fileField).on('change', $fileField, function(e) { file = e.target.files[0] reader = new FileReader(), $preview = $(".movie-group-form__choice"); reader.onload = (function(file) { return function(e) { $preview.empty(); $preview.append($('<video>').attr({ src: e.target.result, width: "45%", height: "110px", class: "preview-image", autoplay: "autoplay", loop: "loop", playsinline: "true", title: file.name })); }; })(file); reader.readAsDataURL(file); }); });今回はJS内にCSSを直接記述しているので、CSSファイルの変更は必要ないです。後は好みで調整して下さい。
まとめ
動画のプレビューも画像のプレビューとほぼ同じで、後はappendに
'<video>'
か'<img>'
を記述するだけで、動画か画像のプレビュー表示かを変更する事が出来ます。気になったら試してみて下さい。
- 投稿日:2019-10-04T19:10:11+09:00
moduleとmixin
モジュール
module SampleModule CONST_NUM =100 def const_num CONST_NUM end end puts SampleModule::CONST_NUM # moduleをincludeしたあとならモジュール名を省略して定数に直接アクセスできるようになる include SampleModule puts CONST_NUM puts const_num
module_function
を使うことでmodule
名に.をつけてメソッドを呼び出せるようになるmodule SampleModule def module_function_sum(a, b) a + b end module_function :module_function_sum end SampleModule.module_function_sum(1, 100) => 101ミックスイン
モジュールの機能をクラスに取り込むには
include モジュール名
とするmodule SampleModule def sum(a, b) a + b end end class Sample include SampleModule def class_sum(a, b) sum(a, b) end end実行してみる
sample = Sample.new puts sample.sum(1, 100) => 101 puts sample.class_sum(1, 100) => 101使い道
- 複数のクラスで使う共通のメソッドを
module
として定義し、適宜include
して使う- 特定のメソッドを
module
としてまとめておきユーティリティーとして使用する
- 投稿日:2019-10-04T17:42:41+09:00
imagemagickを使って画像をアップロードするとSSLが外れてしまう時の対処法
minimagickのgemを使って画像をアップロードすると、その画像が表示されるページのSSLマークが外れるという問題が発生したので、その時の解決方法を残します。
このサイトで目にする画像は、悪意のあるユーザーによって差し替えられたものである可能性があります
事象
・minimagickのgemを使って画像をアップロードすると、その画像が表示されるページでSSLマーク(鍵マーク)が外れ、びっくりマークに変わる
・びっくりマークをクリックすると「このサイトで目にする画像は、悪意のあるユーザーによって差し替えられたものである可能性があります」のメッセージがでる。解決方法
nginxのconfファイルにproxy_set_header X-Forwarded-Proto https;を追記
/etc/nginx/conf.d/hoge.conflocation @app { proxy_set_header Host $http_host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Host $http_host; proxy_set_header X-Forwarded-Server $hostname; proxy_set_header X-Forwarded-Proto https; #この一行を追加 proxy_set_header X-Real-IP $remote_addr; proxy_redirect off; proxy_pass http://app_server; }Nginx再起動
systemctl restart nginx解決までの流れ
①画像ファイルへのリンクの確認
この事象はサイト内で使用している画像に、httpアクセスで記述している箇所があると発生するらしいので、デベロッパーツールで画像リンクのプロトコルを確認。
参考:https://stackdesign.jp/how-to-create-ssl-wordpress-site/→きちんとhttpsになってた。
②Railsの環境設定を変更
production.rbのconfig.force_ssl = trueを有効にすると、本番環境でSSL通信を強制できるので、コメントアウトを外し設定を有効にして再デプロイ。
参考:https://railsguides.jp/configuring.html/config/environments/production.rbconfig.force_ssl = true→ページにアクセスできなくなる
メッセージ
・このページは動作していません
・リダイレクトが繰り返し行われました。→再びコメントアウト
③nginxのconfファイル修正
HTTPSアクセスであることをX-Forwarded-ProtoでRailsへ通知することでリダイレクトのループを回避する。
参考:https://keruuweb.com/rails-nginx-https%E3%81%A7%E3%82%A2%E3%82%AF%E3%82%BB%E3%82%B9%E3%82%92%E3%81%99%E3%82%8B//etc/nginx/conf.d/hoge.conflocation @app { proxy_set_header X-Forwarded-Proto https; #この一行を追加 }→無事に全ページでSSL化が有効になりました
まとめ
「proxy_set_header X-Forwarded-Proto https;」はリダイレクトのループを回避するための設定で、本来はSSL化をする際に設定しておく必要があったらしい。
SSL化の際にきちんと設定ができていたら、そもそも今回のエラーは生じなかったってことですね、、、
- 投稿日:2019-10-04T15:50:48+09:00
[初学者]findメソッドについて(ruby)
目的
学習の備忘録と初学者の参考資料として投稿
findメソッド
該当するモデルのテーブルからデータを検索する際に使われるメソッド。
例えば・・・
userテーブル
id name age gender 1 taro 12 male 2 hanako 11 female 3 jiro 10 male 4 keiko 9 female 検索して表示させたい→
id name age gender ○○○ ○○○ ○○○ ○○○ users_controller.rbdef show @user = User.find(user:id) idを引数として検索する end *viewは省略findは検索条件として指定できるものは「idのみ」です。データを複数取得できます。
findとfind_byの違い
find_byは、複数の条件を指定したりid以外のカラムでも検索できます。データは条件があった中で最初の一つのみ取得できる。
find_by(gender:"male") 上の例から、こんな感じで検索する。まとめ
テーブルからデータを表示や更新や削除する場合によく使うメソッドです。他にもwhereというメソッドもあります。
今後も学習で気づきや参考になるものがあれば、アップしていきます。
もし参考になったらいいね!!よろしくお願いします
- 投稿日:2019-10-04T15:14:02+09:00
【Rails】jQueryでフォームに文字数カウントをつける
フォームに文字を入力していく時、あと何文字まで打てるのか分かった方がユーザーに優しいと思ったため、文字数カウント機能を作りました。
▷今回やること
フォームに残り何文字入力できるかを表示する文字数カウント方法を考える
・文字を入力したり、消したりするたびフォームの文字数を数える → 残り何文字まで入力できるか表示する
・文字数がオーバーしていた場合、文字色を赤にする → ユーザーに警告する文字数カウントのアルゴリズムを考える
jQueryで文字数カウントをする
▷jsが読み込まれたら以下の処理をする ・処理内容(ページが読み込まれた時、フォームに残り何文字入力できるかを数えて表示する) フォームのvalueを取得して文字数を数える <!-- Macの改行コードは1文字(\n)であるが、Rails側では改行コードが2文字(\r\n)で保存されるため、\nは2文字とカウントするように設定 --> 最大文字数 ー 取得した文字数 (=残りの入力できる文字数) if 最大文字数より取得文字数の方が大きい 表示する文字色を赤にする “あと (残りの入力できる文字数)文字” と表示する ▷jQueryのkeyup()でキーボードが押されて離れるたびに処理を行う ・処理内容(キーボードを押した時、フォームに残り何文字入力できるかを数えて表示する) フォームのvalueを取得して文字数を数える。 <!-- Macの改行コードは1文字(\n)であるが、Rails側では改行コードが2文字(\r\n)で保存されるため、\nは2文字とカウントするように設定 --> 入力最大文字数 ー 取得した文字数 (=残りの入力できる文字数) if 最大文字数より取得文字数の方が大きい 表示する文字色を赤にする “あと (残りの入力できる文字数)文字” と表示する else 表示する文字色を黒にする ”あと (残りの入力できる文字数)文字” と表示する 処理終了 処理終了コードで文字数カウント処理を書く
1.htmlでフォーム入力タグと文字数表示タグにclassを設定し、jsで指定できるようにする
フォーム入力タグtext_areaのクラスに
js-text
、文字数表示タグpのクラスにjs-text-count
を指定する
(フォームにbootstrapを適用しています)form.html.erb<%= form_for(@profile) do |f| %> <div class="panel-body"> <div class="form-group"> <%= f.label :yourself, '自己紹介(最大150文字)' %> <%# js-textをclassに追加 %> <%= f.text_area :yourself, class: 'form-control js-text', rows: 6, placeholder: '改行は反映されません' %> <%# js-text-count をclassに追加 %> <P class="js-text-count pull-right"></P> </div> <div class="text-center"> <%= f.submit '保存する', class: 'btn btn-info'%> </div> <% end %>2.jsファイルにフォームと文字数表示に対する処理を書く
js-text
のvalueを数えて、js-text-count
に結果を表示する
app/assets/javascripにcount.jsファイルを作成し、文字数カウントの処理を書いていく
(今回のフォームの最大文字数は150)app/assets/javascrip/count.js// jquery書きはじめ $(function (){ // 処理(ページが読み込まれた時、フォームに残り何文字入力できるかを数えて表示する) //フォームに入力されている文字数を数える //\nは"改行"に変換して2文字にする。オプションフラグgで文字列の最後まで\nを探し変換する var count = $(".js-text").text().replace(/\n/g, "改行").length; //残りの入力できる文字数を計算 var now_count = 150 - count; //文字数がオーバーしていたら文字色を赤にする if (count > 150) { $(".js-text-count").css("color","red"); } //残りの入力できる文字数を表示 $(".js-text-count").text( "残り" + now_count + "文字"); $(".js-text").on("keyup", function() { // 処理(キーボードを押した時、フォームに残り何文字入力できるかを数えて表示する) //フォームのvalueの文字数を数える var count = $(this).val().replace(/\n/g, "改行").length; var now_count = 150 - count; if (count > 150) { $(".js-text-count").css("color","red"); } else { $(".js-text-count").css("color","black"); } $(".js-text-count").text( "残り" + now_count + "文字"); }); });3.リンクをクリックしてページ遷移した時、jacascriptを読み込むようにする
現在のままでは、ページ遷移してもjsが機能しない
▷原因
rails4.0からデフォルトで導入されたgem「turbolinks」が読み込まれているため〜turbolinksとは〜
画面遷移を高速化させるライブラリ。
ページ遷移するとき、現在のページのtitleとbodyだけを抜き取り、
新しいhtmlのtitleとbodyに交換することで、ページ遷移を高速化させる。
→ページ読み込みを起点としたJavascriptは機能しなくなる
jQuery を使用している場合、 下記の様にページが読み込まれたときの処理を記述出来ますが、 Turbolinksによって、実行されなくなります。
$(function() {
#処理内容
});▷解決方法
count.jsを読み込みたいリンクのtubolinksを無効にする
aタグはdata-turbolinks="false"
、link_toメソッドはdata: {"turbolinks" => false}
でtubolinksを無効化できるリンク設定がaタグの場合
<a href=“◯◯” data-turbolinks="false">turbolinksを使わずにリンクする</a>リンク設定がlink_toメソッドの場合
<%= link_to "turbolinksを使わずにリンクする", ◯◯_path, data: {"turbolinks" => false} %>これでページ遷移した時、count.jsが読み込まれるようになり、文字数カウント処理が行われる。
参考
・[簡単すぎる]Rails + jQueryで文字数カウント
・【JavaScript】文字列から改行を全て削除する方法
・turbolinksチートシート
・『Turbolinks』って、なんぞ?
- 投稿日:2019-10-04T15:09:14+09:00
ブログ投稿サイトを作ってみました
こんにちは。
本日は初投稿ということで、プログラミングを始めて2週間少しの初心者が0から作った作品を紹介します。
ーーーーーーーーブログ投稿サイト
トップ画面
ユーザー新規登録、ログイン画面
投稿画面
詳細確認画面
(写真引用元:https://www.travel.co.jp/guide/article/24996/)1. 実装機能
・ユーザ登録、ログイン、ログアウト可能
・投稿はタイトル、本文、画像のみ(非ログイン時は投稿不可)
・投稿したユーザ本人による投稿の編集、削除が可能
・ログインしていなくても投稿一覧、詳細が閲覧可能
・ページネーション機能(投稿は新着順)2. 使用言語・ツール
・Ruby
・Haml/Sass
・JQuery
・Ruby on Rails
・Bootstrap3. 工夫した点
bootstrapというwebアプリケーションフレームワークを使用し、
ボタンやページネーション等を簡単に作成、装飾してみました。
フォームなどにも適用させて、もっと簡単に作成するのが理想でしたが、
公式サイトはもちろん英語だったのでなかなか上手く使えなかったのが少し残念なところです。。。
あとは綺麗な画像を貼ることで見栄えを良くしました!笑4. 苦労した点
devise gem をインストール後、userテーブルをmigrateする際にエラーが発生し、
解決に時間が掛かりました。
エラー内容は「max key length is 767 bytes(768バイト以上のカラムに対するインデックスキーは設定できないよ)」と言った内容。
調べてみると、MySQLの単一カラムインデックスのインデックスキーは、デフォルトで
最大 767 バイトまでとのことでした...。
マイグレーションファイルに於いて、string 型の容量にリミットをつけてあげることで解決出来ました。
ex) t.string :reset_password_token, limit: 1915. 感想
制作時間の半分以上がエラーとの奮闘でしたが、解決した時にはこの上ない感動でした。
普段使っているウェブサイト、アプリ、何から何までこんなに苦労しているんだなと感じることができました。
「こんな機能があるといいな」「こんな風に配置したいな」と、色々とこだわりを入れたかったのですが、そこは自分の今の技術的に厳しめだったので断念。
これからも毎日勉強して、良いものを作ろうと思いました!
- 投稿日:2019-10-04T14:24:41+09:00
日時の扱い方
日時の扱い方
Rubyには日付や時刻を扱うためのDateやTimeといったクラスがあります。そのため、Rialsアプリケーションで日付や時刻を扱う際にもただこれらのクラスを使えばいいと思われるかもしれませんが、ひとつ課題があります。それは、タイムゾーンです。
例えば、Railsアプリケーションがデータベース内に、ある日時を保存するとしましょう。その日時を東京に住むユーザーが見たときは東京時間、シンガポールに住む人が見たときはシンガポール時間で表示した方が良いでしょう。このように、地域の時間に合わせた日時を表示する必要があるということです。そのため、Railsでは日時のデータをタイムゾーンとともに取り扱うことができるようになっている。
タイムゾーンとともに日時を扱うには、Timeの代わりにActiveSupport::TimeWithZoneクラスを用います。Railsが日時を扱う際(日時型のデータをデータベースから読むときや、created_atなどのタイムスタンプを記録する際)には、自動的にこのクラスが利用されます。
それでは、Railsコンソールを立ち上げて挙動を確認してみましょう。(※Rialsアプリケーションのコンソールで動作します。)
まず、現在有効なタイムゾーンを確認してみましょう。Time.zoneと売ってみてください。何も手を加えていないRailsアプリケーションでは次のように、"UTC"という名前を持つActiveSupport::TimeZoneオブジェクトが返されるはずです。これは、UTC(協定世界時)タイムゾーンを意味しています。
2.6.0 :013 > Time.zone => #<ActiveSupport::TimeZone:0x000000000a8e9568 @name="UTC", @utc_offset=nil, @tzinfo=#<TZInfo::DataTimezone: Etc/UTC>>続いて、そのUTCタイムゾーンにおける現在時刻を表すオブジェクトを取得しましょう。それには、Time.zone.nowを実行します。
2.6.0 :003 > Time.zone.now => Fri, 04 Oct 2019 13:52:47 JST +09:00Time.zone.nowは、ActiveSupport::TimeWithZoneクラスのオブジェクトとなっています。試しに、classメソッドを調べてみましょう。
2.6.0 :004 > Time.zone.now.class => ActiveSupport::TimeWithZone確かにそのようになっていますね。
オブジェクトの作成日時を表すreated_atなどもActiveSupport::TImeWithZoneのオブジェクトとなっています。
タイムゾーンの変更
タイムゾーンは「現在のタイムゾーン」に当たります。データベースからモデルオブジェクトを取ってくると、オブジェクト内のcreated_atやupdated_atは、Time.zoneで示されたタイムゾーンに対応する時間オブジェクトとなります。
したがって、もしもモデルのcreated_atなどを日本時間での時間オブジェクトとして取得したいのであれば、Time.zoneを日本時間に指定してからオブジェクトを取得すれば良いということになります。試しに、Time.zoneに日本時間を指定してみましょう。次のように、Time.zoneにAsia/Tokyoを代入してみてください。
2.6.0 :009 > Time.zone = 'Asia/Tokyo' => "Asia/Tokyo"これで設定が変わるので、Time.zone.nowを実行すると、今度は日本時間での現在時刻が取得できます。
2.6.0 :010 > Time.zone => #<ActiveSupport::TimeZone:0x000000000a8d9e10 @name="Asia/Tokyo", @utc_offset=nil, @tzinfo=#<TZInfo::DataTimezone: Asia/Tokyo>> 2.6.0 :011 > Time.zone.now => Fri, 04 Oct 2019 14:19:30 JST +09:00同様に、クラスのcreated_atも、日本時間のオブジェクトを取得できるようになりました。
2.6.0 :018 > User.first.created_at => Fri, 04 Oct 2019 02:14:57 UTC +00:00
- 投稿日:2019-10-04T13:51:44+09:00
Rubyの標準ライブラリ net/http を使って kintone の REST API を叩いてみる
このところ学習用にkintoneのREST API を色々と叩いているのですが、そういえば大好きなRubyからだってHTTPリクエスト投げれればできそうじゃんね。と思ったんでやってみました。
色々試しながら上手くいったものから、都度追加していくよ。
レコード
レコードの取得(GET)
https://developer.cybozu.io/hc/ja/articles/202331474
get_record.rburl = "https://#{ENV['SUBDOMAIN']}.cybozu.com/k/v1/record.json" uri = URI.parse(url) api_token = ENV['SELECT_TOKEN'] req = Net::HTTP::Get.new(uri.path) req['X-Cybozu-API-Token'] = api_token req['Content-Type'] = 'application/json' req.body = JSON.generate({"app" => "100", "id" => "1"}) Net::HTTP.start(uri.host, uri.port, :use_ssl => true) {|http| res = http.request(req) case res.code.to_i when 200 pp JSON.parse(res.body) else pp %Q(#{res.code} #{res.message}) pp JSON.parse(res.body) end }get_records.rburl = "https://#{ENV['SUBDOMAIN']}.cybozu.com/k/v1/records.json" uri = URI.parse(url) api_token = ENV['SELECT_TOKEN'] req = Net::HTTP::Get.new(uri.path) req['X-Cybozu-API-Token'] = api_token req['Content-Type'] = 'application/json' fields = ["\$id", "商品名", "金額"] query = %q(金額 >= "50000") req.body = JSON.generate({"app" => "100", "fields" => fields, "query" => query, "totalCount" => true})レコードの一括取得
https://developer.cybozu.io/hc/ja/articles/360029152012
カーソルの作成
get_records_cursor.rburl = "https://#{ENV['SUBDOMAIN']}.cybozu.com/k/v1/records/cursor.json" uri = URI.parse(url) api_token = ENV['SELECT_TOKEN'] req = Net::HTTP::Post.new(uri.path) req['X-Cybozu-API-Token'] = api_token req['Content-Type'] = 'application/json' fields = ["\$id", "商品名", "金額"] query = %q(金額 >= "50000") req.body = JSON.generate({"app" => "100", "fields" => fields, "query" => query, "totalCount" => true, "size" => "500"}) cursor = "" Net::HTTP.start(uri.host, uri.port, :use_ssl => true) {|http| res = http.request(req) case res.code.to_i when 200 pp JSON.parse(res.body) cursor = JSON.parse(res.body)["id"] pp cursor else pp %Q(#{res.code} #{res.message}) pp JSON.parse(res.body) end }カーソル範囲のレコード取得
get_records_cursor.rbreq = Net::HTTP::Get.new(uri.path) req['X-Cybozu-API-Token'] = api_token req['Content-Type'] = 'application/json' req.body = JSON.generate({"id" => cursor}) Net::HTTP.start(uri.host, uri.port, :use_ssl => true) {|http| res = http.request(req) case res.code.to_i when 200 pp JSON.parse(res.body) else pp %Q(#{res.code} #{res.message}) pp JSON.parse(res.body) end }ファイルアップロード
https://developer.cybozu.io/hc/ja/articles/201941824
kintoneの領域にファイルをアップロードします。
ファイルアップロード
file.rbbegin upload_file = File.open '1.txt', "r" data = [["file", upload_file, {"filename" => "1.txt", "content_type" => "text/plain"}]] url = "https://#{ENV['SUBDOMAIN']}.cybozu.com/k/v1/file.json" uri = URI.parse(url) api_token = ENV['SELECT_TOKEN'] req = Net::HTTP::Post.new(uri.path) req['X-Cybozu-API-Token'] = api_token req['Content-Type'] = 'multipart/form-data' req.set_form(data, "multipart/form-data") pp req Net::HTTP.start(uri.host, uri.port, :use_ssl => true) {|http| res = http.request(req) res.each_header do |name, val| puts "name=#{name}, val=#{val}" end case res.code.to_i when 200 pp JSON.parse(res.body) else pp %Q(#{res.code} #{res.message}) pp JSON.parse(res.body) end } rescue => exception pp exception upload_file.close endアップロードしたファイルとレコードの関連付け
https://developer.cybozu.io/hc/ja/articles/201941784
アップロードしたファイルの filekey と kintoneレコードを紐付けします。
レコードの更新APIを利用します。file_upload.rbbegin url = "https://#{ENV['SUBDOMAIN']}.cybozu.com/k/v1/record.json" uri = URI.parse(url) api_token = ENV['UPDATE_TOKEN'] req = Net::HTTP::Put.new(uri.path) req['X-Cybozu-API-Token'] = api_token req['Content-Type'] = 'application/json' req.body = JSON.generate({ "app" => "100", "id" => "1", "record" => {"file" => {"value" => [{"fileKey"=>"590279cd-6657-419f-8fac-d760a4a6caaa"}]}} }) Net::HTTP.start(uri.host, uri.port, :use_ssl => true) {|http| res = http.request(req) res.each_header do |name, val| puts "name=#{name}, val=#{val}" end case res.code.to_i when 200 pp JSON.parse(res.body) else pp %Q(#{res.code} #{res.message}) pp JSON.parse(res.body) end } rescue => exception pp exception end
アプリ
フォームの設定の取得
フィールドの一覧を取得する
https://developer.cybozu.io/hc/ja/articles/204783170#anchor_getform_fields
get_app_fields.rbrequire 'rubygems' require 'bundler/setup' require 'dotenv/load' require 'net/http' require 'uri' require 'json' require 'base64' require 'pp' url = "https://#{ENV['SUBDOMAIN']}.cybozu.com/k/v1/app/form/fields.json" uri = URI.parse(url) pass_auth = Base64.strict_encode64("#{ENV['UID']}:#{ENV['PASS']}") req = Net::HTTP::Get.new(uri.path) req['Content-Type'] = 'application/json' req['X-Cybozu-Authorization'] = pass_auth req.body = JSON.generate({"app" => "100"}) Net::HTTP.start(uri.host, uri.port, :use_ssl => true) {|http| res = http.request(req) case res.code.to_i when 200 pp JSON.parse(res.body) else pp %Q(#{res.code} #{res.message}) pp JSON.parse(res.body) end }アプリのプロセス管理の設定の取得
https://developer.cybozu.io/hc/ja/articles/216972946
プロセスにはAPIトークン認証は使えません。代わりにパスワード認証を使います。
status.rburl = "https://#{ENV['SUBDOMAIN']}.cybozu.com/k/v1/app/status.json" uri = URI.parse(url) req = Net::HTTP::Get.new(uri.path) pass_auth = Base64.strict_encode64("#{ENV['UID']}:#{ENV['PASS']}") req['X-Cybozu-Authorization'] = pass_auth req['Content-Type'] = 'application/json' req.body = JSON.generate({"app" => "100", "lang" => "ja"}) Net::HTTP.start(uri.host, uri.port, :use_ssl => true) {|http| res = http.request(req) case res.code.to_i when 200 pp JSON.parse(res.body) else pp %Q(#{res.code} #{res.message}) pp JSON.parse(res.body) end }
- クエリ文字列
結果は同じです。
status_url.rburl = "https://#{ENV['SUBDOMAIN']}.cybozu.com/k/v1/app/status.json?app=100&lang=ja" uri = URI.parse(url) pass_auth = Base64.strict_encode64("#{ENV['UID']}:#{ENV['PASS']}") Net::HTTP.start(uri.host, uri.port, :use_ssl => true) {|http| res = http.get("#{uri.path}?#{uri.query}", {'X-Cybozu-Authorization' => pass_auth}) res.each_header do |name, val| puts "name=#{name}, val=#{val}" end case res.code.to_i when 200 pp JSON.parse(res.body) else pp %Q(#{res.code} #{res.message}) pp JSON.parse(res.body) end }
スペース情報の取得
https://developer.cybozu.io/hc/ja/articles/202166200
スペース情報の取得はAPIトークン認証が使えません。
代わりにパスワード認証を使ってください。space.rburl = "https://#{ENV['SUBDOMAIN']}.cybozu.com/k/v1/space.json" uri = URI.parse(url) req = Net::HTTP::Get.new(uri.path) pass_auth = Base64.strict_encode64("#{ENV['UID']}:#{ENV['PASS']}") req['X-Cybozu-Authorization'] = pass_auth req['Content-Type'] = 'application/json' req.body = JSON.generate({"id" => "1"}) Net::HTTP.start(uri.host, uri.port, :use_ssl => true) {|http| res = http.request(req) case res.code.to_i when 200 pp JSON.parse(res.body) else pp %Q(#{res.code} #{res.message}) pp JSON.parse(res.body) end }API情報
API 一覧の取得
https://developer.cybozu.io/hc/ja/articles/201941934
認証情報は必要ありません。
apis.rburl = "https://#{ENV['SUBDOMAIN']}.cybozu.com/k/v1/apis.json" uri = URI.parse(url) req = Net::HTTP::Get.new(uri.path) Net::HTTP.start(uri.host, uri.port, :use_ssl => true) {|http| res = http.request(req) case res.code.to_i when 200 pp JSON.parse(res.body) else pp %Q(#{res.code} #{res.message}) pp JSON.parse(res.body) end }
環境
- macOS 10.13.6
- ruby 2.5.0
リンク
雑記
やってみたら、まあ普通にできた。
やっぱりRubyいいな。
- 投稿日:2019-10-04T13:22:13+09:00
RailsアプリにRSpecを導入する手順
はじめに
RSpecはRubyのテストフレームワークです。これ以外にMinitestというものがありますが、実際の現場では、RSpecが使われることが多いようなので導入する手順をメモしておきます。
環境
Widows 10
cloud9RSpecをインストール
gemを追加
最近はsystemスペックの利用が推奨されています。systemスペックは、バージョンが3.8.0以上である必要があるためそれをインストールしましょう。Gemfilegroup :development, :test do gem 'rspec-rails' # バージョン指定する必要があるかも'~> 3.8.0' end$ bundle installRSpecをインストールする
$ rails generate rspec:install必須ではないが、RSpec の出力をデフォルトの形式から読みやすいドキュメント形式に変更できる。やっといたほうが見た目が良くなるのでおすすめです。
.rspec--require spec_helper --format documentationテストを速くする
このgemを追加するとSpringにより、テストスイートが速くなる。必要だと思ったら入れてください。Gemfilegroup :development do gem 'spring-commands-rspec' end # bundle installを忘れずに!そしたら、以下のコマンドを実行して下さい。
$ bundle exec spring binstub rspecそしてこれからは、RSpecのコマンドを打つ際先頭に、bin/をつけるようにしましょう。
ジェネレータ
rails g する際に一緒にスペックファイルも生成されるようにする。また、あまり使うことのないファイルは生成されないようにします。コードが複雑になってきたら使うかもしれないので、その時は削除していってください。config/application.rb. . module Sample class Application < Rails::Application config.generators do |g| g.test_framework :rspec, fixtures: false, # factory_bot_railsを使うなら削除してください view_specs: false, helper_specs: false, routing_specs: false end end endこれで基本的なセットアップは終了です!
便利なgem
ここからはRSpecを使っていく際に便利なgemを紹介します。最新のものを使うようにしましょう。
Gemfilegroup :development, :test do gem 'factory_bot_rails' # テストのサンプルデータを生成できる end group :test do gem 'capybara' #統合テスト(system)をするのに必要 gem 'launchy' # save_and_open_page をスペック内で呼びだしたときに、HTMLを自動的に開く gem 'webdrivers' # js付きののテストができるようになる。 endCapybaraのセットアップ
Capybaraを読み込めるように、requireする。spec/rails_helper.rb# その他の設定 require 'capybara/rspec'Capybaraで、JavaScriptを使ったテスト
1 設定ファイルを書く
rails_helper.rbに直接書いてもいいが、今後設定が多くなってくると見にくくなるので、独立したファイルに設定を書いていきます。spec/rails_helper.rbDir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f } #このコメントアウトを外す。これで、supportディレクトリ下にあるファイルを読み込めるようになる。このディレクトリを作り、そこにcapybara.rbというファイルを生成し、設定を書きます。
spec/support/capybara.rbCapybara.javascript_driver = :selenium_chrome or Capybara.javascript_driver = :selenium_chrome_headless # ヘッドレスモードを使いたい場合2 gemを追加
webdriversは、selenium-webdriver も一緒にインストールしてくれるので、selenium-webdriver がある場合は削除しといてください。Gemfilegem 'webdrivers'これで、js: trueオプションをつけることで、JavaScript付きのテストができる。
cloud9でヘッドレスモードを使えるようにする
僕は今、cloud9を使っているので、ここで使えるようにしていきます。cloud9では、ヘッドレスモードしかできないみたいです。1 Chromeブラウザをインストール
初期のAWSは、Chromeがインストールされてないのでインストールする。$ curl https://intoli.com/install-google-chrome.sh | bash2 ヘッドレスモードにする
spec/support/capybara.rbCapybara.javascript_driver = :selenium_chrome_headless3 selenium-webdriverとcapybaraを最新版にする
$ bundle update selenium-webdriver capybaraDeviseのヘルパーメソッドを使えるようにする
これを記述することで、コントローラー、システム、リクエストスペックでDeviseのヘルパーメソッドである、sign_inが使えるようになる。
また、リクエストスペックの場合、Deviseのヘルパーメソッド使うために、少し設定が必要。spec/rails_helper.rb# その他の設定 RSpec.configure do |config| # その他の設定 config.include Devise::Test::ControllerHelpers, type: :controller config.include Devise::Test::IntegrationHelpers, type: :system config.include RequestSpecHelper, type: :request endリクエストスペックの追加設定
新しいファイルを作って設定を記述。spec/support/request_spec_helper.rbmodule RequestSpecHelper include Warden::Test::Helpers def self.included(base) base.before(:each) { Warden.test_mode! } base.after(:each) { Warden.test_reset! } end def sign_in(resource) login_as(resource, scope: warden_scope(resource)) end def sign_out(resource) logout(warden_scope(resource)) end private def warden_scope(resource) resource.class.name.underscore.to_sym end end
- 投稿日:2019-10-04T13:04:15+09:00
[初学者]よく起こるエラー〜ActiveRecord::PendingMigrationError 〜
目的
学習の備忘録と初学者の参考資料として投稿
ActiveRecord::PendingMigrationErrorというエラー
MVCの一角であるモデルを作成するため、ターミナルで・・・・
<ターミナル> $ rails g model ○○○○(モデル名) ・・・ちょっくら確認してみるか $ rails sエラー発生!!!!
ActiveRecord::PendingMigrationError〜、あちゃ〜
忘れてた
解決方法
<ターミナル> $ rails db:migrate>>解決!!
そもそもマイグレーションとは
SQLを書くことなくRubyでデータベース内にテーブルを作成することができる機能。わざわざ面倒くさい事をマイグレーションファイルが行ってくれている。なので絶対忘れずにマイグレーションしよう!!
[参考]ちなみによく見る『schema.rb』とは
マイグレーションした際に作成されるファイルで、テーブルのカラムやそのデータ型などマイグレーションした結果が書かれている。マイグレーションするたびに最新の状態へ更新。実際ファイルを見てみるといままでのマイグレーションの履歴が見れる。
まとめ
モデルを作成したら、すぐにマイグレーション実行しよう!!
ちなみにマイグレーションファイルを勝手に削除すると大変な事に・・・・・
消さないでね
今後も学習で気づきや参考になるものがあれば、アップしていきます。
もし参考になったらいいね!!よろしくお願いします
- 投稿日:2019-10-04T12:54:25+09:00
Rails console で日付操作をするときのメモ
データの日付情報を変更したいときの備忘録。
準備
まずはじめにdateという情報を持ってるHogeテーブルがあるとする。
何度も入力するのが手間なので、変更したいdateが入ってるidを持ったHogeを指定し、変数に格納します。hoge = Hoge.find(1234)agoとsinceを使う
agoは◯日前、sinceは◯日後、というふうになります。ただしこの場合、「今この瞬間から2日前」というふうになるので注意しないとだめです。
hoge.update(date: 2.days.ago)hoge.update(date: 2.days.since)おわりに
よくつかうのでメモに残しておきました⭐
- 投稿日:2019-10-04T12:36:35+09:00
Rails6 のちょい足しな新機能を試す89(Event object編)
はじめに
Rails 6 に追加された新機能を試す第89段。 今回は、
Event object
編です。
Rails 6 では、ActiveSupport::Notifications.subscribe
で、ブロックパラメータを1つにすると、そのブロックパラメータにActiveSupport::Notifications::Event
オブジェクトが設定されるようになりました。
これで、ブロックの中でActiveSupport::Notifications::Event.new
を使う必要がなくなりました。Ruby 2.6.4, Rails 6.0.0 で確認しました。
$ rails --version Rails 6.0.0今回は、User の CRUD を作り、各コントローラのアクションを実行したときの情報を取得してログに出力してみます。
プロジェクトを作る
rails new rails_sandbox cd rails_sandbox
User の CRUD を作る
name をもつ User の CRUD を作ります
bin/rails g scaffold User nameSubscribe する
config/initializers/notification_subscriber.rb
を作成します。
ActiveSupport::Notifications.subscribe
を呼び出すときに、ブロックパラメータをevent
1つだけにします。config/initializers/notification_subscriber.rbActiveSupport::Notifications.subscribe 'process_action.action_controller' do |event| action = "#{event.payload[:controller]}##{event.payload[:action]}" Rails.logger.info("#{action} cpu_time=#{event.cpu_time} duration=#{event.duration} allocations=#{event.allocations}") endUser の登録などをしてログを確認する
実際に
rails server
を実行してブラウザから http://localhost:3000/users にアクセスします。以下のようにコンソールに出力されているはずです。
... UsersController#index cpu_time=833.013591 duration=840.9244199865498 allocations=1237733試したソース
試したソースは以下にあります。
https://github.com/suketa/rails_sandbox/tree/try089_subscriber_event参考情報
- 投稿日:2019-10-04T11:52:01+09:00
ゲストログイン機能の実装方法(ポートフォリオ用)
ポートフォリオ用のWebサイトに必須と言われるゲストログイン機能。
特に
Devise
のconfirmable
を使用している場合は,ゲストログイン機能が無いと,新規登録が面倒という理由でポートフォリオを見てすらもらえない可能性が高くなります。ところが,普通のWebサイトには絶対に導入しないためか,記事が見当たりませんでした。そこで,私のたどりついた実装方法を備忘録としてアップしておきます。
ゲストログイン機能の実装方法
以下,
Devise
を使用している前提とします。config/routes.rbpost '/homes/guest_sign_in', to: 'homes#guest_sign_in'app/controllers/homes_controller.rbclass HomesController < ApplicationController def guest_sign_in user = User.find_or_create_by(email: 'guest@example.com') do |user| user.password = SecureRandom.urlsafe_base64 user.confirmed_at = Time.now # Devise の confirmable を使用している場合は必須 end sign_in user redirect_to root_path, notice: 'ゲストユーザーとしてログインしました。' end endapp/views/homes/index.html.erb<%= link_to 'ゲストログイン(閲覧用)', homes_guest_sign_in_path, method: :post %>
ポイントは
Devise
のsign_in
メソッドを利用することです。ゲストユーザーをあらかじめ作成する手間を省くため,
find_by
ではなく,find_or_create_by
を利用しています。パスワードを把握する必要はないので,ランダム文字列にしています。備考
メールアドレス
,パスワード
を変更できるように設定する場合は,ゲストユーザーのメールアドレスなどを変更されないように注意する必要があります。実は,最初,
devise/sessions/new.html.erb
の真似をして,hidden_field
を加えて……という手順で実装しようとしました。ところが,この方法ではuser_email
,user_password
などのidセレクタが重複するエラーが出てしまいます。そこで,sign_in
メソッドの存在を思い出し,このような実装方法にたどりつきました。おまけ
ゲストユーザーのデータを定期的に初期化するため,実際にはこのような形式で実装しました。
name
カラムはニックネーム
,content
は自己紹介文
の想定です。app/controllers/homes_controller.rbclass HomesController < ApplicationController def guest_sign_in new_user_check = false user = User.find_or_create_by(email: 'guest@example.com') do |user| user.password = SecureRandom.urlsafe_base64 user.confirmed_at = Time.now new_user_check = true end # 新規ユーザー作成時と,前回のゲストログインor更新から30分以上経過している場合はデータを初期化 data_initialization(user) if new_user_check || Time.now - user.updated_at > 1800 sign_in user redirect_to root_path, notice: 'ゲストユーザーとしてログインしました。' end private def data_initialization(user) user_params = { # ゲストログイン時にデータを初期化するかどうか判断できるようにupdated_atを更新 updated_at: Time.now, name: 'ゲスト', content: 'ゲストユーザーの各種データは30分後に初期化されます。ご了承下さい。', } user.update(user_params) end end
- 投稿日:2019-10-04T10:41:55+09:00
Ruby の fork と spawn を試す
/proc/{PID}/ 配下の情報について Ruby で fork/spawn をした時の違いを確認した時のメモ
(あくまで個人用のメモです)環境
- OS:amzn2-ami-hvm-2.0.20180810-x86_64-gp2 (ami-08847abae18baa040)
$sudo amazon-linux-extras install ruby $ ruby --version ruby 2.6.3p62 (2019-04-16 revision 67580) [x86_64-linux]/proc{PID} 配下の情報について
以下にまとまった情報あり
- /proc/配下には様々な情報があるが、/proc/{PID} という形式でプロセスが生成されるとディレクトリが作成され、配下にプロセスに関わる情報が格納されている
- {PID} = プロセス ID。プロセスを生成すると生成される ID
- プロセスが終了すると、そのプロセスの /proc/ プロセスディレクトリはなくなる
なお、今回確認したかった
cmdline
はい以下のように書いてあるcmdline — プロセスを起動した際に発行されたコマンドが格納されています。
fork してみる
fork(2) システムコールを使ってプロセスの複製を作 ります。親プロセスでは子プロセスのプロセスIDを、子プロセスでは nil を返します。ブロックを指定して呼び出した場合には、生成し た子プロセスでブロックを評価します。
内部的には fork(2)のシステムコールを呼び出しているようであり、確認。
上記のサンプルコードを少し修正。fork.rbchild_pid = fork do puts "child process. pid: #{Process.pid}" sleep(1) end puts "parent process. pid: #{Process.pid}, child pid: #{child_pid}" r = `cat /proc/#{child_pid}/cmdline` puts r Process.waitpid(child_pid)実行すると以下のような感じ
$ruby fork.rb parent process. pid: 2794, child pid: 2795 child process. pid: 2795 rubyfork.rb
/proc/{PID}/cmdline
はrubyfork.rb
となっている。
上記のコードの場合、処理しているのは sleep だが、実行しているのは Ruby のコードという為だと思われる(違ったらご指摘下さい)spawn してみる
関数 Kernel.#spawn と同じです。
引数を外部コマンドとして実行しますが、生成した 子プロセスの終了を待ち合わせません。生成した子プロセスのプロセスIDを返します。
こっちの場合どうなるのか。
spawn.rbchild_pid = spawn({"FOO"=>"BAR", "BAZ"=>nil}, 'sleep 10') puts "parent process. pid: #{Process.pid}, child pid: #{child_pid}" r = `cat /proc/#{child_pid}/cmdline` puts r Process.waitpid(child_pid)$ruby spawn.rb parent process. pid: 2894, child pid: 2895 sleep10
こうなる。
こっちの場合、spawn(env,command)
でよばれて command が cmdline に指定されているという点が違う。
親プロセスID と生成された子プロセスIDが違うのは同じ。
spawn
は Linux のコマンドとして存在する。
一方、 fork はシステムコールという所が違うのだろうか。TODO
以下辺りの情報など関連する情報を集めてもう少しまとめたい。。。
(fork,spawn,thread...)
- 投稿日:2019-10-04T08:58:23+09:00
railsでプロジェクトを丸々コピーする
- 投稿日:2019-10-04T05:02:22+09:00
rubyのselenium-webdriverで同じclass名の要素を取る!
ど素人がrubyのselenium-webdriverを使って七転八倒した記録です。
ただの忘れやすい個人の備忘録です。selenium-webdriver 3.142.2を使ってます。
同じclass名の要素を取ろうとするとき、
driver.find_element(:class, 'クラス名').text
では、最初の要素しか取れない。https://www.rubydoc.info/gems/selenium-webdriver/0.0.28/Selenium/WebDriver/Find
にあるように
driver.find_elements(:class, 'クラス名').text
なら引数が配列で複数取れる。これに数日かかった模様w
xpathやcssとかでも取れるけど、タグは模様替えで簡単に変わってしまうのでできるだけ避けたかった
- 投稿日:2019-10-04T05:02:22+09:00
rubyのselenium-webdriverで同じclass名の要素を取る!class名の中の空白も
ど素人がrubyのselenium-webdriverを使って七転八倒した記録です。
ただの忘れやすい個人の備忘録です。生暖かい目でご覧ください。
アドバイスとかあればよろしくお願いいたします。
selenium-webdriver 3.142.2を使ってます。同じclass名の要素を取ろうとするとき、
driver.find_element(:class, 'クラス名').text
では、最初の要素しか取れない。https://www.rubydoc.info/gems/selenium-webdriver/0.0.28/Selenium/WebDriver/Find
にあるように
driver.find_elements(:class, 'クラス名').text
なら戻り値が配列で取れる。これに数日かかった模様w
xpathやcssとかでも取れるけど、タグは模様替えで簡単に変わってしまうのでできるだけ避けたかった
もう一つ。class名に空白がある場合エラーがでる。
driver.find_element(:class, '空白までのクラス名').find_element(:class, '空白後のクラス名').text↑のようにメソッドチェーンで分けるとうまく行く
- 投稿日:2019-10-04T01:01:01+09:00
RailsチュートリアルエラーExpected response to be a <3XX: redirect>, but was a <200: OK>
エラー発生!
Railsチュートリアルも13章に差し掛かり、早く終わりたいと取り組んでいると
エラーが重なり迷走していると、またエラーが!FAIL["test_should_not_allow_the_not_activated_attribute", UsersControllerTest, 1.5222024869999586] test_should_not_allow_the_not_activated_attribute#UsersControllerTest (1.52s) Expected response to be a <3XX: redirect>, but was a <200: OK> test/controllers/users_controller_test.rb:66:in `block in <class:UsersControllerTest>'users_contrloller_test.rbrequire 'test_helper' class UsersControllerTest < ActionDispatch::IntegrationTest def setup @user = users(:michael) @other_user = users(:archer) #11.3演習テスト @non_activated_user = users(:non_activated) end test "should redirect index when not logged in" do get users_path assert_redirected_to login_url end test "should get new" do get signup_path assert_response :success end test "should redirect edit when not logged in" do get edit_user_path(@user) assert_not flash.empty? assert_redirected_to login_url end test "should redirect update when not logged in" do patch user_path(@user), params: { user: { name: @user.name, email: @user.email } } assert_not flash.empty? assert_redirected_to login_url end test "should not allow the admin attribute to be edited via the web" do log_in_as(@other_user) assert_not @other_user.admin? patch user_path(@other_user), params: { user: { password: @other_user.password, password_confirmation: @other_user.password_confirmation, admin: true } } assert_not @other_user.reload.admin? end test "should redirect destroy when not logged in" do assert_no_difference 'User.count' do delete user_path(@user) end assert_redirected_to login_url end test "should redirect destroy when logged in as a non-admin" do log_in_as(@other_user) assert_no_difference 'User.count' do delete user_path(@user) end assert_redirected_to root_url end #11.3演習テスト https://www.yokoyan.net/entry/2017/09/14/070000 test "should not allow the not activated attribute" do log_in_as(@non_activated_user) assert_not @non_activated_user.activated? get users_path assert_select "a[href=?]", user_path(@non_activated_user), count: 0 get user_path(@non_activated_user) assert_redirected_to root_url #<=ここがエラー end end
assert_redirected_to root_url
が問題のようだ
users_controller.rbを見てみると…
redirect_to root_url and return unless @user.activated?
が抜けてました!users_controller.rbclass UsersController < ApplicationController before_action :logged_in_user, only: [:index, :edit, :update, :destroy] before_action :correct_user, only: [:edit, :update] before_action :admin_user, only: :destroy def index @users = User.where(activated: true).paginate(page: params[:page]) end def show @user = User.find(params[:id]) redirect_to root_url and return unless @user.activated? @microposts = @user.microposts.paginate(page: params[:page]) #13.23 end def new @user = User.new end def create @user = User.new(user_params) if @user.save @user.send_activation_email flash[:info] = "Please check your email to activate your account." redirect_to root_url else render 'new' end end def edit @user = User.find(params[:id]) end def update @user = User.find(params[:id]) if @user.update_attributes(user_params) flash[:success] = "Profile updated" redirect_to @user else render 'edit' end end def destroy User.find(params[:id]).destroy flash[:success] = "User deleted" redirect_to users_url end private def user_params params.require(:user).permit(:name, :email, :password, :password_confirmation) end # 正しいユーザーかどうか確認 def correct_user @user = User.find(params[:id]) redirect_to(root_url) unless current_user?(@user) end # 管理者かどうか確認 def admin_user redirect_to(root_url) unless current_user.admin? end endそうだよね、redirect_to root_urlってテストに書いているのに、コードに無いと困るよねRailsさん。ごめんなさいそしてありがとう( ^∀^)