- 投稿日:2020-10-13T23:26:38+09:00
【超初心者向け】ハッシュとシンボルの押さえておきたい最低限の知識
配列とハッシュの違い
配列は同じ意味を持つ複数の情報を1つにまとめたもので、ハッシュは関係のある複数の情報を1つにまとめたもの
ハッシュ
変数 = { キー1 => バリュー1, キー2 => バリュー2, キー3 => バリュー3 }・別々の意味を持つ値を1つにまとめることができるので、複数の関係性のある値を管理するときに用いる
・「データ」とそれに対応する「名前」のセットを要素として持つ
・ハッシュではデータをバリュー、名前をキーという# ハッシュのキーに文字列を使用した場合 hash1 = { "name" => "nick", "age" => 30, "country" => "UK" }シンボル
・ハッシュのキーに数値として用いられるもの
・見た目は文字列のように見えるが実際の中身は数値である
・書き方は2種類あるがどちらも実態は同じ
・hash3が一番シンプルでよく使用される# ハッシュのキーにシンボルを使用した場合 hash2 = { :name => "nick", :age => 30, :country => "UK" } hash3 = { name: "nick", age: 30, country: "UK" }⚠️コンピュータは文字列より数値の方が処理速度が早くなるため
シンボルの方がよく使用される
ここまでで超基礎の部分はクリアです!!
シンボルで書かれたハッシュに慣れるのがいいかと思いますが、理解をした上で使用するようにしましょう。
続いてはハッシュの追加や2重ハッシュの値の取得について説明したいと思います!
もう少し知識を吸収したい方はぜひ続きもご覧ください。
ハッシュへ要素を追加
teacher = { name: "nick"} teacher[:age] = 30 # ハッシュ[追加するキー] = 値 puts teacher # 出力結果 # {:name=>"nick", :age=>30}ハッシュの値を変更
teacher = { name: "nick", age: 30} teacher[:name] = "john" # ハッシュ[変更したい値のキー] = 値 puts teacher # 出力結果 # {:name=>"john", :age=>30}ハッシュの値を取得
teacher = { name: "nick", age: 30} puts teacher[:name] # ハッシュ[取得したい値のキー] # 出力結果 # nick2重ハッシュの値を取得
#変数teacher_data→配列の内部に複数の情報をハッシュとして持つ #teacher_dataからnameデータを取得する teacher_data = [ { teacher: { profile: { name: "nick" } } }, { teacher: { profile: { name: "john" } } }, { teacher: { profile: { name: "mac" } } } ] teacher_data.each do |t| puts t[:teacher][:profile][:name] end # 出力結果 # nick # john # mac【解説】
ブロック引数のtはteacher_dataのtを用いています。
putsのあとはハッシュ[取得したいキー]を取得したいデータ(今回の場合はname)まで連結して記述します。
お疲れ様でした!!
ハッシュとシンボルについての超基礎知識は以上です!
基礎が理解できていないと後々困ると思うので、この機会にぜひ理解が深まればな〜と思います。
わかりにくい点、至らない点ございましたら遠慮なくお知らせください!
それではありがとうございました。参考
- 投稿日:2020-10-13T23:10:27+09:00
【プログラミング初心者の方へ】メソッドってなに?
はじめに
最近プログラミングを始めた方、特にスクールに行かず「独学でやったるぜ!」と意気込むそこのあなた!
はい。自分もそうでした。そして理由もなく考えもなくRubyに手を出してるところも一緒です。仲間!
でも、、、
わからないことがわからない
ですよね。
コード書け!って言われてもなに書けばいいのかわかんない!まあそれが普通だと思います。たまに歴半年くらいで開眼してメタプロまで書いちゃうような突然変異種(天才)もいますが気にしない方がよいです。そういう人は大概優しくて教えるのも上手なので色々教えてもらいましょう。
本題
Rubyに限らずですが、プログラミング初心者がよくつまづいたり、理解に苦しむところは
メソッド
,引数
じゃないでしょうか。自分はそうでした。
自分で考えたメソッドを書く
これの意味が理解できなかったです。ああ懐かしいもどかしい。
自分の中でしっくりくる捉え方が見つかるまで時間がかかりました。(自分は割とすぐに実務に入ったのでその中で感覚を掴みました。長く独学をするのはあまりおすすめしません。)
メソッドにも
インスタンスメソッド
,クラスメソッド
なるものがいてどう使うのかどこで使うのか全然わからない!って感じでした。なので自分なりの解釈をここでお伝えしたいと思います!
メソッドの解釈
ターミナルを開いて
irb
を起動しましょう。以下のように入力してみてください。irbhoge = 'hogeはホゲホゲ'続けて以下のコードを実行します。
irbhoge.length9という結果がでたあなたは天才です。素晴らしい。
はい。この時の
length
がメソッドです。え?そんなの知ってるって?
さすがです。あなたはもう初心者ではないでしょう。次はこちら
irbclass User def name 'hoge' end end次に以下のコードを実行します。
irbuser = User.new user.name
"hoge"
という結果がでたあなたは天才です。素晴らしい。
はい。この時のname
がメソッドです。わかった!と思ったあなたはもう次のステップに進んでいます。この記事を読み続ける必要はないでしょう。
ん?と思ったらもうちょっと読んでみてください。
今実行したのは、
Stringクラス
のlengthメソッド
Userクラス
のnameメソッド
の2つです。
lengthメソッド
については下記のURLを参考にどうぞ。
String#length (Ruby 2.7.0 リファレンスマニュアル)
Stringクラス
のlengthメソッド
はあらかじめRubyに組み込まれているものです。オブジェクトの文字長を返します。
Userクラス
のnameメソッド
は今回自分で生み出したものということになります。こちらは中身がhogeでもfugaでもいいのです。これらはどちらも
インスタンスメソッド
になります。それぞれのクラスのインスタンスに対してくっつけて使います。
Hogeクラス
のインスタンスはHoge.new
で作れますね。
User
とかHoge
とかに対して直接くっつけて使うメソッドはクラスメソッド
と言います。違いはこれだけです。自分で考えたメソッドを書く
初めはこれがすごく難しいものであると勘違いしていました。
でも概念がわかればすごく便利に使えます。今回書いたのはname
で中身はhogeだけでしたが、いろんな処理をまとめて書いておくことでそのメソッドを一発叩けば実行することができるようになります。例えば(今回は引数も使っちゃいましょう)
irbclass Number def check(a, b) if a == 2 a * b elsif a == b a / b else a + b end end endこれで
Numberクラス
のcheckメソッド
を実行しましょう。irbnum = Number.new num.check(1, 2) num.check(2, 2) num.check(3, 3)引数によって計算式が変わるメソッドですね。簡単なものでも
irb
を使って色々書いて実行してみるのがいいと思います。引数については今のでしっくりきたでしょうか。
クラスメソッド
はこの最たるもので、バッチ処理をする時には大活躍します。まさに一撃!という感じです。バッチ処理ってなんやねん!と思った方はこちら
要は溜めてまとまった処理をシステムの裏側で実行する仕組みです。
最後に
ここまで読んで、わかんない!という方。本当にすみません。それはこの記事の分かりにくさです。もっと分かりやすく書けるように勉強します。
ちなみに今この瞬間にメソッドについてよくわかってなくても、
irb
やコンソールでさっき出てきたlength
が使えれば問題ないです。そのうち分かります。あなたが分かった時や詳しくなった時には、その時に初心者の方に優しく教えてあげましょう。最後まで読んでいただきありがとうございました。
- 投稿日:2020-10-13T21:32:59+09:00
Rubyで三角形を出力
本日授業で初めてRubyとやらを触ったので記念に記録。
○の出力のみで以下のような三角形をつくるという問題。
○
○○○
○○○○○
○○○○○○○n = gets.to_i #入力 for x in 1..n (n-x).times{print(" ")} # 空白の数はn-1した数から1段につき1つずつ減っていく for y in 1..2*(x-1)+1 # ○の数は2*(x-1)+1 print("○") end puts endはじめに、丸の左側にできている空白を出力し、それに続いて丸を出力する処理をします。そして、丸の出力が終わったらputsで改行をするという流れでプログラムを書きました。
左側にできる空白の数は一段目はn-1であり、それ以降-1されていきます。
○の数は、2(x-1)+1で求められます。
以上をプログラムに落とし込むと、無事、出力ができました。やはり言語が違えば仕様も違うので戸惑いますが早く慣れていきたいです
- 投稿日:2020-10-13T21:21:56+09:00
link_toメソッドのpathの引数、要る・要らない
はじめに
アプリケーションを作るときに、いつもlink_toメソッドでエラーが出ていた。しかも、そのリンク先に飛ぶときではなく、link_toメソッドがあるページを表示させたときに、
ActionController::UrlGenerationError
このエラーが出ていて、悩まされた。いつも○○_path
と、ルーティングを確認して記述するところまでは問題がなく、躓かない。ここに( )で引数を渡すとなると、何を渡したらいいのか分からなくなっていた。引数がなくてもOKなパターン
アプリケーションを利用する誰もが同じページに飛ぶ場合は引数がなくてもよい。ログインページやroot_pathのページがこれにあたる。
やっぱりrails routesは便利だった
ターミナルでカレントディレクトリが作成中のアプリケーションのディレクトリで
% rails routesを入力すると、ルーティングを教えてくれる。
pathの記述はもちろん、Prefixの部分を見る。しかし、
ここで着目すべきは、URI Patternの部分。ここで/:idなど、idがURIに含まれている場合は、引数を渡す必要がある。
:idとidがURIに含まれている場合は、引数に(user.id)などとすればよい。
また、引数によっては、.idを省略できる場合もある。
- 投稿日:2020-10-13T20:58:13+09:00
【Rails】検索ボックスの作成
手順
ルーティングの設定
コントローラーの設定
viewファイル:searchの作成ルーティングの設定
profilesのルーティングにsearchを追加。
rutes.rbresources :profiles do get :search, on: :collection endsearch_profiles GET /profiles/search(.:format) profiles#searchコントローラーの設定
今回は:nameについて部分一致するケースを想定。
controller.rbdef search if params[:name].present? # 部分一致 @profiles = Profile.where('name LIKE ?', "%#{params[:name]}%") else @profiles = Profile.none end endviewの作成
search.html.erb<h1>検索ボックス</h1> <%= form_with url: search_profiles_path, method: :get, local: true do |f| %> <%= f.text_field :name %> <%= f.submit :search %> <% end %> <h1>検索結果</h1> <% @profiles.each do |profile| %> <ul> <li><%= profile.name %><span><%= link_to "詳細", profile_path(profile) %></span></li> </ul> <% end %>
- 投稿日:2020-10-13T20:50:17+09:00
中高生6人でサービスを作ってプログラミングスクールのコンテストで1位を取った話
今回は、中学生1人、高校生5人でサービスのアイディアから実装まで行い、Life is Tech!という中高生向けのプログラミングスクールのコンテストでWEB部門1位になって、思ったこと、感じたことをお話ししたいと思います。
0. メンバー
メンバーは中学3年生〜高校3年生までの中高生で、中学生が1人の高校生が5人のチームで開発を行いました。
女の子が3人で男の子が3人で、学生のエンジニアのチームにしては女の子の比率が高いチームですが、普段からみんなすごく仲が良く、学校の放課後や休日に遊びに行ったり、ご飯食べたりする仲です。
(チームのお気に入りは釣りですが、どっかのウイルスのせいで最近は遊びに行けてません...ぴえん...)1. どのようなサービスを作ったのか。
今回作成したサービスはAssemble Tempoという開発者達とチーム戦で戦う、新しい形の開発時間記録サービスです。
※開発段階の画面です。『モチベーションを継続させるサービスを作る』という目標を設定して、どのようにすればモチベーションを継続させることができるか?とチームで考えた際に、ゲーム形式のサービスにしようという話になり、考えつきました。
次にどのようなゲームにするか、チーム内で話し合ったのですが、開発時間をチーム戦で競えばモチベーションを継続できるのでは、という話になり、チーム戦で開発時間を競うサービス作ることにしました。
2. 使用したプログラミング言語とサービス
プログラミング言語
プログラミング言語: Ruby, Javascript
フレームワーク: Sinatra
開発環境用DB: sqlite3
本番環境用DB: PostgreSQLこれらを採用した理由は、Life is Tech!のWebサービスコースで採用されているため、メンバーの大半が使用したことがあったり、教科書などがあるため、わからなくても教育が簡単だと判断したためです。
サービス
チーム開発を行う上で様々なサービスを使用しました。
まず、チームのコミュニケーションとして、Google HangoutsとSlackを使用しました。
Slackでは、コードに関する質問から新しいアイディア、完成した部分のフィードバックなどを行いました。Google Hangoutsは某ウイルスの感染防止対策としてオンライン会議をする際に使いました。
コードの共有や管理にはGithubをプロジェクトのタスク管理にはTrelloを使用しました。
Trelloはメンバー同士で話し合って、どのように進めていくかを話し合い、ラベルを使って、優先度や難しさなどを表示しました。
3. 実装について。
実装は、フロントエンドとバックエンドのチームに別れて実装を行いました。
フロントエンド
まず初めにどのような画面が必要かをメンバーで話し合い、仮のフレームを作成しました。
※グループディスカッションを行った際の写真です。次に、ある程度必要な画面などが決まってきたらXDを使用して、フレームを作成しました。
※レスポンシブ版です。バックエンド
バックエンドもフロント同様に、どのようなシステムを使うか、どのような実装を行うか、メンバーで話し合い実装しました。
バックエンドの主な機能
ユーザ認証・メール確認機能
グラフの計算・グラフのリアルタイム更新(Server Send events)
グループ分け機能
アイコン機能
タイマー機能が主な機能です。
その中でも、実装に時間がかかった、Server Send eventsとタイマー機能に関して説明をしたいと思います。
Server Send events
Server Send eventsはhttpを使用して、リアルタイム通信を行う技術のことで、サーバからクライアントへのPushとして使えます。
WebSocketとの違いは、主にクライアントからサーバへの送信ができないことです。(代わりにAjaxを使用しています)Server Send eventsはSinatraでのライブラリがなく、一から実装をしないといけないため、時間がかかりました。
rubyset :server, 'thin' $connections = [] get '/send_message' do message = "メッセージです。" $connections.each do |sse| sse << "retry: 500\n" + "event: event\n" + "data: #{message}\n\n" unless sse.closed? end end get '/sse', provides: 'text/event-stream' do stream :keep_open do |sse| $connections << sse graph_data.callback { $connections.delete(sse) } end end※Qiita用に変更しています
タイマー機能
タイマー機能は、タイマー用のテーブルを用意します。
新規作成は、テーブルにユーザのデータが無い場合はタイマーを作成します。
テーブルに、ユーザのデータがある場合は、タイマーを終了するようにしました。ruby# データベースに既に、データがあるか確認 if time = Timers.find_by(ユーザのID: session[:ユーザのセッション], 始まりの時間: now_time.all_day, 終わりの時間: nil) # 開発終了した時間と開発時間をDBに保存 Timers.update(終わりの時間: now_time) else # タイマーを新規作成 Timers.create(ユーザのID: session[:ユーザのセッション], 始まりの時間: now_time) end※Qiita用に変更しています
4. チーム開発の感想
今回初めて、バックエンドの開発をするメンバーがいたり、メンバーのほとんどがGitを使ったことが無かった中で、リリースをできたことは、すごく嬉しかったです。
学んだこと。
一番学べたと思ったところは、機能を部分部分に分けてメンバーにお願いするところです。(PM)
メンバーによって、書ける言語や使える技術などが違うためそれを把握して、メンバーにお願いするところがすごく勉強になりました。
使ったことないような技術でも、これならできるかな?など考えながら、メンバーに機能の実装をお願いしました!!他にも、メンバーのわからないところなどを教えることによって、アウトプットがたくさんできて、僕も知らなかったことなどを学ぶことができました。
大変だったこと。
大変だったことは、たくさんあります。
まず、チーム開発で一番重要である、コードの管理・共有のGitを使えるメンバーが僕しかいなく、Gitを教えるのが大変でした。次に、学生特有の問題なのですが、みんな学校が違うため、予定が合わずディスカッションなどみんなで話し合う機会が少なく、大変でした。
他にも、テスト期間などになるとみんな返信がなくなり、ちゃんとリリースできるか心配でした。メンバーに対して思ったこと。
チーム開発がするのが初めてだったと思うので、最初の方はGitがわからなかったり、大変だったと思います。
でも、みんなちゃんとついてくれてすごくいい作品ができたなと思いました。最初の方は、「メンバーに迷惑かけちゃうかも」など言ってたメンバーも最後は「リリースできてよかった!」や「楽しかった!!」など言っていたので、僕は嬉しかったです。
プログラミングの技術の方も、上がっていて「Ruby全然わかんない!!」と言ってたメンバーがRubyを書けるようになったり、DB(ActiveRecord)を使えるようになったメンバーなどがいました!!
メンバーも技術があがったと実感しているみたいで、それを実感できるほど成長できたのはすごいと思いました。5. 最後に
僕もメンバーも初めてが多かった今回のチーム開発ですが、コンテストには間に合い、1位を取れて嬉しかったです。
今回のチーム開発でPMや開発環境、サポート、実装面で反省することはたくさんありましたが、今後の開発などに生かしていけるといいなと思いました。今後、どのような機能を実装するかなどの話し合いをしており、アップデートをしていく予定なのでサービスを使って、開発のモチベーションなどを高めてもらえると嬉しいです!!
- 投稿日:2020-10-13T18:23:00+09:00
[Rails]deviseの導入
はじめに
deviseとは、ユーザー管理機能を簡単に実装するためのgemです。
目次
1.deviseのインストール
2.deviseの設定ファイルを作成
3.モデルの作成
4.テーブルの作成
5.ビューの編集
6.コントローラーの編集1. deviseのインストール
gemfileに以下を記述します。
gemfilegem 'devise'アプリのディレクトリで以下を実行します。
ターミナル
bundle installgemをインストールした後はサーバーを再起動します。
サーバーを再起動することでgemが反映されます。ターミナル
rails s2. deviseの設定ファイルを作成
deviseを使用するためには、gemのインストールに加え、 devise専用のコマンドで設定ファイルを作成する必要があります。
以下を実行することで、追加したdeviseというgemの「設定関連に使用するファイル」を自動で生成することができます。ターミナル
rails g devise:install3. モデルの作成
deviseを利用する際には、アカウントを作成するためのUserモデルを新しく作成する必要があります。
作成には通常のモデルの作成方法ではなく、deviseのモデル作成用コマンドでUserモデルを作成します。ターミナル
rails g devise userまた、rails g deviseコマンドによりモデルやマイグレーションを自動生成するだけでなく、routes.rbにルーティングも自動的に追加されます。
4. テーブルの作成
必要なカラムを追加する場合は、マイグレーションファイルに記述し以下を実行します。
ターミナル
rails db:migrate5. ビューの編集
カラムを追加した場合は、追加したカラムを入力できるように、新規登録画面のビューを編集する必要があります。
デフォルトでは、deviseのビューファイルは隠れているので、以下を実行します。ターミナル
rails g devise:views6. コントローラーの編集
また、コントローラーを編集したい場合は以下を実行することでdevise管理下のコントローラーを作成することができます。
ターミナル
rails g devise:controllers users
- 投稿日:2020-10-13T17:56:50+09:00
筆者がエラーに苦しんだ備忘録【bundler: failed to load command: unicorn NameError: uninitialized constant Model】
初めに
この問題は解決済みです。
多分特例すぎて誰の参考にもならないです。
質問フォーマットに記入してたら、エラーの原因に気づいて解決しました。
筆者の備忘録として残してあります。感想
エラー文を全部読みましょう。
でも、bundler: failed to load command: unicorn
って言われたら、unicorn疑っちゃう。。。
一行下のNameError: uninitialized constant Model
が超大事でした。
なんでローカル環境で起動しちゃうんですか〜
せめてエラー検知してくれ〜〜前提・実現したいこと
Railsで開発したアプリをCapistranoを使用してデプロイしようとしましたが、
unicorn:startコマンドで必ず失敗します。
エラーを解決して、正しくunicornが起動できるようなりデプロイすることがゴールです。発生している問題・エラーメッセージ
以前、capistranoでデプロイできていたのですが、1週間ほど空いた後にデプロイしたら、今回のエラーが発生しました。
デプロイしてない間に一部ソースコードは編集しました。capistranoのエラー文
00:52 unicorn:start 01 $HOME/.rbenv/bin/rbenv exec bundle exec unicorn -c /var/www/MyNote/current/config/unicorn.rb -E deployment -D 01 master failed to start, check stderr log for details #<Thread:0x00007fbbfb37a690@/Users/ohishikaido/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/sshkit-1.21.0/lib/sshkit/runners/parallel.rb:10 run> terminated with exception (report_on_exception is true): Traceback (most recent call last): 1: from /Users/ohishikaido/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/sshkit-1.21.0/lib/sshkit/runners/parallel.rb:11:in `block (2 levels) in execute' /Users/ohishikaido/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/sshkit-1.21.0/lib/sshkit/runners/parallel.rb:15:in `rescue in block (2 levels) in execute': Exception while executing as ec2-user@54.150.220.39: bundle exit status: 1 (SSHKit::Runner::ExecuteError) bundle stdout: Nothing written bundle stderr: master failed to start, check stderr log for details (Backtrace restricted to imported tasks) cap aborted! SSHKit::Runner::ExecuteError: Exception while executing as ec2-user@54.150.220.39: bundle exit status: 1 bundle stdout: Nothing written bundle stderr: master failed to start, check stderr log for details Caused by: SSHKit::Command::Failed: bundle exit status: 1 bundle stdout: Nothing written bundle stderr: master failed to start, check stderr log for details Tasks: TOP => unicorn:start (See full trace by running task with --trace) The deploy has failed with an error: Exception while executing as ec2-user@54.150.220.39: bundle exit status: 1 bundle stdout: Nothing written bundle stderr: master failed to start, check stderr log for details ** DEPLOY FAILED ** Refer to log/capistrano.log for details. Here are the last 20 lines: 〜省略〜 DEBUG [2632c234] Finished in 0.563 seconds with exit status 0 (successful). DEBUG [b61a7332] Running [ -e /var/www/MyNote/shared/tmp/pids/unicorn.pid ] && kill -0 `cat /var/www/MyNote/shared/tmp/pids/unicorn.pid` as ec2-user@54.150.220.39 DEBUG [b61a7332] Command: [ -e /var/www/MyNote/shared/tmp/pids/unicorn.pid ] && kill -0 `cat /var/www/MyNote/shared/tmp/pids/unicorn.pid` DEBUG [b61a7332] bash: 0 行: kill: (21662) - そのようなプロセスはありません DEBUG [b61a7332] Finished in 0.565 seconds with exit status 1 (failed). INFO [d82915ac] Running $HOME/.rbenv/bin/rbenv exec bundle exec unicorn -c /var/www/MyNote/current/config/unicorn.rb -E deployment -D as ec2-user@54.150.220.39 DEBUG [d82915ac] Command: cd /var/www/MyNote/current && ( export RBENV_ROOT="$HOME/.rbenv" RBENV_VERSION="2.5.1" RAILS_ENV="production" ; $HOME/.rbenv/bin/rbenv exec bundle exec unicorn -c /var/www/MyNote/current/config/unicorn.rb -E deployment -D ) DEBUG [d82915ac] master failed to start, check stderr log for details本番環境(EC2内) /var/www/アプリ名/shared/log/unicorn.stderr.logに表示される内容
I, [2020-10-13T08:34:14.025904 #12943] INFO -- : Refreshing Gem list bundler: failed to load command: unicorn (/var/www/MyNote/shared/bundle/ruby/2.5.0/bin/unicorn) NameError: uninitialized constant Model /var/www/MyNote/shared/bundle/ruby/2.5.0/gems/bootsnap-1.4.6/lib/bootsnap/load_path_cache/core_ext/active_support.rb:80:in `block in load_missing_constant' /var/www/MyNote/shared/bundle/ruby/2.5.0/gems/bootsnap-1.4.6/lib/bootsnap/load_path_cache/core_ext/active_support.rb:9:in `without_bootsnap_cache' /var/www/MyNote/shared/bundle/ruby/2.5.0/gems/bootsnap-1.4.6/lib/bootsnap/load_path_cache/core_ext/active_support.rb:80:in `rescue in load_missing_constant' /var/www/MyNote/shared/bundle/ruby/2.5.0/gems/bootsnap-1.4.6/lib/bootsnap/load_path_cache/core_ext/active_support.rb:59:in `load_missing_constant' /var/www/MyNote/releases/20201013083325/app/controllers/users/registrations_controller.rb:3:in `<top (required)>' 〜省略〜解決した経緯
unicorn.stderr.logの確認。
コピペして貼り付けた時に原因に気づきました。
めっちゃくちゃしれーっと書いてありますね!!!!!
/var/www/MyNote/releases/20201013083325/app/controllers/users/registrations_controller.rb:3:in `<top (required)>'
おまえかーい!!!
僕の4時間と心の焦りを返してください。泣原因のソースコード
users/registrations_controller.rbclass Model::RegistrationsController < Devise::RegistrationsController endそりゃ確かに
NameError: uninitialized constant Model
になりますわ。。
Modelクラスなんて存在しませんからねー補足情報(FW/ツールのバージョンなど)
Ruby2.5.1
Rails5.2.4.2
unicorn 5.4.1
AWS EC2 Amazon linux AMI
- 投稿日:2020-10-13T17:21:32+09:00
Rails で LTI 認証を実装する
LTI 認証とは
LTI認証という規格があります。
LTIとはLearning Tools Interoperability という単語の頭文字で、要するに学習支援ツール間で認証情報をやり取りする際の規格という意味です。認証技術の中でも分野が特定されているかなりニッチな技術なので、知らない方も多いんではないでしょうか。僕も教育工学を専門にする前はLTIという単語すら知りませんでした。
以下にIMS GLOBAL から公式に出されているLTI認証の説明図をのっけて置きます。
個人的には、結局OAuthの一種と理解しているのですが、我々が開発するアプリケーションを Learning Tools, 認証の基盤となる大本のツールを Learning Platform として、Learning Tools は Learning Platform の拡張機能を提供する代わりに、認証情報を Learning Platform からもらいます。これによってユーザーは様々なアプリをユーザーを切り替えることなしに、使い分けることができるという利点があるわけです。このとき、Learning Toolsのほうを LTI Tool Provider, Learning Platformのほうを LTI Consumer と呼んだりもします。
ただ、問題はこれをどう実装するかです。実際、ニッチな技術ゆえにドキュメンテーションに乏しく、ネット上を探しても実装例はあまり公開されていません。そこで今回、この記事では Ruby on Rails を使った LTI 認証の実際について紹介したいと思います。
実装例
ライブラリのインストール
まずは、必要なライブラリをインストールします。
$ bundle add devise $ bundle add ims-lti $ bundle add oauthRails を使うメリットは lti 認証のためのライブラリがあるところです。今回は
ims-lti
を使って実装します。認証キーの登録
config
配下にlti_settings.yml
ファイルを作成します。
内容は以下の内容を記載してください(コンシューマーキー、LTIシークレットは適宜安全な文字列を使用してください)。config/lti_settings.ymlproduction: __consumer_key__: '__lti_secret__' development: __consumer_key__: '__lti_secret__'作成したら、これを読み込むための設定を
config/application.rb
に追加します。config/application.rbconfig.lti_settings = Rails.application.config_for(:lti_settings)コントローラーの作成
ltis_controller
を作って以下の内容を記載しましょうrequire 'oauth/request_proxy/action_controller_request' class LtisController < ApplicationController skip_before_action :verify_authenticity_token, only: :launch def lti_launch # 受け取った consumer key が config/lti_settings.yml の中にあるかどうかを確認 if not Rails.configuration.lti_settings[params[:oauth_consumer_key]] render :launch_error, status: 401 return end shared_secret = Rails.configuration.lti_settings[params[:oauth_consumer_key]] authenticator = IMS::LTI::Services::MessageAuthenticator.new(request.url, request.request_parameters, shared_secret) #Check if the signature is valid if not authenticator.valid_signature? render :launch_error, status: 401 return end #check if the message is too old if DateTime.strptime(request.request_parameters['oauth_timestamp'],'%s') < 5.minutes.ago render :launch_error, status: 401 return end # LTI 情報をsessionに保存 session_data = { "fullname" => authenticator&.message&.lis_person_name_full, "email" => authenticator&.message&.lis_person_contact_email_primary, "user_id" => authenticator&.message&.user_id, "context_id" => authenticator&.message&.context_id, "context_title" => authenticator&.message&.context_title, "tool_consumer_instance_name" => authenticator&.message&.tool_consumer_instance_name } print(session_data) session['lti-authenticator'] = session_data sign_in_and_redirect(User.first) end end
MessageAuthenticator
にわたってきたリクエストと事前にこちらで保持しているキーの情報を渡すことで簡単に認証ができます。認証が成功したら、devise
ライブラリを使ってsign_inすることで、アプリ側での認証を実装しています。最後に
lti_launch
を起動するためのエンドポイントを定義しておきましょう。config/routes.rbmatch 'lti/launch' => 'ltis#lti_launch', via: [:get, :post], as: :lti_launchLearning Platform 側での設定
ここまでできたら、あとは Learning Platform 側で事前に
lti_settings.yml
に記載した認証情報を書いて指定したエンドポイントに遷移するように設定すれば完成です。このやり方は個々のLearning Platformによって異なるので割愛します。(補足)LTI 遷移時に Rails で cross origin error が出たら
config/application.rb
に以下の内容を追記してくださいconfig/application.rbconfig.lti_settings = Rails.application.config_for(:lti_settings) config.action_dispatch.default_headers['Referrer-Policy'] = 'unsafe-url' config.action_controller.forgery_protection_origin_check = false config.action_controller.allow_forgery_protection = false参考文献
- 投稿日:2020-10-13T16:11:19+09:00
デプロイ後に背景画像が適用されない場合の対処法
この記事を書いた背景
デプロイしたら背景画像が表示されない!
調べたら結構そういう人いたため。実施環境
macOS Catalina 10.15.7
VS Code 1.50.0
Ruby 2.6.5
Rails 6.0.0
サーバー:AWS EC2
WEBサーバー:Nginx
アプリケーションサーバー:unicorn 5.4.1対処法
僕はこれでいけました。
デプロイ後、本番に上がったアプリ等で背景画像が表示されます。①背景画像は『/app/assets/images』フォルダに格納する
②背景画像を指定するCSSの種類を『SCSS』にする
③背景画像を指定するCSSの記述『background-image: image-url("画像名");』
scss/*例*/ body { background-image: image-url("wallpaper.jpg"); }※この記述だと逆にローカル環境で背景画像が表示されない...笑
- 投稿日:2020-10-13T15:58:31+09:00
アプリをもっと良くしよう
コメント機能の追加
Commentのscaffoldをする
Commentの著者名、コメント本文、Ideaテーブルへの関係(
reference
)をscaffoldします。
rails generate scaffold comment user_name:string body:text idea:reference
マイグレーションをします。
rails db:migrate
モデルに関係(relation)を追加する
Ideaとcommentオブジェクト間の接続をRailsに認識させます。
app/models/idea.rbclass Idea < ApplicationRecord has_many :commentsapp/models/comment.rbclass Comment < ApplicationRecord belongs_to :ideaコメントフォームの表示と編集
app/views/ideas/show.html.erb<p> <strong>Picture:</strong> <%= image_tag(@idea.picture_url, width: 600) if @idea.picture.present? %> </p> <h3>Comments</h3> <% @comments.each do |comment| %> <div> <strong><%= comment.user_name %></strong> <br /> <p><%= comment.body %></p> <p><%= link_to 'Delete', comment_path(comment), method: :delete, data: { confirm: '削除してもよろしいですか?' } %></p> </div> <% end %> <%= render 'comments/form', comment: @comment %>app/controllers/ideas_controller.rbdef show @comments = @idea.comments.all @comment = @idea.comments.build endapp/views/comments/_form.html.erb<div class="field"> <%= form.label :body %> <%= form.text_area :body %> </div> <%= form.hidden_field :idea_id %>最後に次の行を削除します。
app/views/comments/_form.html.erb<div class="field"> <%= form.label :idea_id %> <%= form.number_field :idea_id %> </div>HTML&CSSを使ってデザインしましょう
アプリケーションのレイアウトを適用する
app/assets/stylesheets/application.cssbody { padding-top: 100px; }上の行を以下のように書き換えます。
app/assets/stylesheets/application.cssbody { padding-top: 60px; }最後に
app/assets/stylesheets/scaffolds.scss
を削除します。ナビゲーションを良くしよう
"New Idea"ボタンをナビゲーションに常に表示します。
app/views/layouts/application.html.erb<li class="active"><a href="/ideas">Ideas</a></li> <li><%= link_to 'New Idea', new_idea_path %></li>アイデアリストのデザイン
以下のように書き換えます。
app/views/ideas/index.html.erb<h1>Listing ideas</h1> <% @ideas.in_groups_of(3) do |group| %> <div class="row"> <% group.compact.each do |idea| %> <div class="col-md-4"> <%= image_tag idea.picture_url, width: '100%' if idea.picture.present? %> <h4><%= link_to idea.name, idea %></h4> <%= idea.description %> </div> <% end %> </div> <% end %> <h2>Ideaの詳細ページをデザイン</h2> 以下のように書き換えます。 ```app/views/ideas/show.html.erb <p id="notice"><%= notice %></p> <div class="row"> <div class="col-md-9"> <%= image_tag(@idea.picture_url, width: '100%') if @idea.picture.present? %> </div> <div class="col-md-3"> <p><b>Name: </b><%= @idea.name %></p> <p><b>Description: </b><%= @idea.description %></p> <p> <%= link_to 'Edit', edit_idea_path(@idea) %> | <%= link_to 'Destroy', @idea, data: { confirm: 'Are you sure?' }, method: :delete %> | <%= link_to 'Back', ideas_path %> </p> </div> </div>
```Carrierrwaveを使ったサムネイルの表示
ImageMagickのインストール
brew install imagemagick
を実行します、gem 'carrierwave'の下に、
gem 'mini_magick'を追加します。その後、以下のコマンドを実行します。
bundle
画像をアップロードしたときにサムネイルを作成する
app/uploaders/picture_uploader.rb# include CarrierWave::MiniMagick version :thumb do process :resize_to_fill => [50, 50] end上の
#
を削除します。サムネイルの作成
app/views/ideas/index.html.erb<%= image_tag idea.picture_url, width: '100%' if idea.picture.present? %>を以下のように変更します。
app/views/ideas/index.html.erb<%= image_tag idea.picture_url(:thumb) if idea.picture.present? %>Deciceで認証機能を追加
devise gemを追加
gem 'devise'を追加します。次に以下のコマンドをターミナルで実行します。
bundle
アプリにdeviseをセットアップ
以下のコマンドを実行します。
rails generate devise:installDeviceの環境設定
environmentファイルにデフォルトのurlオプションを追加します。
config/environments/development.rbconfig.action_mailer.default_url_options = { host: 'localhost:3000' }
end
の前に追加します。app/views/layouts/application.html.erb<% if notice %> <p class="alert alert-success"><%= notice %></p> <% end %> <% if alert %> <p class="alert alert-danger"><%= alert %></p> <% end %> <%= yield %>さらに上の行を追加します。
また、以下を削除します。
app/views/ideas/show.html.erb<p id="notice"><%= notice %></p>同じように
app/views/comments/show.html.erb
でも削除します。
なぜなら、app/views/layouts/application.html.erb
に同じ行を追加したためです。Userモデルのセットアップ
User modelを作るためにbundled generator script を使います。
rails generate devise User rails db:migrateサインアップとログインリンクの追加
ユーザーがログインできる適切なリンク、または案内をナビゲーションバー右上のコーナーに追加する。
app/views/layouts/application.html.erb<p class="navbar-text pull-right"> <% if user_signed_in? %> Logged in as <strong><%= current_user.email %></strong>. <%= link_to 'Edit profile', edit_user_registration_path, class: 'navbar-link' %> | <%= link_to "Logout", destroy_user_session_path, method: :delete, class: 'navbar-link' %> <% else %> <%= link_to "Sign up", new_user_registration_path, class: 'navbar-link' %> | <%= link_to "Login", new_user_session_path, class: 'navbar-link' %> <% end %> </p> <ul class="nav navbar-nav"> <li class="active"><a href="/ideas">Ideas</a></li> </ul>最後にログインしていない時に登録した内容を確認できないようにする。
app/controllers/application_controller.rbbefore_action :authenticate_user!
end
の前に追加します。Gravatarでプロフィール写真を追加
Gravtastic gemを追加
gem 'gravtastic'これを
devise
の下に追加します。Terminalで、次のコマンドを実行します。
bundleGravatarをセットアップ
最後の行の下に次を追加します。
app/models/user.rbinclude Gravtastic gravtasticGravatarを設定する。
app/views/layouts/application.html.erb<% if user_signed_in? %>のなかに,以下のようになるように書き換えます。
app/views/layouts/application.html.erb<% else %> <%= image_tag current_user.gravatar_url %>さらにデザインしよう
headerのデザイン
app/assets/stylesheets/application.cssnav.navbar { min-height: 38px; background-color: #f55e55; background-image: none; } .navbar a.brand { font-size: 18px; } .navbar a.brand:hover { color: #fff; background-color: transparent; text-decoration: none; }tableのデザイン
以下のように書き換えます。
app/views/ideas/index.html.erb<table class="table">以下のコードを使って、画像のサイズを調整します。
<%= image_tag(idea.picture_url, width: 600) if idea.picture.present? %>
app/assets/stylesheets/ideas.scss
の最後に以下を追加します。app/assets/stylesheets/ideas.scss.container a:hover { color: #f55e55; text-decoration: none; background-color: rgba(255, 255, 255, 0); }footerにスタイルを追加
app/assets/stylesheets/application.cssfooter { background-color: #ebebeb; padding: 30px 0; }buttonにスタイルを追加
app/assets/stylesheets/ideas.scs.container input[type="submit"] { height: 30px; font-size: 13px; background-color: #f55e55; border: none; color: #fff; }
- 投稿日:2020-10-13T15:05:40+09:00
Railsでコントローラーの単体テストコード時に「302」のエラーが出た時の対処法
はじめに
前回の記事の続きってわけでも無いのですが、似たような内容にはなっています。
それと「302」のエラーの中のあくまでも1例ですのでよろしく御願い致します。エラー内容
それではまずはコントローラーの単体テストコード実装時に下記のようなエラーが出ました。
ご覧くださいターミナル% bundle exec rspec spec/requests/orders_spec.rb OrdersController GET /index indexアクションにリクエストすると正常にレスポンスが返ってくる (FAILED - 1) indexアクションにリクエストするとレスポンスに出品済みの商品の説明文が存在する (FAILED - 2) Failures: 1) OrdersController GET /index indexアクションにリクエストすると正常にレスポンスが返ってくる Failure/Error: expect(response.status).to eq 200 expected: 200 got: 302 (compared using ==) # ./spec/requests/orders_spec.rb:24:in `block (3 levels) in <top (required)>' 2) OrdersController GET /index indexアクションにリクエストするとレスポンスに出品済みの商品の説明文が存在する Failure/Error: expect(response.body).to include @item.details expected "<html><body>You are being <a href=\"http://www.example.com/users/sign_in\">redirected</a>.</body></html>" to include "商品の説明" # ./spec/requests/orders_spec.rb:29:in `block (3 levels) in <top (required)>' 〜中略〜エラー内容の検証
それではエラー内容を検証していきたいと思います。
今回のエラーの原因となる該当箇所は2つあります。
まず1つ目は下記の部分です。ターミナル1) Failure/Error: expect(response.status).to eq 200 expected: 200 got: 302次に2つ目は下記の部分です。
ターミナル2) Failure/Error: expect(response.body).to include @item.details expected "<html><body>You are being <a href=\"http://www.example.com/users/sign_in\">redirected</a>.</body></html>" to include "商品の説明"エラー内容の検証
それではエラー内容の検証をしていきます。
- まず1つ目のエラーはexpectedで「200」(成功)を期待していますが実際に返ってきたレスポンスは「302」(Found)となっています。 ここで「302」(Found)についての詳しい説明を載せておきます。
302 (Found) エラーとは
「The HyperText Transfer Protocol (HTTP) の 302 Found リダイレクトステータスレスポンスコードは、リクエストされたリソースが一時的に Location で示された URL へ移動したことを示します。ブラウザーはこのページにリダイレクトしますが、検索エンジンはリソースへのリンクを更新しません 。」
上記を簡単に説明しますと「本来遷移したいページではなく違うページにリダイレクトされましたよ」という内容です。
(引用させて頂いた参考サイト)
HTTP レスポンスステータスコードについての参考サイト
- それでは次に2つ目のエラーですが自分が着目したポイントは下記の部分です。
<a href=\"http://www.example.com/users/sign_in\">redirected</a>.まず「users/sign_in」とあるのでログイン画面が関わっていると推測出来ます。そしてその次に「redirected」とあるのでここでもリダイレクトされたということが推測出来ます。
以上の検証内容から推測すると「リダイレクトでログイン画面に飛ばされたのかな?」と仮定することが出来ます。
ではそのような処理をしている箇所はと言うと「authenticate_user!」という部分が該当すると分かりました。ここで少し「authenticate_user!」について説明します。
authenticate_user!とは
処理が実行された時にユーザーがログインしていなければ、そのユーザーをログイン画面に遷移させます。という処理をしてくれるdevise用のメソッドです。
以上の点から自分はテストコード実行時は該当の「authenticate_user!」の箇所をコメントアウトすることにしました。
orders_controller.rbclass OrdersController < ApplicationController before_action :authenticate_user! (この行をコメントアウトする)
再度単体テストコードを実行
ターミナル% bundle exec rspec spec/requests/orders_spec.rb OrdersController GET /index indexアクションにリクエストすると正常にレスポンスが返ってくる indexアクションにリクエストするとレスポンスに出品済みの商品の説明文が存在する indexアクションにリクエストするとレスポンスに出品済みの商品の画像が存在する indexアクションにリクエストするとレスポンスに出品済みの商品の販売価格が存在する indexアクションにリクエストするとレスポンスに購入内容の確認の文言が存在する Finished in 5.79 seconds (files took 10.02 seconds to load) 5 examples, 0 failures上記の通り無事にテストコードを実行することが出来ました。
おわりに
今回のエラー(302)はコントローラーのテストコード実行時に「authenticate_user!」でログイン画面にリダイレクトされていたために起きたエラーでした。結合テストコードだとログインする処理は簡単なのですがコントローラーの単体テストコードの際にログイン出来るのか少し調べた限りではよくわかりませんでしたので今回はコメントアウトをすることで対処しました。
当記事内で参考にさせて頂いたサイト
- 投稿日:2020-10-13T11:19:42+09:00
【Ruby】ハッシュの取り出しについて
●●●問題●●●
puts hash.keys puts hash.values上記のメソッドを実行した時に
one two three 1 2 3とターミナルに表示されるような変数hashを作成するためのコードをシンボルを使って記述してください。
●●●回答●●●
hash{one:1,two:2,three:3}●●●解説●●●
まずはハッシュの構造から。
シンボルをつけるハッシュの記述方法は、キーの後ろにコロンをつけて定義する。{キー:値}また、ハッシュオブジェクトに対して、「オブジェクト.keys」とすることで、ハッシュのキーを取得。
「オブジェクト.values」とすることで、ハッシュの値を取得することができる。(例) hash{one:1} に対して hash.keys ⇨ one hash.values ⇨ 1よって、上記の回答となる。
- 投稿日:2020-10-13T09:39:12+09:00
【Rails】Gem gretelを用いたパンくずリスト作成
そもそもパンくずリストとは
パンくずリストとは下記の写真のようにページを階層順に配列し、ユーザーが操作時に現在どの位置にいるかを可視化したリストです。このようなリストを位置型パンくずリストと呼びます。
他にも属性型パンくずリストといいページを階層的に示したものでなく、そのページがどの種類のカテゴリに属しているかを示すリストもあります。属性型パンくずリストの例としてはECサイトが挙げられます。
パンくずリストを導入することによって主に下記の3点のメリットがあります。
・操作性の向上
→ユーザーがサイト内での位置情報を常に確認できる。滞在時間の向上
→パンくずリストにより階層毎の移動が容易になり回遊性が高まる。SEO効果
→パンくずリストによりクローラーの巡回をサポートする。gretelのインストール
【ドキュメント】
https://www.rubydoc.info/gems/gretel【GitHub】
https://github.com/lassebunk/gretelGemfileにて
gem 'gretel'記載後は下記を実行
$ bundle installこれでインストールは完了です。
設定
下記のコマンドでパンくずリストを設定するためのファイルを作成します。
$ rails generate gretel:installするとこのようなファイルが作成されます。
config/breadcrumbs.rbcrumb :root do link "Home", root_path end # crumb :projects do # link "Projects", projects_path # end # crumb :project do |project| # link project.name, project_path(project) # parent :projects # end # crumb :project_issues do |project| # link "Issues", project_issues_path(project) # parent :project, project # end # crumb :issue do |issue| # link issue.title, issue_path(issue) # parent :project_issues, issue.project # end # If you want to split your breadcrumbs configuration over multiple files, you # can create a folder named `config/breadcrumbs` and put your configuration # files there. All *.rb files (e.g. `frontend.rb` or `products.rb`) in that # folder are loaded and reloaded automatically when you change them, just like # this file (`config/breadcrumbs.rb`).今回ブログアプリの管理画面にパンくずリストを実装するので下記のように記載します。
config/breadcrumbs.rb#管理画面 crumb :root do link "Home", admin_dashboard_path end #記事(一覧) crumb :admin_articles do link "記事", admin_articles_path endコードの説明
config/breadcrumbs.rbcrumb :(設定ファイル) do link "(パンくずリストに表示される名前)", (呼び出し元のパス) endビューの設定
ここでbreadcrumbs.rbに記載したcrumb :admin_articles doが繋がります。
admin/articles/index.html.slim- breadcrumb :admin_articles下記を記載した箇所にパンくずリストが表示されます。
layouts/admin.html.slim
== breadcrumbs
親の設定
最後に下記のようにさらに階層を加えた表示方法を記載します。
config/breadcrumb.rbcrumb :root do link "Home", admin_dashboard_path end crumb :admin_articles do link "記事", admin_articles_path end crumb :edit_admin_article do link "記事編集", admin_articles_path parent :admin_articles end先ほど「記事」のパンくず追加に加えて今回は「記事編集」というパンくずを追加しました。
前回と異なる点は記事と記事編集を紐付けるために記事編集の欄にparent :admin_articlesを記載しております。最後にadmin/articles/edit.html.slimでもビューの設定を終えればパンくずの実装が可能になります。
参照したページの一覧
【ドキュメント】
https://www.rubydoc.info/gems/gretel【Flexible Ruby on Rails breadcrumbs plugin.(GitHub)】
https://github.com/lassebunk/gretel【gretelでパンくずリストを作成】
https://doruby.jp/users/kisuzuki/entries/gretel%E3%81%A7%E3%83%91%E3%83%B3%E3%81%8F%E3%81%9A%E3%83%AA%E3%82%B9%E3%83%88%E3%82%92%E4%BD%9C%E6%88%90
- 投稿日:2020-10-13T03:41:44+09:00
【Rails】 あいまい検索機能の付け方
経緯
現在絶賛作成中のポートフォリオで、フリマアプリのラクマの仕上げに検索機能をの実装したいと思い作成。さほど難しくはなかったけれども、色々記載しておこうと思います。
環境
ruby 2.6.5
Rails 6.0.3.2
haml使用イメージ図
手順
1、ルーティングの設定
2、検索フォームを作成
3、モデルに定義
4、コントローラーに設定
5、ビューの作成の5つの手順になります。
簡単なので、サックと出来ると思います。ルーティングの設定
今回は、7つの基本アクション以外のアクションを定義します。
7つの基本アクションとは、index
new
create
等のアクションの事ですね。
先ずは、コードからroutes.rbresources :items do collection do get 'search' end end説明ですが、
今回は先程言った通り7つの基本アクション以外で定義します。要は新しいアクションを作るみたいなイメージです。
その為のコードが、collection ~ end
の所です。
get の横のsearch
が新しいアクション名です。そして、
collection
ですが、ここはURLの指定先にidの必要の可否で変わります。
idの可とは、showアクションのような個々に登録されている商品の詳細ページなどに見にいく時にふられるものです(まぁ、ふられると言うと言葉のニュアンス的に違うのですが・・・)
なので、idなしで有ればcollection
idありで有ればmember となります。今回は、特定のページにいく必要がないため、
collection
を使用してルーティングを設定してます。
検索フォームを作成
先ずは、コードから
index.html.haml= form_with(url: search_items_path, local: true, method: :get, class: "search-form") do |f| = f.text_field :keyword, placeholder: "検索する", class: "search-input" %label{for: "search-icon", class: "search-label"} %i.fas.fa-search .search-icon = f.submit "検索", class: "search-btn", id: "search-icon"必要そうな所だけ説明します。
先ずは、urlの設定部分ですが、先程設定したsearchのルーティングで設定されるplefixを書きます。plefixをパスとして書く時は文字の最後に_pathをつけるような書き方をします。
調べ方は、ご存知だと思いますが、
ターミナルでrails routes
です。次に、まぁこれは無理に行う必要はないですが、上記の画像のように、ムシメガネ?みたいなアイコンとsubmit(送信ボタン)の紐付けについてです。
つまり、ムシメガネ?みたいなアイコンを押したら送信ボタンが押されるように設定していると言う事です。やり方は、label:for と id で紐付けます。
上記のコードで言うと、
これと%label{for: "search-icon", class: "search-label"}
これで= f.submit "検索", class: "search-btn", id: "search-icon"
です。
search-icon
って言う同じ名前がありますよね。これで紐付けされています。そして、今回は検索フォームに
f.text_field :keyword
と記述したので、このフォームに入力した値はコントローラーでparams[:keyword]
と書くことで取得する事ができます。
モデルに定義
ここも、コードから
item.rbdef self.search(search) return Item.all unless search Item.where('name LIKE(?)', "%#{search}%") end言い忘れましたが、今回はitemって言う名前でモデル等を作ってます。
説明します。
検索したキーワードが含まれている投稿を取得するために、whereメソッドとLIKE句を利用します。
whereメソッドは、モデル名.where('検索対象となるカラムを含む条件式')とする事でテーブル内の「条件に一致したレコードのインスタンス」を配列の形で取得できます。LIKE句は、曖昧(あいまい)な文字列の検索をするときに使用するもので、whereメソッドと一緒に使います。
詳細は、省きますが今回は、searchが含まれるnameカラムのデータを検索するものです。
詳しく知りたい方は、下記のリンク先が分かりやすいと思います。
【SQL】LIKE句の基本的な使い方~複数検索する場合の方法まで解説そもそも、searchって何?っと思われた方の向けに説明します。
要は引数の話です。
引数のsearch(1行目の(search)
)は、検索フォームから送信されたパラメーターが入ります。イメージしやすく言うと、検索フォームに みかん と入力して送信ボタンを押すとこの引数に みかん が入ると言う事ですね。
後は、文法の話です。
この引数にみかんというデータが入れば定義の中のsearchもみかんになるって訳です。つまり、このまま、みかんネタで言えば、itemテーブルのnameカラムにみかんと言う文字が入っているものを検索するって言う事です。
なので、言ってしまえば、1行目の(search)
はどんな単語でも良いって事ですね。次に、
return Item.all unless search
ですが、これは読んで字のごとくですが、
search(さっきので言えばみかん)と言う文字がなかったら他全てを出力すると言う意味です。そして、最後に1行目の
self.search
の説明です。
現時点だと、.search
というメソッドは使うことができません(この後コントローラーで定義するのに使います)
が、モデルで設定することにより、コントローラーで使用することができるようになります。そして、モデルの中でメソッドを定義する際には、メソッド名の頭にself.
を付けると事で、コントローラーで使えるクラスメソッドになります。以上で、モデルに定義は終了です。
コントローラーに設定
はたまた、ここもコードから
item_controller.rbdef search @items = Item.search(params[:keyword]) end
@items = Item.search(params[:keyword])
のコードは、
上記で述べてきた、今迄の説明で事足りるかと思うので省略します。
ビューの作成
検索結果画面のビューの作成ですが、
ここは、search.html.haml
と言うファイルを作成して、
eachメソッドを使って出力すればオッケーかと思います。search.html.haml.contents__box - @items.each do |item| ここより下は今自分が作っているものに照らし合わせて作成お願いします。これで、全ての実装が完了です!
実装出来なかったなどの不備が有ればご連絡ください!ありがとうございました。
- 投稿日:2020-10-13T00:23:24+09:00
RailsでCSVインポートする時、nkfコマンドを使ったらめっちゃ楽だった
RailsでCSVファイルをインポートするとき、こんな感じに実装してた。
def read_csv begin rows = CSV.read(file, encoding: 'UTF-8') rescue CSV::MalformedCSVError begin # csvファイルがUTF-8でない場合はShift_JISで読む rows = CSV.read(file, encoding: 'Shift_JIS') rescue CSV::MalformedCSVError, Encoding::InvalidByteSequenceError, Encoding::UndefinedConversionError # csvファイルがUTF-8・Shift_JISでもない場合 @error = 'ファイルのエンコードはUTF-8かShift_JISではありません。' end end rows&.shift # ヘッダーを削除する rows end問題点
例外処理が多くて面倒だし、そもそもインポートできる文字コード2つしかないとか…
解決策
どうやら
nkf
とかいうモジュールを使うとなんでも変換できそうだ…
https://docs.ruby-lang.org/ja/latest/class/NKF.html
- nkfをPCにインストール
brew install nkf
nkf -w --overwrite 変換したいファイルのpath
このコマンドを使えばいい感じに変換できそう。
- Railsの中にこのコマンドを組み込んでみる。
def read_csv(file) system("nkf -w --overwrite #{file.path}") rows = CSV.read(file) rows&.shift # 1行目のヘッダーを削除する rows endすっきりとしたコードになりました。
注意点
あらかじめ
brew install nkf
コマンド等でnkfをインストールしておかないと、nkf
コマンドが使えないので気をつけてください。