20190927のRailsに関する記事は14件です。

プログラミングスクールに50万溶かしたリーマンがエッッサイトを作った話


どうも29歳中小企業営業マンです。

 

プログラミングスクールに50万を費やして挫折→復活→挫折→その後5ヶ月でサイトをイチから完成させました。ここまで本当に長くて長くて大変だったよ・・・。サイトを完成させて本当に泣きそうなほど嬉しいよ・・・。辛かった・・・。本当にお兄さん辛かったよぉッッ


実は、ここまで来るのにプログラミング学習で50万使いました・・・。


著者歴
年齢: 29歳
仕事: 営業職(B to C)
学歴: 国公立大学 文系(経済学部)
プログラミング歴: 10ヶ月
開発期間: 5ヶ月(1日2時間くらい)
はじめてPCを使ったのは? :高校生、Windows95のメイプルストーリーがやりたくてはじめて触れました。


♡うそです、中学3年生のyourfilehostで動画鑑賞しますた♡


そこで作りました。

http://shiko-tsuma.club

 


シコい人妻のコンセプト



ひとことで表すと人妻サイトです。
機能は極力シンプルにして、ユーザーが見やすいようなデザインを第一優先にしました。(もちろん管理人も日々
シコい人妻http://shiko-tsuma.club
をシコシコ使ってカイゼンしています。)


すべて、と人気(PV数で並び替え)のメニューがあります。
さらに、投稿時に付与したタグをクリックすると同じタグの付いた動画が一覧表示されます。


 


サイトデザインについて


動画サイトのキングをインスパイアしました。そのサイトはとてもシコりやすいデザインなので別の意味でもいつもお世話になってます。
フォントはGoogle Fontを使用しています。また色合いはごちゃごちゃしないようにメインカラー(黒)、ベースカラー(白)、アクセントカラー(ピンク)以外の色は使用していません。
あともちろんスマホレイアウトを最優先しました。そしてタブレットのデザインは省きました。



開発までの経緯


実は、一回プログラミングに挫折しております。
動画で学べるプログラミング学習サイトをすべて学んだらHサイトを作れるんじゃね?って思った時期がありました。
ちょうどこの記事も参考にしていましたし→https://anond.hatelabo.jp/20101203150748
動画サイトでHTML, CSS, PHP, JavaScriptのメニューを3ヶ月位でこなしました。もちろん有料会員。(3ヶ月で3000円を費やす)
しかし、PHPのどうしても解決できないエラーにハマりました。
「クソッ、なんで動かねぇーんだ、チクショウ」そうやって机を叩いたことがたくさんあります。
「もうやめよう、無理だ、いや、まだ続けよう、いや、やめよう、無理だ、いや、まだ続けよう」そうやって何度も悩み続けました。



どうしてもプログラミングでサイトを作りたい!
けど、どうしようもない!
どうすればいいのか悩んだ挙げ句、Google先生に頼みました。



プログラミング教材、プログラミングオンラインスクールについて


プログラミング Web開発 などで調べると魅力的なページに辿り着きました。プログラミングを教えていて、サロンなどもやっている○○○さんという方のBlogでした。
そのBlogでは



プログラミングで自由な生き方ができる!
プログラミングって魔法なんだ!
こんな夢のようなキャッチフレーズに心打たれました。


本気になった私は教材の購入ボタンを押しました。



某○○○さんの教材



ものすごく期待して届いた教材を進めたところ・・・



「なんだこれ、本で読んだのと全く同じやん・・・」
「こんな基礎中の基礎なんて」



基礎中の基礎しか学べませんでした。
HTML、Ruby、Railsの基礎中の基礎なのでプログラミングを初めてする人にはいいかもしれないです。けど自分が実現したいWeb開発には直接は役に立ちません。もはや悲しみに近い怒りですがこの人は自分でWebアプリなどを本番環境やサーバを立てて自分で運営したことがあるのだろうか?と怒りを禁じえませんでした。
(後にエンジニアのメンターさんは20年前からまるで成長していない(安西先生風)Webアプリケーションを作らせている、と言っていました・・・。)
(ここまでで10万円を費やす)



「ん~、基礎ばっかりやってもまだ掲示板しか作れないし、作りたい機能や動かないコードの質問をしても調べろ、って言われるだけだったしな・・・」
「本当にプロのエンジニアに教わったら早いかもしれない」
そう思いました。



そして、「プログラミング 実践 開発」 「プログラミング エンジニア 講師」で調べると現役のエンジニアがメンターとして週に何回か見てくれるプログラミングスクールにたどり着きました。


 


オンラインスクールで学ぶ



そこで行われるカリキュラムというのは、オンラインスクール自身が作成した教材を進めながら、エンジニアのメンタリングを週に何回か受けるというもの。
他のスクールも検討しながら、1ヶ月近く悩み続けました。しかしプログラミングは投資だ、と思い
「えい、40万円入金ッッ」(ここまでで50万円・・・勇気がいりました)を実行しました。



最初は休日の朝にメンターとのコンタクトがあったのですが、起きられないことが多々ありました(連日深夜まで残業だったからとても眠かった)。出された課題も1日2時間もかかるので仕事で神経を減らして疲れた体には辛かったです。
「正直仕事が忙しいし、プログラミング勉強してる暇ないから、また挫折か・・・」と思いました。めちゃくちゃダメ人間なのです。



「また何も成し遂げられないのか・・・」



実は私、大学受験で第一志望に落ちて、理系に行くはずだったのに文系で絶望しました。だから理系のプログラマーに憧れます!
やりたかった仕事の就職も失敗しました。
高校も不登校だったし、昔うつ病も発症しています。



「もともとダメ人間でクズな自分が継続などできないのか・・・」



しかし、縁があって担当してもらったメンターさんの話が自分にとって刺激的で面白かったのです。


 


「Webサイトを大企業に売却して3000万稼いだ話」
「ベンチャー企業に誘われて手取り100万稼いだ話」
「どこどこのサイトのデータベースの裏話」
「自分の開発したサイトアプリケーションの話」


「すげぇ」そう思いました。
また、自分が仕事で使用しているツールがどうやって作られているのかも説明してくれてすごいリアルで面白かった。こちらの質問にも具体的に答えてくれて「すげぇ」って感じでした。
あと、オンラインスクールの推奨フレームワークがRubyだったのですが、Rubyが直感的で書いていて気持ちが良かったのです。



今まで動画サイトや本でフワッと学んだ知識がつながるのを実感しました。
気づいたら仕事から帰ってスーツのままプログラミングを学習していました。すごく楽しくなってきたのです。



しかし、シコい人妻http://shiko-tsuma.club を公開した今だからわかるのですが、プログラミングスクールの教材はRailsガイドのマネごとでした・・・。



この気持わかる人いますか?



ぶっちゃけ今だったら最初から


RubyとRailsの学習ガイド2019年版
https://magazine.rubyist.net/articles/0059/0059-Ruby-Rails-Beginners-Guide.html



の通りやったほうが良かった。



また、教材以外にもこれらを学びました。
https://www.sbcr.jp/product/4797386295/


https://gihyo.jp/book/2017/978-4-7741-9397-7


http://gihyo.jp/magazine/wdpress/plus/978-4-7741-4204-3


https://saruwakakun.com/html-css/basic



あとgitも公式チュートリアルで学びました
https://try.github.io/



いやー、オンラインスクールはgitの実践的なエラー解決は教えてくれなかったw
基本git -f はしてはいけないとか知らなかった。
おかげでgitミスって書いたコードが消し飛んだことが多々あります。


結局のところ、プログラミングの基礎的な内容については高額な教材(1万円以上)を買う必要はないかと思います。3000円の本を2,3周すれば十分です。高額な教材と3000円の本の内容は一緒です。(経験者は語る)1人では続かなくて誰かにサポートしてほしい場合は買ってもいいんじゃないでしょうか。
つまり、オンラインのプログラミング学習は教材にあまり価値はありません。そのサポートに数万円の価値があります。(人件費だから高いのは当たり前)



プログラミング学習が流行っていますが、プログラミングは手段です。何を目的にするかが重要かなと思いますね。私の場合はWeb開発でした。そして、Web開発において、大事なのは継続できるモチベーションづくりです。もし何度も挫折するのならば、良質な本で学びながらプログラミングを仕事にしているメンターに週何回か見てもらえばいいのではないでしょうか。



ぶっちゃけ、自分でサービスを開発していない人やレベルの低いエンジニアにわざわざ教わる価値はない、ですね。



シコい人妻ができるまで


プログラミング業務未経験の初心者がシコい人妻http://shiko-tsuma.club
みたいなサイトを作る場合、勉強したリストは以下の通り。
実際、私はこれらを10ヶ月くらいで開発しながらこなしました。
(途中別のWebアプリを作ろうとしたが続かず失敗、その後シコ妻に変更して5ヶ月後で完成して今に至る)



HTML / CSS


「HTML / CSSなんて常識だろ、パパっと学んどけばいいんだ」そう思ってあとで苦労しました。
これらの知識が中途半端だったので、いざゼロから書けってなったときに困りました。
たとえばRailsでリンクを生成するメソッドでタグの位置を微妙に間違えたりして表示されないことなどがありました。



Linuxのターミナル


基礎的なコマンドを動画で学びました。
https://dotinstall.com/lessons/basic_unix_v2



HTTPのしくみ


本でサラッと学びました。この本です。
https://www.amazon.co.jp/Webを支える技術-HTTP、URI、HTML、そしてREST-WEB-PRESS-plus/dp/4774142042/ref=sr_1_1?__mk_ja_JP=カタカナ&keywords=http&qid=1569577311&s=books&sr=1-1


とりあえずCRUDということを学びました(小並感)


Ruby


each, ifなどの文法を学びました。この本です。
https://www.amazon.co.jp/プロを目指す人のためのRuby入門-言語仕様からテスト駆動開発・デバッグ技法まで-Software-Design-plusシリーズ/dp/4774193976/ref=sr_1_1?__mk_ja_JP=カタカナ&keywords=ruby&qid=1569577335&s=books&sr=1-1



本当はオブジェクト指向とかできればいいのでけれどまだそのレベルではないです。Rubyは$とか書かなくていいので書いていて気持ちがいいです。でもプログラミング強い人からするとRubyは型が曖昧で気持ち悪いらしい・・・。本当でしょうか?



Railsについて


最初はフレームワークの何がいいのかわかりませんでした。ですが、Railsで開発したり、Railsの記事を読んだりするうちに、そもそもフレームワークとはWeb作りなどで使う定番のコードをあらかじめ用意しておいたもので、フレームワークをそのルール通りに使うと開発の時間が削減できる、ということを知りました。
今、オンラインスクールとかネット上で教えている内容の多くはRailsです。全くのプログラミング素人にRailsを教えているわけです。
しかし、初心者がいきなりフレームワークを使用してコピペで書いたツギハギ開発をすると「わけのわからないエラー」が量産します。
かくいう私がまさにそうでした。



参考
今すぐ辞めて欲しい、「Ruby on Rails勉強してます」「CakePHP勉強してます」
https://blog.sumyapp.com/2013/07/no-recommend-rails/



Railsは基礎的な文法を覚えるだけで簡単な機能を作れますが、一歩ルールから外れたことをすると途端にどうしていいかわからなくなり混乱します。
これからはサーバ、データベース、コンピュータサイエンスの基礎を学ぼうと思いました。


 


データベース


基本的なSQL文法などは動画サイトなどで学びました。あとは適宜ググりながらやりました。
また、1対多や多対多の使用例を開発して身にしみてわかりました。データベースは正規化、N+1問題、高速化などなかなか奥が深い分野です。ちなみにオンラインスクールはSQL文しか教えてくれませんでした。


 


サイトのコンセプトを考える


「ここまで来たらいよいよサイトづくりだ!」そう思い、興奮しながらサイト案を練りました。



ER図、サイトマップを作成する


「いーあーる図!?なんじゃそれは!」
ググるとどうやらデータベースの概要図とのことでした。そもそもデータベースに格納するデータはどのようなものか?そのカラムにどんな値を持たせるのか?関連は?ということを図にするのです。
参考 https://qiita.com/inexp_eng4432/items/817db9ba18829e0f6d57
(いつもQiitaさんお世話になってヤース)



あと、サイトURLからどのような構造をしているか、というサイトマップも作成しました。


trelloでタスクを並べる


「なにをやれないいのか、イマイチわかりづらいな・・・どうしよう」
https://trello.com
ここでタスクを書き並べました。付箋みたいで便利。


rails new rails migration


「rails new shikoi_hitozuma てぇぇーい!」
ER図で作成したデータベース構造を見ながら実際のデータベースにテーブルを構築していきました。


modelを書いていく


「まずはModelからだ、と習ったぜぃ」
リソースを人気順にしたり、新しい順にしたり、ということを書いていきました。


routingを書く


「index show だったな、これらをそれぞれのModelに関して設計していくぜぃ」
どういうURL階層にするか、というサイトマップを参考にして書きました。


controllerを書く


「次はControllerだな、Modelから渡されたものを加工するぜぃ」
index showなどのアクションごとにインスタンス変数を書いていきます。


viewを書く


「よし、今度は表示させていくぜぃ HTMLてててーいッッ」
実際に見る画面を構築していきます。


activeadminで投稿する


rails のgem にactiveadminという、管理画面を一瞬で作るものがあります。それを導入して投稿を管理しました。
「だけど、公式情報が少なすぎてわからねぇーーーーーーひぃいいいいい」
activeadminはものすごい苦労しました・・・。


サイトデザインをする


「CSSぅー?こんなんぱぱっと終わらすぜぇ」
はじめはCSSをバカにしていましたが、本気でやりました。パッと見のデザインで印象は大きく変わりますから。1日2時間で1ヶ月位かけました。
ちなみにエンジニアの人は「CSSなんて鼻くそほじりながら書けるでしょ」って思っているようですが、違いますよ。確かに思考はあまりいらないかもしれないけれど、最優先事項の一つだと思います。



本番サーバーを構築する


「くそーーーーーーー!クソクソクソ!!!動かない!どうしてうごかねーんだ、なんでだ馬鹿野郎!!」
ってめちゃくちゃ思いながら行った、本番サーバー構築。
今回は開発環境をバーチャル環境のUbuntuで構築しました。オンラインスクールでは某エディタを使用するのですが、メンターから「本当はこんなクソエディタの開発環境じゃなくて、ローカル環境でDockerとかを用いて開発できればいいんですけど」と言っていたのでローカル環境で開発しました。※クソエディタはCloud9です。


まぁ、開発環境の構築は問題ないとして、本番環境が色々難しかったです。VPSとかAWSとかそこらへんです。
※ちなみに今はDockerを勉強しています。環境構築がもう少し楽になるといいんですが・・・仮想環境とDockerの違いがわからない、なんであんなにDockerなんて流行っているの??疑問だ。


あと、そもそも開発環境で作ったものを本番環境にあげるなんてやったことなかったのですよ。だから開発環境と本番環境でgemを分けたりということを初めて学びました。
ここ、めっちゃ重要だと思うのです。Herokuで済ましている場合ではないです。
ちなみにオンラインスクールなどの教材はそのことについて触れてすらいないのです。本当の本番環境構築は初心者には難しすぎる、と認識しているのでしょうか?


 


使用技術について


Ruby
Rails


CSS



オンラインスクールではbootstrapを推奨していましたが、ちゃんとしたデザインで開発するならばbootstrapは使ってはいけないとのこと。だからFlexboxでイチからデザインしました。


 


gem


activeadmin
オシャレな管理画面。
これで記事を投稿しています。
投稿しやすいようにUIを変えるのに非常に苦労しました。情報が少ないのですw
苦労した点を書いていきます。



サムネイル画像をradioボタンで表示するには
動画を投稿する際に画像を見ながら選びたいですよね。
ラジオボックスのボタンを画像にする



activeadminのformのところをこんな風にします。
f.input :movie_thumbnail, as:
:radio,collection:Model.find(params[:id]).movie_thumbnail.select(:movie_thumbnail_url, :id).map { |c| ["<img src='#{c.movie_thumbnail_url}'>".html_safe, c.id] }


collectionのところでまずサムネイルを一覧表示させます。
そしてhtml_safeでHTMLタグとして認識すると画像が表示されます。


[Rails]ERBのエスケープを自在に扱おうぜ
https://qiita.com/satoken0417/items/7bcdb59eae82776375f9



kaminari


オシャレなページング(まだ入れてなかった)


 


pry



irbのオシャレなやつ
デバッグするときにbinding.pryするとirbよりオサレです。


 


サーバ



Nginx
unicorn
「nginx unicorn 早い、すごいお」
オンラインスクールの教材では一切教えてくれなかったですが、ここも超大事です。Webアプリケーションエンジニアのプロは高速なサーバーを構築するのが当たり前だそうですね。
これらは設定をググって書けばいいだけでしたが最初はハマって大変でした。
これらの記事でなんとか解決しました。
nginx + unicorn + Railsの設定方法
https://qiita.com/akito1986/items/56198edcafc222b320a8


STI


シコい人妻http://shiko-tsuma.club/には tagテーブルがあるのですが、そこから派生する妻ラベル(人妻の分類)や体型などのテーブルは内容が重複するのでSTIという設計を用いました。


参考記事
[Rails] STI(単一テーブル継承)とメタプログラミングでDRY
https://qiita.com/kidach1/items/789c2e7aebbcfbd2583e


これからは以下の機能を作っていきます。昼間はブラック企業で働いている関係上、作業は深夜になりそうですが、えっちい人妻のためにがんばります。
みんな、はてブコメントでコメントどしどしくれよな!


追加したい機能


 


セッションを利用した履歴表示


多分セッションを期間で区切ってやればできると思います。


ユーザーが投稿できるForm


ユーザーがこれを共有したいと思う動画のURLを貼り付ければ投稿できる、というやつ。activeadminでできますね。


コメント機能


commentというテーブルを作って、記事にリレーションさせればいいと思います。


ユーザーのお気に入り登録


これもfavoriteというテーブルを作ってuserにリレーションさせます。


日毎、週毎、月ごとのランキング


今は直接記事にPVを加算していますが、別テーブルから期間ごとのランキングや上昇度を測ってYoutubeの急上昇みたいな機能もほしいですね。



参考にしたところ


 


本番環境構築について


そもそもデプロイの経験が初めてだったのでdevelopment / production の棲み分けがわかってませんでした。
そのときに参考にした記事がこちら
(初心者向け)vpsを契約して、capistrano3でRailsアプリをデプロイするまで [その1 サーバー設定編]


https://qiita.com/ryo2132/items/f62690f0b16ec11270fe

Rails


Modelを簡素化するscope
Railsでよく利用する、Scopeの使い方。
https://qiita.com/ngron/items/14a39ce62c9d30bf3ac3


本番環境でbundlerがエラー起こしたときに参照しました。
BUNDLED WITH で Gemfile.lock が更新されてしまう件
https://qiita.com/suu_g/items/2b1630b8015d51c5292e


 


CSS


Flexboxについて
日本語対応!CSS Flexboxのチートシートを作ったので配布します
https://www.webcreatorbox.com/tech/css-flexbox-cheat-sheet


 


まとめ



初心者がサイトを開発したい場合は


・フレームワーク
・サーバーサイド言語
を軽く学んだ上で


・作りたいサイトのコンセプト
・作りたいサイトの機能
を紙に起こして


・サイトマップ
・データベースのER図


を元にして開発するのがいいです。
その際に「こうしたい」という機能がたくさんあると思いますが、それを大胆に1つか2つまで削ぎ落として、シンプルなものを完成させるのがいいです。できることよりできないことのほうが多いですから。


また、
・サーバーサイド言語
・フレームワークとデータベース
・デザイン
がWebアプリでは大事かな、と思います。


この記事も参考にするといいです。
(兎に角)早くプロトタイプを作る技術(初心者向け)
https://qiita.com/teradonburi/items/1d629a751ed42e923d7d


プログラミング初心者ゆえ、みなさんのアドバイス待ってます。


それではみなさん、よきシコい人妻http://shiko-tsuma.clubライフを。


PS
あとよくプログラミングスクールで謳われている「3ヶ月でフリーランスになる」ことは不可能だと思います。
開発してみて身にしみましたが、一口にプログラミングと言ってもやることが多すぎるので3ヶ月程度では仕事にするのはほぼ不可能だと思います。


現役エンジニアの人はどう思いますか?


また、メンターさんはプログラミング歴20年だし、知り合いのRubyプログラマは仕事ができるまで死ぬほど働いて3,4年かかったと言っていました。そんな人達がゴロゴロいるなかで勝てると思いますか?


知り合いの東大卒がこう言っていました。「俺は小学生から12年間、週に4回以上塾通い&一貫中高&自学自習(1日5時間以上)でギリギリ東大入れた。だから1年やそこらの努力で東大とか言っている有名人がムカつく。」と。
「じゃあ、100万払えば偏差値30でも3ヶ月で東大合格できる塾ってどう思う?」
「100%うそ、ありえない。受かる人は元々素地がある人。そもそも予備校の東大合格者の数だって、元々模試でA判定の人を無料で通わせたのをカウントしただけ。」



100万払えば3ヶ月で東大に合格させる塾なんてないのと同じように、50万払って3ヶ月でスーパープログラマーになれると思いますか?



みなさん、いいシコ妻ライフを。http://shiko-tsuma.club

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ActionCableにおいてのcurrent_userについて読み解く|Rails

action cableのcurrent_userについて読み解く

本記事投稿の経緯

Railsで簡単なチャットアプリを作成中、ActionCable内でのcurrent_userの取り扱いにつまづいたのでメモ。

環境

Rails 5.2.3(最新じゃないンゴオオオォ)
Ruby 2.4.0(最新じゃないンゴオオオォ)

connection.rbで定義されるcurrent_user

connection.rb
module ApplicationCable
  class Connection < ActionCable::Connection::Base
    identified_by :current_user

    def connect
      self.current_user = find_verified_user
    end

    protected
    def find_verified_user
    remember_token = User.encrypt(cookies[:user_remember_token][:value]) if cookies[:user_remember_token]
      if current_user = User.find_by(remember_token: remember_token)
        current_user
      else
        reject_unauthorized_connection
      end
    end
  end
end

上記は公式ドキュメントのサンプルコードであるが、ActionCableはWebSocketで通信する際、まずここで認証を行える。その際、current_userを定義しているのだが、こいつの仕組みがイマイチ把握できなかったのでソースコードを読み解いていくことにした。

identified_by

まずはidentified_byを見ていく。(コードは一部です。)

action_cable/connection/identification.rb
included do
  class_attribute :identifiers, default: Set.new
end

module ClassMethods
  # Mark a key as being a connection identifier index that can then be used to find the specific connection again later.
  # Common identifiers are current_user and current_account, but could be anything, really.
  #
  # Note that anything marked as an identifier will automatically create a delegate by the same name on any
  # channel instances created off the connection.
  def identified_by(*identifiers)
    Array(identifiers).each { |identifier| attr_accessor identifier }
    self.identifiers += identifiers
  end
end

コメントに大体が書いてあるのだが、identifier_byは後で特定のconnectionを見つけられるようにキーを作っている。今回であればcurrent_userをキーとしてconnectionを識別できるようにしてくれているのだ。
更にはそれを子であるchannelに自動で同じ名前でdelegateするという。

Connections form the foundation of the client-server relationship. For every WebSocket accepted by the server, a connection object is instantiated. This object becomes the parent of all the channel subscriptions that are created from there on.

そういえばrails guideにもconnectionはそこから作成されるchannnelの全ての親となると書いてあった。
(これややこしいが継承のことではないっぽい?。、delegateしてるし...それはまた今度、気が向けば記事にします。)

つまり、WebSocketの接続の識別としてcurrent_userは使われており、更には子であるchannelでも利用可能であるはず。

てわけで使ってみる。

実際にcurrent_userを使ってみる

流れ

⓪チャットルームモデルとユーザーモデルは多対多の関係。(ここは省略。)
①connection接続時にユーザーがログイン済みユーザーか認証し、current_userに接続したユーザーを入れる
②room_channelにサブスクライブする時、先のcurrent_userにそのチャンネルに接続する権限があるか認証する。

connection.rbは上記のサンプルコードと同じにします。
room_channel.rbのサブスクライブ部分は下記のとおり。

room_channel.rb
class RoomChannel < ApplicationCable::Channel

  def subscribed
    if !params.empty? && current_user.is_member?(params['room_id'])
      stream_from "room_channel_#{params['room_id']}"
    else
      reject
    end
  end

end

クライアントからチャットルームのidを送ってもらい、そのルームにログイン中のユーザーが属しているか確認している。
is_member?メソッドは下記のような感じで。

user.rb
  def is_member?(room_id)
    members = Room.find(room_id).users
    members.any?{|member| member.id == self.id }
  end

こんな感じでcurrent_userを使って各チャンネルでも認証をできる。

is_member?メソッドに指摘が入ったので修正(20190927)

下記はexists?を使ったver。
ここ、色々書き方あるが、どれが一番リソースに優しいか考えてたら、記事にできそうだったので今度書きます。(SQL力が足りない...)

user.rb
  def is_member?(room_id)
    Room.find(room_id).users.exists?(self.id)
  end

まとめ

connection時、ユーザーがログイン済みか認証し、ログインしていればそれをcurrent_userにいれ、子のチャンネルで利用可能にする。
current_userを使えばチャンネル内でも認証可能。

あとがき

実は今回、current_userの取り扱いでつまづいたのはrspecでテスト中のことでして、
current_userはチャンネル内で使えるって聞いたんだけど!!」
とか叫いたりして、
「本当に使えんのか?.....調べてやる!」
と思い執筆しました。

結局、testコードの書き方が間違っていただけでしたンゴ!!めでたしめでたし!!

まあためにはなったかな。。。

参考記事

【ActionCable】チャンネル接続/購読時にユーザ認証を行う
これはMUST!ActiveSupport の Class#class_attribute を使おう!
Rubyのdelegateについて整理する
Rails Guide

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Cloud9でRailsのAPIの開発環境を構築

はじめに

Cloud9でRailsのAPIサーバの開発環境を構築する手順の忘備録になります.

次のような方におすすめです.

  • Cloud9にRailsのAPIサーバを構築したい
  • React+RailsやVue+Railsの開発環境が欲しい
  • Herokuなどの他のサービスを通さずにアプリを公開したい

なぜ書いたのか

RailsのみならCloud9のプレビュー機能が使えます.(参考サイト
ただ,プレビューはあくまでもプレビューであり,ネットに公開されているわけではありません.
そしてAPIサーバは外部からアクセスできる必要があり,プレビュー機能では開発環境の役目を果たすことができません.

そこで,Cloud9上でネット公開されるRailsのAPIサーバの構築を試みました.
他に同様の記事が無く苦戦したので忘備録として残しておきます.

基本的な流れだけのせて,他の記事をリンクを載せて端折らせていただきます.

Cloud9の環境構築

AWSのアカウントを作成します.
そして,安全に操作できるようにユーザを作成し,Cloud9の環境を構築します.
初めてのAWS Cloud9導入

Rails APIサーバのセットアップ

rvmなりrbenvなりでRubyのバージョンを指定し,Railsをインストールします.

# rvmの場合.(rvmはデフォルトで入ってる)
rvm install "rubyのバージョン"
rvm use "rubyのバージョン"

gem install rails -v "railsのバージョン"

RailsアプリをAPIモードで作成します.

rails new "アプリ名" --api

あとは,rails db:migrateやら何やらを実行してください.

CORSの設定

他のオリジンからアクセスを許可するために,コメントアウトを外してあげます.
そして,originsに,フロントのオリジンを指定します.

config/initializers/cors.rb
# 'rails new'の直後はコメントアウトされてる
Rails.application.config.middleware.insert_before 0, Rack::Cors do
  allow do
    origins 'hoge.fuga.example.com' #ここをフロントのオリジンに変える
    resource '*',
      headers: :any,
      methods: [:get, :post, :put, :patch, :delete, :options, :head]
  end
end

ネットワークの指定

Cloud9が動いているEC2インスタンスへは初期設定ではインターネットからアクセス出来ません.
そのため,「AWS 実行中のアプリケーションをインターネット経由で共有する」に従って,EC2にアクセス出来るようにします.

アカウントを作成したばかりなら,必須なのはセキュリティグループの設定ぐらいだと思います.
書いてありますが,ポート番号は8080~8082のどれかです.

Railsの起動

railsを起動します.
バインドとさきほどのポート番号を指定します.

rails s -p "ポート番号" -b 0.0.0.0

ブラウザで表示

「ネットワークの指定」の手順で実行した

curl http://169.254.169.254/latest/meta-data/public-ipv4

で得られるIPアドレスにポート番号をくっつけてブラウザで表示します.(例: 256.1.2.3:8081)

すると,いつもの画面が出てくるはずです.

image.png

これはブラウザで表示していますが,APIモードで動いているはずです.

終わりに

かなり省略しましたが,大まかな流れは合ってると思います.

ネットワークの設定までは順調だったのですが,バインドのところでつまずきました.
Cloud9だとポートやバインドは指定せずとも動くので甘えてました.

以上の手順で,最大3つのアプリまで一つのインスタンス上でネット公開できます.
そのため,RailsとReactやVueなどを同時に公開することも可能です.

Rails+Reactで動くことを確認しました.
ぜひ,試してみてください.

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Railsチュートリアル 第5章 - レイアウトを作成する…レイアウトのリンク

レイアウトのリンク概論

Railsにおいても、リンクを直接記述することは可能です。

Aboutへのリンクを直接記述する
<a href="/static_pages/about">About</a>

しかし、リンクを直接記述するというのは、いかにも力押しで、Railsらしいエレガントなコードではないですね。変数・定数の定義以外では、できる限りリテラルの埋め込みは避けたいものです。

さらに、以下のような事情もあります。

  • aboutページのURLは、/static_pages/aboutより/aboutのほうが好ましい
  • Railsでは、aboutページのようなページへのリンクには、名前付きルートを使うのが慣例である

となると、Aboutページへのリンクは以下のように書くのがRails的です。

Aboutへのリンクの、Railsらしい記法
<%= link_to "About", about_path %>

前述「Railsらしい記法」には、以下のような利点があります。

  • コードの意味がわかりやすくなる
  • about_pathの定義を書き換えることで、about_pathが使われているすべてのURLを一度に変更することができるようになる

Railsチュートリアルでは、今後使う予定のURLとルーティング(route)とのマッピングを、以下のように定義しています。

ページ名 URL 名前付きルート
Home / root_path
About /about about_path
Help /help help_path
Contact /contact contact_path
Sign Up /signup signup_path
Log In /login login_path

Contactページ

演習 - サンプルアプリケーションにContact (問い合わせ先) ページを作成してみるで既に作成していました。当該項目をご参照ください。

RailsのルートURL

名前付きルートをサンプルアプリケーションの静的ページで使うために、ルーティング用のファイル(config/routes.rb)を編集していきます。

現時点で、既にHomeページのルーティングは設定されています。rootルーティングが存在しないと、Railsアプリケーションそのものが動作しないからです。

config/routes.rb(抜粋)
root 'static_pages#home'

名前付きルートを含むルートURLを設定することには、以下のような利点があります。

  • ブラウザからアクセスしやすくなる
  • 名前付きルートを使ってURLを参照できるようになる
    • rootであれば、root_pathroot_urlといったメソッドを使えるようになる

rails consoleからapp.root_pathapp.root_urlメソッドを使うこともできます。現時点におけるapp.root_pathおよびapp.root_urlの結果は以下の通りでした。

>> app.root_path
=> "/"
>> app.root_url
=> "http://www.example.com/"

ルーティング用のファイルのgetルールは、第1引数にURL、第2引数にオプションハッシュを取ります。オプションハッシュの:toキーに値を与えることによって、名前付きルートを定義することができます。

早速config/routes.rbを編集し、名前付きルートを定義しましょう。例えば、Helpページに対する記述は、以下のように変換します。

config/routes.rb(抜粋)
- get 'static_pages/help'
+ get '/help', to: 'static_pages#help'

Helpページに対して名前付きルートを定義したところで、rails consoleから、help_pathメソッドやhelp_urlメソッドを使ってみましょう。

>> app.help_path
=> "/help"
>> app.help_url 
=> "http://www.example.com/help"

help_pathメソッドやhelp_urlメソッドが使えるようになっていますね。

逆に、名前付きルートを定義していないページに対して、_path_urlメソッドを呼び出すことはできません。

>> app.about_path
...略
NoMethodError (undefined method `about_path' ...略)

現時点でAboutページに対しては名前付きルートを定義していないので、このようなエラーになるのですね。

最終的に、config/routes.rbは以下のように書き換えます。

config/routes.rb
  Rails.application.routes.draw do
    root 'static_pages#home'
-   get  'static_pages/home'
-   get  'static_pages/help'
-   get  'static_pages/about'
-   get  'static_pages/contact'
+   get  '/help',    to: 'static_pages#help'
+   get  '/about',   to: 'static_pages#about'
+   get  '/contact', to: 'static_pages#contact'
  end

rails consoleから、再びabout_pathメソッドを呼び出してみましょう。

>> app.about_path
=> "/about"

今度は無事呼び出すことができました。

テストの修正

現状でrails testを実施すると、テストは失敗します。

# rails test
Running via Spring preloader in process 974
...略

ERROR["test_should_get_help", StaticPagesControllerTest, 0.26505280000856146]
 test_should_get_help#StaticPagesControllerTest (0.27s)
NameError:         NameError: undefined local variable or method `static_pages_help_url' ...略

ERROR["test_should_get_home", StaticPagesControllerTest, 0.33508309998433106]
 test_should_get_home#StaticPagesControllerTest (0.34s)
NameError:         NameError: undefined local variable or method `static_pages_home_url' ...略

ERROR["test_should_get_about", StaticPagesControllerTest, 0.39137299999129027]
 test_should_get_about#StaticPagesControllerTest (0.39s)
NameError:         NameError: undefined local variable or method `static_pages_about_url' ...略

ERROR["test_should_get_contact", StaticPagesControllerTest, 0.4491715999902226]
 test_should_get_contact#StaticPagesControllerTest (0.45s)
NameError:         NameError: undefined local variable or method `static_pages_contact_url' ...略
  4/4: [=============================================================================================================================================================] 100% Time: 00:00:00, Time: 00:00:00

Finished in 0.50959s
4 tests, 0 assertions, 0 failures, 4 errors, 0 skips

static_pages_about_url等の名前が参照できない」というエラーですね。これらの名前は、例えば「about_path」等に置き換えたので、テストも相応に書き直す必要があります。

test/controllers/static_pages_controller_test.rb
  require 'test_helper'

  class StaticPagesControllerTest < ActionDispatch::IntegrationTest

    def setup
      @base_title = "Ruby on Rails Tutorial Sample App"
    end

    test "should get root" do
      get root_path
      assert_response :success
    end

    test "should get home" do
-     get static_pages_home_url
+     get root_path
      assert_response :success
      assert_select "title", "Home | #{@base_title}"
    end

    test "should get help" do
-     get static_pages_help_url
+     get help_path
      assert_response :success
      assert_select "title", "Help | #{@base_title}"
    end

    test "should get about" do
-     get static_pages_about_url
+     get about_path
      assert_response :success
      assert_select "title", "About | #{@base_title}"
    end

    test "should get contact" do
-     get static_pages_contact_url
+     get contact_path
      assert_response :success
      assert_select "title", "Contact | #{@base_title}"
    end

  end

以上の修正が完了すれば、テストは再び通ります。

# rails test
...略

  5/5: [=============================================================================================================================================================] 100% Time: 00:00:01, Time: 00:00:01

Finished in 1.31410s
5 tests, 9 assertions, 0 failures, 0 errors, 0 skips

演習 - 名前付きルートを変更してみる

1. 実は名前付きルートは、as:オプションを使って変更することができます。有名なFar Sideの漫画に倣って、Helpページの名前付きルートをhelfに変更してみてください (リスト 5.29)。

config/routes.rb
  Rails.application.routes.draw do
    root 'static_pages#home'
-   get '/help', to: 'static_pages#help'
+   get '/help', to: 'static_pages#help', as: 'helf'
    get '/about', to: 'static_pages#about'
    get '/contact', to: 'static_pages#contact'
  end

2. 先ほどの変更により、テストがredになっていることを確認してください。リスト 5.28を参考にルーティングを更新して、テストをgreenにして見てください。

1.が終了した時点で、一旦テストを実行してみます。

# rails test
...略

ERROR["test_should_get_help", StaticPagesControllerTest, 1.884794099983992]
 test_should_get_help#StaticPagesControllerTest (1.89s)
NameError:         NameError: undefined local variable or method `help_path' for ...略

  5/5: [=============================================================================================================================================================] 100% Time: 00:00:02, Time: 00:00:02

Finished in 2.07678s
5 tests, 7 assertions, 0 failures, 1 errors, 0 skips

確かにtest_should_get_helpのところでテストが失敗していますね。

rails consoleで、app.help_pathメソッドとapp.helf_pathメソッドの存在を確かめてみましょう。

>> app.help_path
NoMethodError (undefined method `help_path' for #<ActionDispatch::Integration::Session:0x000055f201d2df40>)\

>> app.helf_path
=> "/help"

app.help_pathメソッドが存在しない一方、app.helf_pathメソッドが存在します。

この場合、test_should_get_helpのテストを通すためには、test/controllers/static_pages_controller_test.rbに以下の変更を行う必要があります。

test/controllers/static_pages_controller_test.rb(抜粋)
    test "should get help" do
-     get help_path
+     get helf_path
      assert_response :success
      assert_select "title", "Help | #{@base_title}"
    end

以上の変更を保存した上で改めてrails testを実行します。

# rails test
...略

  5/5: [=============================================================================================================================================================] 100% Time: 00:00:02, Time: 00:00:02

Finished in 2.15824s
5 tests, 9 assertions, 0 failures, 0 errors, 0 skips

今度はテストが通りました。

3. エディタのUndo機能を使って、今回の演習で行った変更を元に戻して見てください。

全体としては、以下2つの内容の変更となります。

config/routes.rb
  Rails.application.routes.draw do
    root 'static_pages#home'
-   get '/help', to: 'static_pages#help', as: 'helf'
+   get '/help', to: 'static_pages#help'
    get '/about', to: 'static_pages#about'
    get '/contact', to: 'static_pages#contact'
  end
test/controllers/static_pages_controller_test.rb(抜粋)
    test "should get help" do
-     get helf_path
+     get help_path
      assert_response :success
      assert_select "title", "Help | #{@base_title}"
    end

以上の変更を保存した上で改めてrails testを実行します。

# rails test
...略

  5/5: [=============================================================================================================================================================] 100% Time: 00:00:01, Time: 00:00:01

Finished in 1.86960s
5 tests, 9 assertions, 0 failures, 0 errors, 0 skips

無事テストが通りました。これで心置きなく次の学習にかかれます。

余談

get '/help', to: 'static_pages#help', as: 'helf'

以上のように書くべきところを、誤って以下のように書いてしまいました。

get '/help', to: 'static_pages#help', as: helf

これでどうなったかといいますと…

# rails test
/var/www/sample_app/config/routes.rb:3:in `block in <top (required)>': undefined local variable or method `helf' for #<ActionDispatch::Routing::Mapper:0x000055bb8e302880> (NameError)
...略

# rails console
/var/www/sample_app/config/routes.rb:3:in `block in <top (required)>': undefined local variable or method `helf' for #<ActionDispatch::Routing::Mapper:0x0000563606493238> (NameError)
...略

rails testrails consoleもできなくなってしまいました。「未定義の変数名を使ってしまった」というエラーですね。

名前付きルート

名前付きルートを定義したことにより、レイアウト中で名前付きルートを使えるようになりました。具体的には、「link_toメソッドの第2引数に名前付きルートを使えるようになった」というのが大きな変化です。早速headerパーシャルとfooterパーシャルにあるlink_toメソッドの記述を変更していきましょう。

なお、headerパーシャルでは、Web共通の慣習に従って、ロゴにもHomeページへのリンクを追加しています。

app/views/layouts/_header.html.erb
  <header class="navbar navbar-fixed-top navbar-inverse">
    <div class="container">
-     <%= link_to "sample app", '#', id: "logo" %>
+     <%= link_to "sample app",  root_path, id: "logo" %>
      <nav>
        <ul class="nav navbar-nav navbar-right">
-         <li><%= link_to "Home",   '#' %></li>
-         <li><%= link_to "Help",   '#' %></li>
+         <li><%= link_to "Home",    root_path %></li>
+         <li><%= link_to "Help",    help_path %></li>
          <li><%= link_to "Log in", '#' %></li>
        </ul>
      </nav>
    </div>
  </header>
app/views/layouts/_footer.html.erb
  <footer class="footer">
    <small>
      The <a href="https://railstutorial.jp/">Ruby on Rails Tutorial</a>
      by <a href="http://www.michaelhartl.com/">Michael Hartl</a>
    </small>
    <nav>
      <ul>
-       <li><%= link_to "About",   '#' %></li>
-       <li><%= link_to "Contact", '#' %></li>
+       <li><%= link_to "About",    about_path %></li>
+       <li><%= link_to "Contact",  contact_path %></li>
        <li><a href="http://news.railstutorial.org/">News</a></li>
      </ul>
    </nav>
  </footer>

例えば、/aboutではAboutページが表示されます。

スクリーンショット 2019-09-26 20.38.07.png

このときのHTTPリクエストとそれに対するrails serverの反応は以下のとおりです。

Started GET "/about" for 172.17.0.1 at 2019-09-26 11:37:03 +0000
Cannot render console from 172.17.0.1! Allowed networks: 127.0.0.1, ::1, 127.0.0.0/127.255.255.255
Processing by StaticPagesController#about as HTML
  Rendering static_pages/about.html.erb within layouts/application
  Rendered static_pages/about.html.erb within layouts/application (0.8ms)
  Rendered layouts/_rails_default.erb (140.5ms)
  Rendered layouts/_shim.html.erb (0.3ms)
  Rendered layouts/_header.html.erb (0.7ms)
  Rendered layouts/_footer.html.erb (0.5ms)
Completed 200 OK in 349ms (Views: 307.2ms)

演習 - 名前付きルート

1. リスト 5.29のようにhelfルーティングを作成し、レイアウトのリンクを更新してみてください。

config/routes.rb
  Rails.application.routes.draw do
    root 'static_pages#home'
-   get '/help', to: 'static_pages#help'
+   get '/help', to: 'static_pages#help', as: 'helf'
    get '/about', to: 'static_pages#about'
    get '/contact', to: 'static_pages#contact'
  end
app/views/layouts/_header.html.erb
  <header class="navbar navbar-fixed-top navbar-inverse">
    <div class="container">
      <%= link_to "sample app",  root_path, id: "logo" %>
      <nav>
        <ul class="nav navbar-nav navbar-right">
          <li><%= link_to "Home",    root_path %></li>
-         <li><%= link_to "Help",    help_path %></li>
+         <li><%= link_to "Help",    helf_path %></li>
          <li><%= link_to "Log in", '#' %></li>
        </ul>
      </nav>
    </div>
  </header>

この変更を加えた後、rails consoleにおけるapp.help_pathメソッドとapp.helf_pathメソッドの存在確認の結果は以下の通りになります。

>> app.help_path
NoMethodError (undefined method `help_path' for #<ActionDispatch::Integration::Session:0x0000561721e38dc8>)
>> app.helf_path
=> "/help"

一方、rails serverの結果は以下の通りになります。

Started GET "/help" for 172.17.0.1 at 2019-09-26 11:44:11 +0000
Cannot render console from 172.17.0.1! Allowed networks: 127.0.0.1, ::1, 127.0.0.0/127.255.255.255
Processing by StaticPagesController#help as HTML
  Rendering static_pages/help.html.erb within layouts/application
  Rendered static_pages/help.html.erb within layouts/application (0.5ms)
  Rendered layouts/_rails_default.erb (194.1ms)
  Rendered layouts/_shim.html.erb (0.4ms)
  Rendered layouts/_header.html.erb (0.6ms)
  Rendered layouts/_footer.html.erb (1.0ms)
Completed 200 OK in 376ms (Views: 342.8ms)

名前付きルートの名前を変えても、エンドポイントが/helpのまま変わっていないことは重要です。config/routes.rbにおいて、getルールの第1引数を変えなければ、エンドポイントは変わらないのです。

2. 前回の演習と同様に、エディタのUndo機能を使ってこの演習で行った変更を元に戻してみてください。

config/routes.rb
  Rails.application.routes.draw do
    root 'static_pages#home'
-   get '/help', to: 'static_pages#help', as: 'helf'
+   get '/help', to: 'static_pages#help'
    get '/about', to: 'static_pages#about'
    get '/contact', to: 'static_pages#contact'
  end
app/views/layouts/_header.html.erb
  <header class="navbar navbar-fixed-top navbar-inverse">
    <div class="container">
      <%= link_to "sample app",  root_path, id: "logo" %>
      <nav>
        <ul class="nav navbar-nav navbar-right">
          <li><%= link_to "Home",    root_path %></li>
-         <li><%= link_to "Help",    helf_path %></li>
+         <li><%= link_to "Help",    help_path %></li>
          <li><%= link_to "Log in", '#' %></li>
        </ul>
      </nav>
    </div>
  </header>

リンクのテスト

初めての結合テストです。ここでは、「アプリケーションのHTML構造を調べて、レイアウトの各リンクが正しく動くかどうかをチェックする」というテストを書く方法を学習していきます。

まず、site_layoutというテストのテンプレートを作成します。

# rails generate integration_test site_layout
Running via Spring preloader in process 1434
      invoke  test_unit
      create    test/integration/site_layout_test.rb

Railsが渡されたファイル名の末尾に_testという文字列を追加しているのがポイントなのだそうです。

リンクのテストの全体像

今回のテストの全体像は以下のとおりです。

  1. ルートURL(Homeページ)にGETリクエストを送る。
  2. 正しいページテンプレートが描画されているか確かめる。
  3. Home、Help、About、Contactの各ページへのリンクが正しく動作するか確かめる。

test/integration/site_layout_test.rbの全体像は以下のとおりです。

test/integration/site_layout_test.rb
require 'test_helper'

class SiteLayoutTest < ActionDispatch::IntegrationTest

  test "layout links" do
    get root_path
    assert_template 'static_pages/home'
    assert_select "a[href=?]", root_path, count: 2
    assert_select "a[href=?]", help_path
    assert_select "a[href=?]", about_path
    assert_select "a[href=?]", contact_path
  end
end

リンクのテストは何を確認するか

上記のコードでは、以下の確認が行われます。

  • root_pathへのGETリクエストの送出
  • root_pathへGETリクエストを送出して返ってきたリソースに対する以下の確認
    • static_pages/homeというテンプレートが描画されているか
    • root_pathが示すリソースをリンク先とするa要素が2つ存在するか
    • help_pathが示すリソースをリンク先とするa要素が1つ存在するか
    • about_pathが示すリソースをリンク先とするa要素が1つ存在するか
    • contact_pathが示すリソースをリンク先とするa要素が1つ存在するか

実際のコードの解説

例えば、以下のコードを取り上げてみます。

assert_select "a[href=?]", about_path

当該テストコードでは、Railsは?を自動的にabout_pathに置換します1。現時点で、about_pathに対応するエンドポイントは/aboutなので、これにより、以下のようなHTMLコードがあるかをチェックすることになります。

<a href="/about">...</a>

現時点で、static_pages/homeテンプレートが描画されたときのルートURLへのリンクは2つ存在します2。ルートURLが2つあるかどうかをチェックする場合は、以下のテストコードを用います。オプションハッシュで:countキーに対する値が2と定義されているのがポイントです。

assert_select "a[href=?]", root_path, count: 2

この他にも、assert_selectには様々な機能があります。興味がありましたら、Railsチュートリアル 表5.2を参照してみてください。

テストを実行してみる

統合テストのみを実施する場合は、Railsの開発環境で以下のコマンドを実行します。

# rails test :integration

rails testの部分はrails tでもOKですね。

# rails t :integration
...略

  6/6: [=============================================================================================================================================================] 100% Time: 00:00:02, Time: 00:00:02

Finished in 2.20712s
6 tests, 14 assertions, 0 failures, 0 errors, 0 skips

無事にテストが通りました。全体のテストはどうでしょうか。

# rails test
...略

  6/6: [=============================================================================================================================================================] 100% Time: 00:00:01, Time: 00:00:01

Finished in 1.81602s
6 tests, 14 assertions, 0 failures, 0 errors, 0 skips

全体のテストも無事通りました。

「リンクに間違った変更が加えられたら、テストですぐに気づくことができる」という仕組みが無事整備されましたね。

演習 - リンクのテスト

1. footerパーシャルのabout_pathcontact_pathに変更してみて、テストが正しくエラーを捕まえてくれるかどうか確認してみてください。

app/views/layouts/_footer.html.erb
  <footer class="footer">
    <small>
      The <a href="https://railstutorial.jp/">Ruby on Rails Tutorial</a>
      by <a href="http://www.michaelhartl.com/">Michael Hartl</a>
    </small>
    <nav>
      <ul>
-       <li><%= link_to "About",    about_path %></li>
+       <li><%= link_to "About",    contact_path %></li>
        <li><%= link_to "Contact",  contact_path %></li>
        <li><a href="http://news.railstutorial.org/">News</a></li>
      </ul>
    </nav>
  </footer>

上記変更をした場合、テストの結果はどうなるでしょうか…という話ですね。テストは通らないはずです。

# rails t :integration
...略

 FAIL["test_layout_links", SiteLayoutTest, 1.887058500025887]
 test_layout_links#SiteLayoutTest (1.89s)
        Expected at least 1 element matching "a[href="/about"]", found 0..
        Expected 0 to be >= 1.
        test/integration/site_layout_test.rb:10:in `block in <class:SiteLayoutTest>'

  6/6: [=============================================================================================================================================================] 100% Time: 00:00:01, Time: 00:00:01

Finished in 1.89008s
6 tests, 13 assertions, 1 failures, 0 errors, 0 skips

めでたく(?)テストは通りませんでした。「a[href="/about"]にマッチする要素が(HTMLコード中に)見つからない」という不適合を報告してきています。

…この状態で先には進めないので、app/views/layouts/_footer.html.erbに対する先ほどの変更はもとに戻しておきましょう。

2.1. リスト 5.35で示すように、Applicationヘルパーで使っているfull_titleヘルパーを、test環境でも使えるようにすると便利です。こうしておくと、リスト 5.36のようなコードを使って、正しいタイトルをテストすることができます。

test/test_helper.rb
  ENV['RAILS_ENV'] ||= 'test'
  ...略

  class ActiveSupport::TestCase
    # ...略
    fixtures :all
+   include ApplicationHelper
    # ...略
  end
test/integration/site_layout_test.rb
  require 'test_helper'

  class SiteLayoutTest < ActionDispatch::IntegrationTest

    test "layout links" do
      get root_path
      assert_template 'static_pages/home'
      assert_select "a[href=?]", root_path, count: 2
      assert_select "a[href=?]", help_path
      assert_select "a[href=?]", about_path
      assert_select "a[href=?]", contact_path
+     get contact_path
+     assert_select "title", full_title("Contact")
    end
  end

現時点で、テストは問題なく通ります。

# rails test
...略

  6/6: [=============================================================================================================================================================] 100% Time: 00:00:01, Time: 00:00:01

Finished in 1.68342s
6 tests, 15 assertions, 0 failures, 0 errors, 0 skips

2.2. ただし、これは完璧なテストではありません。例えばベースタイトルに「Ruby on Rails Tutoial」といった誤字があったとしても、このテストでは発見することができないでしょう。

app/helpers/application_helper.rb
  module ApplicationHelper

    # ページごとの完全なタイトルを返します。
    def full_title(page_title = '')
-     base_title = "Ruby on Rails Tutorial Sample App"
+     base_title = "Ruby on Rails Tutoial Sample App"
      if page_title.empty?
        base_title
      else
        page_title + " | " + base_title
      end
    end
  end

以下のように、site_layout_testは通ってしまいます。

# rails t test/integration/site_layout_test.rb
...略

  1/1: [=============================================================================================================================================================] 100% Time: 00:00:01, Time: 00:00:01

Finished in 1.88365s
1 tests, 6 assertions, 0 failures, 0 errors, 0 skips

2.3. この問題を解決するためには、full_titleヘルパーに対するテストを書く必要があります。そこで、Applicationヘルパーをテストするファイルを作成し、リスト 5.37FILL_INの部分を適切なコードに置き換えてみてください。

test/helpers/application_helper_test.rb
require 'test_helper'

class ApplicationHelperTest < ActionView::TestCase
  test "full title helper" do
    assert_equal full_title,         "Ruby on Rails Tutorial Sample App"
    assert_equal full_title("Help"), "Help | Ruby on Rails Tutorial Sample App"
  end
end

早速application_helper_test.rbに対してrails testを実行してみます。

# rails test test/helpers/application_helper_test.rb
...略

 FAIL["test_full_title_helper", ApplicationHelperTest, 0.04009939997922629]
 test_full_title_helper#ApplicationHelperTest (0.04s)
        --- expected
        +++ actual
        @@ -1 +1 @@
        -"Ruby on Rails Tutoial Sample App"
        +"Ruby on Rails Tutorial Sample App"
        test/helpers/application_helper_test.rb:5:in `block in <class:ApplicationHelperTest>'

  1/1: [=============================================================================================================================================================] 100% Time: 00:00:00, Time: 00:00:00

Finished in 0.04308s
1 tests, 1 assertions, 1 failures, 0 errors, 0 skips

見事(?)テストで不適合が出ました。

2.余談. base_titleを正しく直したときに、テストが通るかを確認してみます。

base_titleの中身を"Ruby on Rails Tutorial Sample App"に直してみます。

app/helpers/application_helper.rb
  module ApplicationHelper

    # ページごとの完全なタイトルを返します。
    def full_title(page_title = '')
-     base_title = "Ruby on Rails Tutoial Sample App"
+     base_title = "Ruby on Rails Tutorial Sample App"
      if page_title.empty?
        base_title
      else
        page_title + " | " + base_title
      end
    end
  end

再びapplication_helper_test.rbに対してrails testを実行してみます。

# rails test test/helpers/application_helper_test.rb
...略

  1/1: [=============================================================================================================================================================] 100% Time: 00:00:00, Time: 00:00:00

Finished in 0.02249s
1 tests, 2 assertions, 0 failures, 0 errors, 0 skips

今度こそテストが通りました。


  1. このとき、about_path内に特殊記号があればエスケープ処理されます。 

  2. 1つはロゴに、もう1つはナビゲーションバー内にあります。 

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Ruby on Rails コンテンツの一覧を昇順/降順 にするメソッドとkaminari ページネーションの実装

初めに

Ruby on Railsで作成しているブログのコンテンツ一覧などの昇順/降順にするメソッドとページネーションを実装するためのgem kaminariの実装メモです。

降順/昇順にするにはorderメソッドを使う

  • orderメソッドは、テーブルから取得してきたインスタンスたちを並び替えるメソッドである。

昇順の場合

contents_controller.rb
# 省略
def index
  @contents = Contents.all.order("id ASC")
end

降順の場合

contents_controller.rb
# 省略
def index
  @contents = Contents.all.order("id DESC")
end
  • allメソッドを利用した場合、通常であればレコードはid順に取得されるが、上記のようにorderメソッドの引数として(“id DESC”)とすれば、レコードを逆順に並び替えられる。

  • また、orderメソッドを利用する場合は、以下のようにallメソッドを省略することができる。

contents_controller.rb
# 省略
def index
  @contents = Contents.order("id DESC") # allメソッドを省略できる
end

ページネーション(kaminari)の実装

  • kaminariをいうGemの一種をインストールすることによって実装可能。

1. Gemfileの最後の行にkaminariを追記

Gemfile
# (省略)
gem 'kaminari'

2. bundle installを実行

ターミナル
bundle install
  • 必ずローカルサーバーを再起動することを忘れずに。

kaminari:pageメソッド

  • kaminariを導入すると、モデルクラスにpageメソッドが定義される。
  • このメソッドは、ページネーションにおけるページ数を指定する。
  • ビューのリクエストの際にparams中にpageというキーが追加されて、その値がビューで指定した番号になる。よってpageの引数はparams[:page]となる。

kaminari:perメソッド

  • perメソッドもpageメソッドと同様に、kaminariを導入することで使えるメソッドである。
  • 1ページあたりに表示する件数を指定する。
  • perメソッドに引数をして渡した数字が、ページネーションが実装されたビューで1ページあたりに表示する件数になる。

上記2つのメソッドは以下のような記述方法になる。

sample_controller.rb
変数名 = クラスを利用して取得したレコードのインスタンス.page(params[:page].per(ここに1ページで表示したい件数を入力)

contentsコントローラーのindexアクションに今度は投稿日時の降順で記述し、さらにページネーションを導入した記述をしてみると以下のようになる。

contents_controller.rb
# 省略
def index
  @contents = Contents.order("created_at DESC").params[:page].per(5)
end

kaminari:paginateメソッド

  • ページネーションのリンクを表示したいときに使用するメソッド。
  • kaminariをインストールすると利用できます。paginateメソッドの引数は、コントローラで定義した変数を指定する。

viewには<%= paginate(@contents) %>と記述すればよい。

contents.html.erb
<div>
  <% @contents.each do |content| %>
    # 省略
  <% end %>
  <%= paginate(@contents) %>
</div>

最後に

gemを入れると使える便利なメソッドがどんどん増えてとても便利。
積極的に使っていこうと思った。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

rails webアプリケーション管理者権限でユーザーを削除する(delete)方法,deviseなしバージョン(初心者)

(delete)ユーザー削除機能を実装

ネット情報ではログイン機能 gem deviseをを前提としたのが多く当方初心者な為、まぁまぁ時間を食った。
後々の私の様な初心者の為にRailsチュートリアルを中心に改めて自分なりにまとめて見た。

⒈管理者権限用カラムを作成

一般ユーザーと分ける為に管理者専用カラム作成。

$ rails generate migration add_admin_to_users admin:boolean

user.rb
class AddAdminToUsers < ActiveRecord::Migration[5.0]
  def change
    add_column :users, :admin, :boolean, default: false
  end
end

$ rails db:migrate

⒉管理者権限を1人に与える

admin を true に。

db/seeds.rb
User.create!(name: "Exaple User",
             email: "example@railstutorial.org",
             password:                 "foobar",
             password_confirmation:    "foobar",
             admin: true )

$ rails db:migrate:reset

$ rails db:seed

③ログインユーザーが管理者ならパーシャルの横にdelete ボタンを表示

この!current_user?(user)は自分自身の2つ目のアカウントでは管理者権限は無効に。

db/app/views/users/_user.html.erb
<div>
  <%= gravatar_for user, size: 50 %>
  <%= link_to user.name, user %>
  <% if current_user.admin? && !current_user?(user) %>
    | <% link_to "delete" user, method: :delete,
                          data: {confirm: "You sure?"} %>
  <% end %>     
</div>

current_user? が使えるように定義

db/sessions/helper.rb
def current_user?(user)
  user == current_user
end

⒈ログインが前提なので、require_user_logged_inにdestroyを追加。
⒉管理者だけが削除できるように、admin_user, only: :destroyをbefore_actionに新たに作成。
⒊動作用destroyアクションを追加

db/user_controller.rb
before_action :require_user_logged_in, only: [:index, :show, :edit, :update, :destroy, :followings, :followers]
before_action :admin_user, only: :destroy #アクション前に事前確認用。


def destroy
  User.find(params[:id]).destroy
  flash[:success] = "ユーザー削除完了"
  redirect_to users_path
end

private

#管理者か確認。
def admin_user
  redirect_to(root_path) unless current_user.admin?
end

あとは実際に動作確認するだけ。

もしエラーが出たら、こちらも参照。

ユーザー削除するってことは、関連するデータの処理もどうするのか?

https://qiita.com/shutyan/items/05977055b2ce32c2e322

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[初学者]よく起きるエラー 〜syntax error, unexpected end-of-input, expecting keyword_end〜

目的

学習の備忘録と初学者の参考資料として投稿

syntax error, unexpected end-of-input, expecting keyword_endというエラー

コードのエラーってよく赤字で英語表記だから、読む気にならねぇ〜っ:dizzy_face:
しかも焦っちゃう、、、、、:sweat_smile:
実際に単語を訳して見ると

単語訳

syntax・・・構文  
unexpected・・・予想外・予期しない 
expecting・・・期待して  
                       ...etc

つまり

endがねぇよ!!ってこと

ハイハイ、書きます書きます:writing_hand:

まとめ

エラーはパソコンが親切に教えてくれてることなので、恐れず・焦らずに対処したほうがいい。
まずはエラー文を読んでみて、何が書いてるのか理解すれば、簡単に解決することも多い。
                                         
今後も学習で気づきや参考になるものがあれば、アップしていきます。
もし参考になったらいいね!!よろしくお願いします:bow_tone1:

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

text_fieldのplaceholderを改行する方法

はじめに

railsのtext_fieldで作成したテキストボックスに改行ありのplaceholderを書きたかった。

ただ調べると文字列に改行コードをいれたり、cssでいじったりと、
個人的にはあまりやりたくない方法しかでてこなかったので、なにか完結にできる方法がないかを模索していた。

実装

helperでヒアドキュメントを使って文字列を定義する。
それをテンプレート側(haml)で呼び出すだけ。

ソース

= f.text_area :text, class: 'form-control', placeholder: text_placeholder
def text_placeholder
  <<-"EOS".strip_heredoc
    行1
    行2
    行3
  EOS
end

キャプチャ

こんな感じにうまく表示されました。
 2019-09-27 13.01.16.png

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[初学者]シングルクォーテーションとダブルクォーテーションの違い(ruby)

目的

学習の備忘録と初学者の参考資料として投稿

シングルクォーテーションとダブルクォーテーション

ネットや参考書などでよく見られる’’や””の違いについての話。特にプログラミングを初めて勉強する方にとって、どちらにするかで非常に悩ましい場面に遭遇することがあります。

sample.rb
'Hello world' 
=>Hello world

"Hello world"
=>Hello world

こんな感じの:grin:

ダブルクォーテーションの役割

式展開や改行文字列を入れたい場合はダブルクォーテーションで囲む必要がある。

sample.rb
puts "Hello \n world" **改行文字列**
=>Hello
  world

name = Taro
puts "Hello #{name}" **式展開**
=>Hello Taro

まとめ

基本はダブルクォーテーションでいいのでは:point_up:
いろんな記事を見てるとダブルクォーテーションだと読み込み速度が遅くなるやシングルクォーテーションを書いて、視認性をよくするなどなど書いてあるが、特に気にしなくてもいい:ok_hand:

今後も学習で気づきや参考になるものがあれば、アップしていきます。
もし参考になったらいいね!!よろしくお願いします:bow_tone3:

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Rails Webアプリケーション管理者権限でユーザー削除出来なかったエラー(初心者)

動作確認で管理者としてユーザーを削除しようとしたらエラー発生。

忘れないために自分用忘備録

以下エラー文
ActiveRecord::StatementInvalid in UsersController#destroy

Mysql2::Error: Cannot delete or update a parent row: a foreign key constraint fails・・・・・

原因

dependent: :destroy書き忘れていた為に発生したエラー
要するに、削除しようとしているユーザーの投稿、follower、お気に入り等どうするのって話。

対策

UserテーブルとPostテーブルを関連付けするために以下のコードを追加し、
Userのデータが削除されたときに、関連するPostのデータを削除するように設定。

dependent: :destroy

app/models/user.rb
class User < ApplicationRecord
  has_many :posts, dependent: :destroy
  has_many :follows, dependent: :destroy
  has_many :favorites, dependent: :destroy
end

これでユーザーに関連付けられたデータは削除完了。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Railsでデバッグ用のログを出すときの簡易なスニペット

自分用メモ。
こんな感じでlibの下に作っておくとログを出すときに便利。
ログのレベルも一括で変えたりとかできるようにしておくとなお良いかも。

class DebugLogger
  # 一番シンプルな形がこれ
  def self.info_log(log_msg, prefix = '')
    Rails.logger.info("[dev]-[#{Time.current}]-[#{prefix}] #{log_msg}")
  end

  # こんな感じで機能を持ったログを吐かせるようにしとくと、使う側のコードがスッキリする。
  def self.user_params(user, prefix = '')
    columns = ['id', 'name', 'updated_at']
    log_msg = columns.map{|column_name| user.attributes[column_name] }.join(", ")
    Rails.logger.info("[debug]-[#{Time.current}]-[#{prefix}] #{log_msg}")
  end
end

使う時はこう。インスタンス化せずに1行で書けるのがいい。

user = User.find(modified_user_id)

DebugLogger.user_params(user, '編集後')

ちなみに例外を拾ってスタックトレースを出すときはこんな感じで書くと良い

  rescue StandardError => e
    Rails.logger.info("[#{Time.current}] - #{e.backtrace.join("\n")}")
    # render plain: e.message
  end
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【aws】LoadError: No such file to load -- aws-sdk-s3.rb【自動デプロイ中】

はじめに

自動デプロイをかけたところ、タイトルのエラーに遭遇。
結論、解決はしたものの原因不明のエラーの為、今後色々調べたいので備忘録として記載します。
OSが関係してるのかなと推測してますが、分かる方いらっしゃればご教示下さい。

開発環境

Rails 5.2.1
ruby 2.5.1
capistrano 3.11.1
AWS(EC2)
Web Server Nginx
Application Server Unicorn

前提

上記導入済み、aws接続して自動デプロイまでは問題無し。S3設定後初めての自動デプロイ中にunicorn startで止まったエラー。

ファイルのLoadErrorが発生

unicorn startで止まり、エラー文にはstderr.logの詳細をチェックするようにという記述。

current/log/unicorn.stderr.log
# 本番環境でlog表示(less or cat)
$ less log/unicorn.stderr.log

# エラー抜粋
I, [2019-09-20T08:48:07.350883 #12335]  INFO -- : Refreshing Gem list
bundler: failed to load command: unicorn (/var/www/appname/shared/bundle/ruby/2.5.0/bin/unicorn)
LoadError: No such file to load -- aws-sdk-s3.rb

原因(不明)

今回導入予定の無いaws-sdkというパッケージに関連するエラー。
確認したところ、

公式
http://aws.amazon.com/jp/sdkforruby/
参考
https://qiita.com/w650/items/50449fe162bc0f8425e4

というようなgemでした。

検証計画

  • aws-sdk-s3.rbの存在→なし
  • 本番・ローカルでgemfile、gemfile lockの確認→記述なし
  • 再起動・bundleinstallのし直し→変化なし
  • S3導入時に変更した設定関連のファイルを確認→問題無さそう (database.yml/deploy.rb/image_uploder/unicorn.rb/carrierwave.rb/enviroment.rb/capfileなど)
  • コミットを辿り自動デプロイできていたところまで遡る→できていたはずの段階でも同じエラー
  • ★一度、 aws-sdk-s3を導入してみる
  • git cloneをやり直し、再度環境構築
  • EC2インスタンスから作成のし直し

解決

結局、gemを導入することで解決。
Gemfileにaws-sdkを追加、bundleinstall、merge、(念の為本番環境でもpullとbundle install)、自動デプロイで本番環境にページ表示されるように。

さいごに

自分の中では最終手段のひとつと思っていた導入をすることに。
理由や原因が分からないまま、使わなければいいとは言えgemを追加するのが抵抗あったからですが、かなり時間をかけてしまいました。
コードに特に違和感が無ければ、もっと早くに試しても良かったというのが反省点。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Railsチュートリアル 第5章(余談) - Rails5環境で学習を進めているのに、なぜRails5で非推奨のassert_templateが正常動作するのか

Rails5では、assert_templateは非推奨

Railsチュートリアルで使われているコードのうち、assert_templateは、Rails5では非推奨となりました。Ruby on Rails - issue #18950に、非推奨とするに至った経緯の説明、および関連するやり取りが残っています(英語)。

Deprecation of assigns and assert_template in controller tests - BigBinary Blogにも、この変更についての説明が記述されています(英語)。

今Rails5でRailsチュートリアルを進めている

# rails version
Rails 5.1.6

…ちょっと待って下さい。現在Railsチュートリアルを進めているRailsのバージョンは5.1.6ですよね。なぜassert_templateが動いているのです?

Railsチュートリアルでassert_templateが正常動作する理由

答えは/Gemfileにありました。

group :test do
  gem 'rails-controller-testing', '1.0.2'
  gem 'minitest',                 '5.10.3'
  gem 'minitest-reporters',       '1.1.14'
  gem 'guard',                    '2.13.0'
  gem 'guard-minitest',           '2.4.4'
end
gem 'rails-controller-testing', '1.0.2'

rails-controller-testingというGemがインストールされていれば、Rails5でもassert_templateを動かすことができます。Railsチュートリアルでは、第3章のリスト 3.2時点でrails-controller-testing/Gemfileに追加していますね。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Railsでシンプルなグラフを扱うならchart-js-rails よりchartkickを使うべし

Railsでグラフを扱う方法として chart-js-rails を使った方法を こちらの記事で解説しました。
一方、シンプルなグラフを埋め込む場合においては chartkick を使ったほうが簡単なことがわかったので本記事で解説します。

chartkickとは

chart.jsをいい感じにラッピングして、ワンラインでグラフを埋め込めるようにするプロジェクトです。
Rubyに限らず様々な言語で実装されています。

https://chartkick.com/
Chartkick_-_Create_beautiful_JavaScript_charts_with_one_line_of_Ruby.png

また、chart.jsだけでなくGoogle ChartsやHighchartsもサポートしています。

Chartkick_-_Create_beautiful_JavaScript_charts_with_one_line_of_Ruby.png

chartkickを使ったほうが良い理由

RubyとJavascript間のデータの受け渡しを意識しなくて良い

こちらの記事の方法だと、Ruby側で扱う数値を何らかの方法でJavascriptで受け渡す必要がありました。

chartkickの場合はデータを配列にしてRubyのメソッドへ渡すだけなので、Ruby側のみで実装が完結します。

githubのスターの数が多い

あくまでgemで比較した場合ですが、chartkickの方が断然スターが多いです。
直近のコミット日時もchartkickの方が新しいです。

Rails6にも対応している

Ruby on Rails6からデフォルトのJavascriptコンパイラがWebpackerとなります。
おそらく、chart-js-rails をRails6で使おうとすると若干の手間がかかると推測されます。

実際に使ってみる

サンプルアプリケーションを作る

今回は時事ネタとして「ラグビーワールドカップ開催国」に関する情報をグラフ化します。
以下コマンドを実行してアプリケーションを作成します。

$ rails new chartkick_sample
$ rails g scaffold rugby_world_cup_host_country name:string total_attendance:integer matches:integer stadium_capacity:integer held_at:datetime

db/seeds.rbWikipediaを参考にラグビーワールドカップの開催国を入力します。
※厳密には1991年と1987年にも開催されているのですが、開催国が複数あってDB構造が複雑化するので今回は1995年以降のみ入力しました。

db/seeds.rb
[
  [1995, 'South Africa', 1100000, 32, 1423850],
  [1999, 'Wales', 1750000, 41, 2104500],
  [2003, 'Australia', 1837547, 48, 2208529],
  [2007, 'France', 2263223, 48, 2470660],
  [2011, 'New Zealand', 1477294, 48, 1732000],
  [2015, 'England', 2477805, 48, 2600741],
  [2019, 'Japan', nil, 48, nil],
  [2023, 'France', nil, 48, nil],
].each do |record|
  RugbyWorldCupHostCountry.create(
    held_at: Time.zone.local(record[0]),
    name: record[1],
    total_attendance: record[2],
    matches: record[3],
    stadium_capacity: record[4]
  )
end

入力が終わったらDBの作成・マイグレーション・seedを実行します。

rails db:create db:migrate db:seed

http://localhost:3000/rugby_world_cup_host_countries へアクセスすると、一覧が表示されました。

ChartkickSample.png

グラフを表示する

chartkickのインストール

Gemfileに追記して、bundle install します。
続けて yarn add も実行してしまいましょう。

Gemfile
・・・省略・・・
gem 'bootsnap', '>= 1.4.2', require: false
gem "chartkick" # 追記

group :development, :test do
  # Call 'byebug' anywhere in the code to stop execution and get a debugger console
  gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
end
・・・省略・・・
$ bundle install

ここからはRails6以降かRails5以前かで手順が分かれます。

Rails6以降

yarnchart.jsをインストールします。

$ yarn add chartkick chart.js

application.jschart.jschartkick をrequireします。

app/javascript/packs/application.js
require("@rails/ujs").start()
require("turbolinks").start()
require("@rails/activestorage").start()
require("channels")

require("chartkick") // 追記
require("chart.js" // 追記
Rails5以前

application.js へ以下を追記します。

app/assets/javascripts/application.js
//= require chartkick
//= require Chart.bundle

グラフの実装

開催国一覧ページにグラフを埋め込みます。

app/views/rugby_world_cup_host_countries/index.html.erb
<p id="notice"><%= notice %></p>

<h1>Rugby World Cup Host Countries</h1>

<%= column_chart RugbyWorldCupHostCountry.pluck(:held_at, :total_attendance) %><!-- 追記 -->

<table>
  <thead>
    <tr>
      <th>Name</th>
      <th>Total attendance</th>
      <th>Matches</th>
      <th>Stadium capacity</th>
      <th>Held at</th>
      <th colspan="3"></th>
    </tr>
  </thead>
・・・省略・・・

http://localhost:3000/rugby_world_cup_host_countries へアクセスするとグラフが表示されます。

ChartkickSample.png

オプションを指定すれば色やサイズも変えられます。

app/views/rugby_world_cup_host_countries/index.html.erb
<p id="notice"><%= notice %></p>

<h1>Rugby World Cup Host Countries</h1><!-- 追記 -->

<%= column_chart RugbyWorldCupHostCountry.pluck(:held_at, :total_attendance),
                 id: 'total-attendance-chart',
                 width: '400px',
                 height: '500px',
                 colors: ['#b00'] %><!-- 追記 -->

<table>
  <thead>
    <tr>
      <th>Name</th>
      <th>Total attendance</th>
      <th>Matches</th>
      <th>Stadium capacity</th>
      <th>Held at</th>
      <th colspan="3"></th>
    </tr>
  </thead>
・・・省略・・・

ChartkickSample.png

chartkickでできそうにないこと

現時点で実現方法がわからなかったことを記載しておきます。
実現方法をご存知な方はぜひコメントをお願いします。

  • 2軸のグラフを表示する
  • 2種類のグラフ(折れ線グラフと棒グラフなど)を1つのグラフとして表示する

まとめ

RubyとJavascript間の値の受け渡しを意識しなくて良いですし、なにより1行でグラフを埋め込めるのが素晴らしいです。
Railsでシンプルなグラフを出力したい方はぜひ使ってみてください。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む