20210726のRubyに関する記事は17件です。

[Ruby]layoutsファイルと7つのアクション

はじめに 本記事は、本日私が理解できていなかった 「layouts」ファイルの中身について書きました。 今回は、これに何時間もかかりましたので、備忘録として投稿します。  layoutsファイルには 具体例 <!DOCTYPE html> <html> <head> 省略 </head> <body> <header class="header"> <div class="inner"> <div class="nav"> <div class="nav__left"> <%= link_to image_tag("logo.png", class: :logo), root_path %> </div> <% if user_signed_in? %> <div class="nav__right"> <%= link_to "ログアウト", destroy_user_session_path, method: delete, class: :nav__logout %> <%= link_to "New Proto", root_path, class: :nav__btn %> </div> <% else %> <div class="nav__right"> <%= link_to "ログイン", new_user_session_path, class: :nav__btn %> <%= link_to "新規登録", new_user_registration_path, class: :nav__btn %> </div> <% end %> </div> </div> </header> <%= yield %> <footer class="footer"> <p class="copyright">Copyright © ~~~ All rights reserved.</p> </footer> </body> </html> このように、 <html> <head></head> <body> <header></header> <footer></footer> </body> </html> という記述になるファイルになります。 つまり、ブラウザ上に表示されるものに直結すると考えても良いと思います。 勘違いしていたこと 当時、私は、「新規登録ボタン」からユーザー登録ができるようコードを書いておりましたが、 一向に新規登録画面に遷移することはありませんでした。 理由としては、 createアクションで、app>views>registrations>newのファイルにユーザーが情報登録するためのURLをコードに記述しただけだったためです。 <div class="main"> <div class="inner"> <div class="form__wrapper"> <h2 class="page-heading">ユーザー新規登録</h2> <%= form_with model: @user, url: user_registration_path, local: true do |f| %> 省略 </div> </div> </div> 原因 完全に理解していたと思われた 7つのアクションの役割を正確に理解していなかったことから、 このようなミスに繋がったと考えます。 改善策 ・再度、7つのアクションについての役割を分析する。 ・今後もこのようなことが起きないように注意する。 ・注意の方法として、7つのアクションそれぞれに関連深いものも確認しておく。 この3つに焦点を当てて、復習します。 終わりに 初心者がまず失敗してしまうミスという感じがします。 ここからは理解したことをさらに深く、 知識の肉付けをどんどん実施していきたいと思いました。 以上です。 引き続き頑張ります!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

meta-tagsについて

Gem meta-tags について 今回SEO対策として何か実装したいと考えて調べてみた所、meta-tagsというGemを知りましたので、実際に使ったので備忘録として記入したいと思います。 meta-tagsの導入 routes.rb Gem 'meta-tags' bundlerでインストール bundle exec これで導入完了です 各種設定 上記の作業を正常に完了してればconfig/initializers/meta_tags.rbという感じにファイルが生成されています。 meta-tagsの内容は下記の通りです。 meta_tags.rb # Use this setup block to configure all options available in MetaTags. MetaTags.configure do |config| # How many characters should the title meta tag have at most. Default is 70. # Set to nil or 0 to remove limits. # config.title_limit = 70 # When true, site title will be truncated instead of title. Default is false. # config.truncate_site_title_first = false # Maximum length of the page description. Default is 160. # Set to nil or 0 to remove limits. # config.description_limit = 160 # Maxumum length of the keywords meta tag. Default is 255. # config.keywords_limit = 255 # Default separator for keywords meta tag (used when an Array passed with # the list of keywords). Default is ", ". # config.keywords_separator = ', ' # When true, keywords will be converted to lowercase, otherwise they will # appear on the page as is. Default is true. # config.keywords_lowercase = true # List of additional meta tags that should use "property" attribute instead # of "name" attribute in tags. # config.property_tags.push( # 'x-hearthstone:deck', # ) end こちらの記述は「タイトルでも文字数制限などを設定できますが、デフォルトでも大丈夫らしいので、今回はこのままです。 各種サイトの条件に合わせて設定してください。 metaタグの初期設定をおこなうため、「app/helpers/application_helper.rb」にdefault_meta_tagsメソッドを実装します。 application_helper.rb module ApplicationHelper def default_meta_tags { site: 'サイト名', title: 'タイトル', reverse: true, charset: 'utf-8', description: 'description', keywords: 'キーワード', canonical: request.original_url, separator: '|', icon: [ { href: image_url('favicon.ico') }, { href: image_url('icon.jpg'), rel: 'apple-touch-icon', sizes: '180x180', type: 'image/jpg' }, ], og: { site_name: 'サイト名', # もしくは site_name: :site title: 'タイトル', # もしくは title: :title description: 'description', # もしくは description: :description type: 'website', url: request.original_url, image: image_url('ogp.png'), locale: 'ja_JP', }, twitter: { card: 'summary', site: '@ツイッターのアカウント名', } } end end これまでの作業が終わればあとは、application.html.erbのhead内に<%= display_meta_tags(default_meta_tags) %>を記述すればviewに表示できます。 以上です。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Active Storageの導入

Active Storageとは? ファイルアップロード機能を簡単に実装できるGemです。 ActiveStorageを導入しただけではファイルをアップロードできるようになるだけです。 保存した画像を画像を加工してから(サイズや色など)表示できるようにするには以下の画像加工ツールとgemが必要になります。 ImageMagick コマンドラインから画像に処理を加えることができるツールです。 処理としては、画像の作成やサイズ変更、保存形式の変更などがあります。 ImageMagickはGemではなく、ソフトウェアです。 そのため、Homebrewからインストールします。 GemではないImageMagickをRubyやRailsで扱うには、MiniMagickというGemが必要となります。 MiniMagick ImageMagickの機能をRubyで扱えるようにしてくれるGemです。 RailsでImageMagickを扱うために必要となります。 MiniMagickによって、ImageMagickの機能がRailsで使用できるようになりますが、画像サイズの変更には、もう1つImageProcessingというGemを追加する必要があります。 ImageProcessing MiniMagickでは提供できない、画像サイズを調整する機能を提供するGemです。 たくさんのツールとGemを紹介しましたが、それぞれの関係性は把握しておきましょう。 それでは、これらのツールとGemを導入します。 導入手順 まずはImageMagickを Homebrew からインストールします。 ターミナル % brew install imagemagick 次にMiniMagickとImageProcessingをインストールします。 gemfile    # gemfileの一番下に記述する % gem 'mini_magick' % gem 'image_processing', '~> 1.2'      続いて、ターミナルにてbundle installします。 ターミナル % bundle install gemを新しくインストールしたらローカルサーバーを再起動しましょう。 ターミナル % rails s # サーバー開いている場合は一度「 control + c 」で閉じてから再起動するように 以上でActive Storageを使用する為に必要なツールのインストールは完了です。 続いて、Active Storageをアプリケーション内で使用する準備を行います。 ターミナル % rails active_storage:install rails active_storage:installコマンドを実行すると、Active Storageに関連したマイグレーションが作成されます。続けてマイグレートしましょう。 ターミナル % rails db:migrate Sequel Proを確認し、active_storage_attachmentsとactive_storage_blobsの二つのテーブルが追加されていれば成功です。 これで、Active Storageと画像加工ツールの導入は完了です。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Rails】ポートフォリオ

E-tripp ?はじめに  今回のこのポートフォリオは転職を目的として作成しました。ただ作成するのではなく、現場を意識してdevelopからブランチを切り最後にmasterでデプロイをする開発工程で行いました。  また、だらだら作っていてはいつまで経っても転職活動ができないと考え、自分で納期日(完成予定日)と、工程をAプラン(終わったら転職活動スタート)・Bプラン(転職活動中)と分けて取り組むようにしました。以下はAプランの実装で、制作期間は約1ヶ月です。 ?制作背景 課題 旅行プランを作るのに、色々なサイトを探して決めるのが大変とパートナーが不満にしていました。そして簡単に計画を作りたいという要望を叶えたいと考えました。 解決方法 時間や場所をクリックで選択、登録し簡単スケジュール化 目的 簡単に旅行プランを立てる パートナーの要望を叶える、笑顔にさせる 継続的なサービス展開(ビジネス) この課題の解決として誕生したのが『E-tripp』です。 サイトURL https://arcane-forest-90597.herokuapp.com/ ?アプリ概要 クリックするだけで簡単に旅行プランを制作できるアプリです。 ?開発環境 Ruby 2.7.3 Ruby on Rails 6.1.3 PostgreSQL 13.2(DB) Github Visual Studio Code JavaScript jQuery bootstrap4.5.1 Heroku ✈️実装機能 機能 Gem ① ログイン機能 devise ② ゲストログイン機能 ✖︎ ③ プラン作成機能(CRUD) cocoon ④ いいね機能(Ajax) ✖︎ ⑤ いいねカウント機能(Ajax) ✖︎ ⑥ コメント機能(Ajax) ✖︎ ⑦ 検索機能 ransack ⑧ ページネーション機能 kaminari ⑨ 画像アップロード機能   carriewave ⑩ 管理者機能 activeadmin ✏️ER図 苦労した点 多対多のアソシエーション 今回一番苦労しました。1対多のアソシエーションはすぐに理解する事ができたのですが、多対多のアソシエーションに一番時間を費やしました。中間テーブルによってどっちが複数持てるのか、外部キーはどこが所有するのか等、非常に迷いました。解決策としてやりたいことを図や絵や言葉で表現(例;plan→schedule→spot)しながら進めていくことで、無事に解決する事ができました。 ?トップページ 工夫した点 ①ページ切り替え ログインの有無で、ページにボタンを追加していろいろなページに移動できるようにしました。 ②シンプル ユーザーが見やすいようにGIF画像を取り入れました。最初は動画を取り入れたのですが、読み込みに時間がかかる、ユーザーがクリックする手間といった課題が出たので、それを解決するためにGIF画像を採用しました。 苦労した点 デプロイ先で画像が表示されない ローカル環境では表示されていた画像が、デプロイ先では表示されませんでした。原因は、自動デプロイの際に画像がコンパイルされ、パスが変わるとのことで、assets_pathを記述したことで無事に表示されました? ?プラン作成画面 工夫した点 ①プランに複数のスポットを追加可能に ユーザーが複数のスポットを登録できたら良いと思い、『スポットを追加』のボタンを押すことで、スポットのフォームを追加できるよう実装しました。時間も一緒に登録できます。 ②既存のスポットをセレクトボックスで選択 ユーザーの入力負担を減らそうと思い、スポットをセレクトボックスで選択できるよう実装しました。 今後は画像をクリックしたらフォームに登録できるような実装をしていきたいと考えています。? 苦労した点 中間テーブルの追加したカラムに時間を登録 多対多のアソシエーションにおいて、いいね機能等は中間テーブルにFKのみで実装できたが、今回はFKと時間のカラムが追加されたことで中間テーブルにデータが中々保存できませんでした。時間がかかりましたが、form_wtihの中にfields_forを追加したことで無事に解決できました? ?プラン詳細画面 工夫した点 ①プランが見やすいようタイムライン化 ユーザーがすぐに時間と場所を確認できたらいいと思い、タイムライン化で実装しました。 編集機能で順番を入れ替えることもできます。 ②画像をクリックでスポット詳細ページへ ユーザーはすぐに場所の情報を知りたいと思い、行く場所をクリックすることで詳細ページに移動できるよう実装しました。 苦労した点 plan詳細ページからspot詳細ページに移動 plan詳細ページからspot詳細ページに移動したかったのですが、解決に時間がかかりました。初めはplanからuserにリンクをつけての移動ができたので、同じようにすればいいと考えましたが、前者は多対多で後者が1対多の関係だったので、やりたいことが違うとわかりました。原因は引数の数でした。引数を2つ設定したことで無事に解決することができました? ?スポット詳細画面 工夫した点 いいねボタンとコメント機能をAjax化 いいねボタンとコメント機能をAjax化したことで、ページが切り替わる時のユーザーの待ち時間と、サーバーへの負担を減すようにしました。 苦労した点 Ajaxが機能しない コメント機能の作成と削除をAjax化にしたかったのですが、リロードしないと動かない現象が起こりました。原因はjqueryが正しく読み込まれていないことでした。読み込む場所が違っており正しい位置にしたことで無事に解決できました? ?今後実装予定(Bプラン) テスト(Rspec) N+1問題 AWSへデプロイ タグ機能 無限スクロール機能 ページネーションのAjax化 画像をクリックしたらフォームに登録できる機能 さいごに パートナーにこのアプリを使ってもらい、喜んでもらい、笑顔にすることができました。また、もっとこうした方がいいといったアドバイス(要望)を頂いたので、ユーザー側からの意見として参考に修正していきたいと思います。 制作にあたっては、納期日(完成予定日)意識したことで、予定日の週は追い込まれることを経験しました。余裕を持った計画の逆算が必要だと感じました。 またエラーに対しては仮説を立て調べ上げ、8割は自力で解決することができました。詰まっていたところが自力で解決できたときはとても嬉しかったです。 今後は継続的なサービス展開ができるように開発をしていきたいと考えています。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

関数と文字列まとめ

こんにちは、にんじゃわんこさん JavaScript JavaScript const name = "にんじゃわんこ"; console.log(`こんにちは、${name}さん`); JavaScript const name = "にんじゃわんこ"; console.log("こんにちは、" + name + "さん"); Ruby Ruby name = "にんじゃわんこ" puts "こんにちは、#{name}さん" Ruby name = "にんじゃわんこ" puts "こんにちは、" + name + "さん" 連結は文字列同士でしかできないため、基本的に変数展開を使うのが無難
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[Ruby]文字列(String)のtrue、falseをBoolean(TrueClass、FalseClass)へ変換

rubyでture、falseの入力を文字列(Stirng)として受け付けたとき、Boolean型のtrue、falseとして扱うために変換するコードを紹介します。 前提 Rubyではnillかfalse以外をtrueとして扱います。 そのため、文字列のfalseを条件文に利用すると、論理値としてはtrueになってしまいます。 false.rb bool = gets p bool.class if bool p "Trueです!" else p "Falseです!" end =====入力・出力結果===== false String "Trueです!" String→Booleanの変換コード、動作の紹介 文字列のtrue、falseをBooleanに変換する方法を早速紹介します。 string→boolean変換.rb class String def to_bool # 関数の呼び出し元文字列がtureだったらBoolean型のtrueを返す if self =~ /(true|True|TRUE)/ return true # 関数の呼び出し元文字列がfalseだったらBoolean型のfalseを返す elsif self =~ /(false|False|FALSE)/ return false # 関数の呼び出し元文字列がtrue、false以外だったら元の文字列を返す else return self end end end コードの要点をひとつだけ補足すると、class String部分はオープンクラスというRubyの概念を利用して、元々存在していないメソッドを追加しています。 オープンクラスについてはページ下部で紹介しますので、一旦置いておいて、動作確認のコードも合わせて紹介します。 動作確認.rb class String def to_bool # 関数の呼び出し元文字列がtureだったらBoolean型のtrueを返す if self =~ /(true|True|TRUE)/ return true # 関数の呼び出し元文字列がfalseだったらBoolean型のfalseを返す elsif self =~ /(false|False|FALSE)/ return false # 関数の呼び出し元文字列がtrue、false以外だったら元の文字列を返す else return self end end end str = gets.to_bool if str.class == String p 'Stringです!' else if str p 'Trueです!' else p 'Falseです!' end end =====入力・出力結果===== 例① false "Falseです!" 例② true "Trueです!" 例③ a ”Stringです!” オープンクラスの補足 オープンクラスはざっくりいうと、クラスの再定義、メソッドの上書き、メソッドの追加を可能にしてくれる概念です。 メソッドの上書きかどうかはメソッド名で判別されるので、名前被りが発生していないかの確認はとても大切になります。 名前が被っていないかの確認は以下二つが簡単かと思います。 コードを書いて検証(No methodがエラーが出るかどうかを確認) リファレンスを見る(Stringクラスはこちら) Boolean→Stringの補足 String→Booleanは自らメソッドを追加しなければなりませんが、逆のBoolean(TrueClass、FalseClass)→Stringは用意されています。 Boolean→String.rb bool = false str = bool.to_s p bool.class p str.class =====出力結果===== FalseClass String
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Railsでサイトを作成する下準備までの大まかな手順

 記事の目的  Cloud9にてECサイトを作るにあたって「何から始めればいいんだっけ?」と思いQiitaを含めて何回か参照していましたが、流れがまとまらなかったので自分用の備忘録として記載します。参考までに。  本当に大まかにまとめたので、詳細箇所については別途追記するかもしれません。 ECサイト作成前に準備すること。  個人製作の場合は必ず必要というわけではないですが、作成する前に作っておくと後々サイトを作りやすいです。 Cacooというサイトであれば両方作成できるので、おすすめです。 ・ER図 ・ワイヤーフレーム ・GitHubの連携 ・ImageMagickのインストール ファイル・モデル・コントローラーの作成 ①ファイルの作成 ※Cloud9にて諸々の初期設定が終わっていること。これに関しては個人の設定に左右される。 ターミナルを開いて、下記を入力しファイルを作成する。 (例)として、ファイル名を「Illusters」というアプリを作るものとします。 【ターミナル】 ~$ rails new ファイル名 (例)~$ rails new Illusters ※ファイル名は"頭文字:大文字" ②モデルの作成 作りたいモデルを作成する。 モデルの中にカラムとデータ型を一緒に作成すれば後々マイグレーションファイルがごちゃごちゃしないのでオススメ。 user_idといったモデルに直結するidは記載不要。 【ターミナル】 ~$ rails g model モデル名 カラム1:データ型1 カラム2:データ型2 ... (例)~$ rails g model user name:string profile_image:string introduction:text ※モデル名は"頭文字:小文字,単数形" 必要なモデルを作成した後に必ず下記の文を実行しマイグレーションすること! 【ターミナル】 ~$ rails db:migrate ↑を行わないとrailsの実行時にエラーが発生する。 モデルを削除したい場合...「モデルを間違えて作ってしまった」「後々いらなくなってしまった」など 【ターミナル】   ~$ rails d model モデル名 (例)~$ rails d model user を実行すれば削除される。 もちろん、削除した後でも~$ rails db:migrateを行って、マイグレーションファイルを更新する必要がある。 【補足】 よく使うデータ型 データ型 入力される値 使用例 integer 整数 id, 単価, 個数 など string 文字列(256文字以内) 名前, 住所, 画像, 電話番号(0から始まる) など text 文字列(制限なし) 自己紹介, キャプション など boolean true / false 男女設定, はい/いいえの質問, 表示/非表示 など float 小数点以下を含んだ数値 数量, パーセンテージ, datatime 日時 現在時刻, 登録日時 など ③コントローラの作成 ②で作成したモデルに付随するアクションコントローラーを作成する。 【ターミナル】 ~$ rails g controller コントローラ(モデルの複数形) アクション1 アクション2 ... (例)~$ rails g controller users new show edit ※コントローラ名は"頭文字:小文字,複数形" アクション名はターミナルで記載すると、下記が自動で行われるため、時短できる。 また、任意で作成したアクションも記載することはできる。 ・Cloud9内で自動で「△△-controller.html.erb」内にアクション名が追加される ・Cloud9内にフォルダが追加されその中に「△△.html.erb」が作成される コントローラを削除したい場合... モデル同様、コントローラも削除できる。 【ターミナル】   ~$ rails d controller モデル名 (例)~$ rails d controller users を実行すれば削除される。 route.rbファイルにアクション名を追加 route.rb内のファイルにコントローラを記載する。 RESTfulなアクションと任意のアクションで対応が異なるのでそれぞれ説明する。 【A. RESTfulなアクションのみ使用する場合】 【routes.rbファイル内】 resources :コントローラ名 (例) resources :users RESTfulなアクションはよく使うため、「resources :△△」の一文のみで下記7つのアクションができる。 アクション名 使用用途 メソッド new 新規作成画面 GET create 新規作成 POST index 一覧表示 GET show 詳細画面の表示 GET edit 編集画面の表示 GET update 編集 POST/PATCH destroy 削除 DELTE なお、メソッドについて端的に言うと  ・GET : 画面に表示されるもの  ・POST,PATCH : 専用の画面はなくコントローラ内のみで使用される  ・DELETE : POST,PATCH同様専用画面はない。削除するメソッド 【B. 任意のアクションを設定する場合】 RESTfulのものとは一致しないアクションを作成したいときはroutes.rbファイル内に任意のアクション名を追加する。 【routes.rbファイル内】 メソッド 'アクション名' => '保存するファイルの場所' (例)get 'download' => 'item_images#download' (例)post 'download' => 'item_images#download' ※'保存するファイルの場所'に指定がなければ "=> '~~~~'"以降は不要 以上!下準備はこれで完了です。 下準備はこれで終わりです、ここから先はコードをご自由に書いてみてください。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

config gem と dotenv-rails gem を共存させるときの ポイント

Rails での開発では、以下の2つのgemを使い分けたり、併用して設定情報を管理する方が多いかと思います。 config gem yaml 管理 dotenv-rails gem .env(及び環境変数) での管理 ですが、「設定情報を、 yaml に記載したのか、.env(及び環境変数)に記載したのか?」と分からなくなり手が止まる瞬間があります。 なので、最近は config gem を介して .env を参照するようにして、設定情報の参照先を一本化しています。 その中で、以下の 2 つのポイントのどちらかを押さえておかないとエラーになることを確認したので、共有します。 実行環境 Ruby 3.0.0 Rails 6.1.4 前提 読み込みの対象になる yaml と、.env ファイルは以下のものになります。 # config\settings.yml comment: これはテスト用アプリ # .envに記載した環境変数 SAMPLE_API_KEY の内容を読み込む sample_api_key: <%= ENV.fetch('SAMPLE_API_KEY') %> # .env # config\settings.ymlから参照される SAMPLE_API_KEY=sample_api_key 注意するポイント 次に示す 2 つプランのうちどちらかを守らないと、以下のようなエラーになります。 # エラー内容 (erb):2:in `fetch': key not found: "SAMPLE_API_KEY" (KeyError) プラン A:Gemfile で dotenv-rails gem を先に記述する Gemfileにて、dotenv-rails gem を読み込んでから config gem を読み込むようにします。これだけでエラーを回避できます。 # NG gem 'config' gem 'dotenv-rails' # OK gem 'dotenv-rails' gem 'config' プラン B:yaml ファイルでロードメソッドの実行する gemfile での、記述の順番に配慮しなくても yaml 内で、Dotenv::Railtie.load を実行することで、エラーを回避して読み込みできます。 プランAと比べて、明示的に .env が参照されていることがわかるという利点があります。 # <% Dotenv::Railtie.load %> を追加する <% Dotenv::Railtie.load %> comment: これはテスト用アプリ sample_api_key: <%= ENV.fetch('SAMPLE_API_KEY') %> それでは皆さん、安全で便利に設定情報を管理していきましょう。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

deviseでログイン後のリダイレクトを変更したい

app/controllers/users/sessions_controller.rb def after_sign_in_path_for(resource) articles_path end
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[Rails]Twitterシェアボタンは超かんたんに実装できる

色んなサイトで見かけるTwitterのシェアボタン実は、超かんたんに実装できます。 まじですぐ実装できるので、記事が短くなりすぎてしまいそうで不安ですw こんな感じ シェアボタンを押すとこんな感じで、Twitterに飛びます。 かんたんにシェアできるので便利ですね〜 ポートフォリオサイトのせておきますので、どんどんシェアしてみてくださいww 開発環境 ruby 2.6.3 Rails 5.2.6 さっそく実装 実装方法はビューで、TwitterのシェアためのURLにリンクを実装するだけです。 実装 <%= link_to "https://twitter.com/share?url=#{ request.url }&text=【テスト】%0a%0a#{ post.content }、シェアさいこう〜", target: '_blank' do %> <i class="fab fa-twitter" style='color: #3399FF;'></i>シェア <% end %> これだけで、実装完了です。 これだけでは、少しわかりにくいので、解説していきます。 URL まず、リンクの遷移先とツイートに入ってるURL部分を見ていきます。 ツイート内のURL部分はurl=#{ request.url } # request.urlにシェアボタンを設置したページのURLが入る link_to "https://twitter.com/share?url=#{ request.url } ツイート本文 次にツイートの本文部分を見ていきます。 ここは、ツイートしたい内容によって、任意の文字列、カラムなんかを指定してアレンジができます。 ツイート本文は&text= 今回は、 文字列  改行 post.content 文字列 でツイートを構成しています。 # %0a%0aが改行 # カラムを使う場合は#{ }の中に入れる &text=【テスト】%0a%0a#{ post.content }、シェアさいこう〜" target: '_blank' これはlink_toのオプションでつけることにより、リンク先を別タブで開けるようになります。 シェアリンク 最後に表示されているリンク部分のデザインです。 Twitterなので、FontAwesomeのアイコンを使って、青くしています。 <i class="fab fa-twitter" style='color: #3399FF;'></i>シェア まとめ 思ったとおり、短い記事になりましたw 実際この記事読んでもらったら、変更点はツイートの本文ぐらいなので、実装は5分以内にできるんじゃないでしょうか。 さくっと、Twitterシェアボタン実装してみてください!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

カート機能②カートに入れる 同一商品は個数のみ更新する

はじめに カート機能を作成中です。  ”今回はカートに入れる”とカートに入るようにします。 同一商品の場合には、個数のみが更新されるようにします。 前提条件 ここで登場するテーブル・モデルは、 Customer Item Cart_item です。←(CustomerとItemの中間テーブルになる。) (Cartモデルを作成している記事が多いですが、Cartモデルは作成していません。) *ログインしなくても商品の閲覧はできるが、カートには入れられない。 View 個数を選択してカートに入れる #関係するところのみ抜粋 <%= form_with model:@cart_item,url:cart_items_path,method: :post,local:true do |f| %> <%= f.hidden_field :item_id, value: @item.id %> <%= f.hidden_field :customer_id, :value => current_customer.id %> <%= f.select :quantity,[1,2,3,4,5,6,7,8,9,10],{include_blank: '個数選択'},required:true%>&emsp; <%= f.submit 'カートに入れる' ,class: 'btn btn-success btn-sm'%><% end %> hidden_fieldとは何? 複数のWebページ間でデータの受渡しを行う際に利用されます。 hiddenなので画面上には表示されません。 今回だと、カートの画面にcustomer_idとitem_idを渡しています。 エラーの記録:個数選択 無しで、カートに入れる は出来ないようにしたいのに f.selectで、required:trueにしてますがこれは"入力必須"ということです。 しかしながら、"個数選択"のままカートに入れるボタンを押すことができ、nil~のようなエラーが出てきてしまいます。 モデルファイルのバリデーションでもpresense trueにしてて、数字のみ受け付けるようにしてたのですが、 nilで進んでしまい、nil~のエラーがでてました。 解決策 マイグレーションファイルでnil falseにしたら解決しました・・・ コントローラー cart_item_controller.rb def create @cart_item = CartItem.new(params_cart_item) @cart_item.customer_id=current_customer.id @cart_items=current_customer.cart_items.all @cart_items.each do |cart_item| if cart_item.item_id==@cart_item.item_id new_quantity = cart_item.quantity + @cart_item.quantity cart_item.update_attribute(:quantity, new_quantity) @cart_item.delete end end @cart_item.save redirect_to cart_items_path,notice:"カートに商品が入りました" end private def params_cart_item params.require(:cart_item).permit(:quantity, :item_id,:customer_id) end 解説 @cart_item = CartItem.new(params_cart_item) 本の投稿と似てます。 Cart_itemの新規投稿。 ストロングパラメーターで、個数、item_id、customer_idを受け取っています。 @cart_item.customer_id=current_customer.id この記述は不要だったかもしれません。というのも、個数選択のviewで同じような定義をしてるからです。 @cart_items=current_customer.cart_items.all ここで、カートに入っているものを取り出しています。 問題は次!同じ商品をまとめる記述 @cart_items.each do |cart_item| カートの中身を一個ずつ取り出して、 if cart_item.item_id==@cart_item.item_id もし、同じ商品が存在していれば、 new_quantity = cart_item.quantity + @cart_item.quantity 今の個数に足す それを、new_quantityに代入。 cart_item.update_attribute(:quantity, new_quantity) cart_itemモデルのquantityをnew_quantityに更新するよ という意味らしい。 @cart_item.delete 同一商品に関しては、個数だけ更新できたら後はオサラバ 参考にさせていただきました 以下の記事に感謝です 同じ商品がカートに入った場合、個数のみ更新されるよう記述できました。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

過去7日間の投稿をグラフ表示 Chartkick Turbolinks無効化

やりたいこと 過去7日間の投稿数を取得し、折れ線グラフで表示する. グラフが表示できなかったり、12日分表示してしまったり・・・ととにかく大変でした。 そもそもJavascriptの知識が浅いため、、難しかったです。 7日間の投稿データ取得 前回作成した記事と同様です。グラフ化が大変だったのでここはサクッと行きます 違う点は、、 コントローラーに記述しなくても、モデルで定義した値をviewで使用できるということです。 7日間の投稿データ取得 models/book.rb   scope :created_today, -> { where(created_at: Time.zone.now.all_day) } scope :created_yesterday, -> { where(created_at: 1.day.ago.all_day) } scope :created_2days, -> { where(created_at: 2.days.ago.all_day) } scope :created_3days, -> { where(created_at: 3.days.ago.all_day) } scope :created_4days, -> { where(created_at: 4.days.ago.all_day) } scope :created_5days, -> { where(created_at: 5.days.ago.all_day) } scope :created_6days, -> { where(created_at: 6.days.ago.all_day) } users_controller.rb def show @user=User.find(params[:id]) @books = @user.books.page(params[:page]).reverse_order @today_book = @books.created_today @yesterday_book = @books.created_yesterday @this_week_book = @books.created_this_week @last_week_book = @books.created_last_week @book=Book.new end users/show.html.erb <table class="table"> <thead> <tr> <th>6日前</th> <th>5日前</th> <th>4日前</th> <th>3日前</th> <th>2日前</th> <th>昨日</th> <th>今日</th> </tr> </thead> <tbody> <tr> <th><%= @books.created_6days.count %></th> <th><%= @books.created_5days.count %></th> <th><%= @books.created_4days.count %></th> <th><%= @books.created_3days.count %></th> <th><%= @books.created_2days.count %></th> <th><%= @yesterday_book.count %></th> <th><%= @today_book.count %></th> </tr> </tbody> </table> グラフ化①・・・chart.js ? chartkick をいれる chart.jsで検索するとchartkickが出てきます。 もう何を入れるのか分からなくなりました 以下の記事で別物であるということに気づきました。多くの記事で、chartkickを使用しているので、chartkickでやっていきたいと思います。 Gemインストール 以下の記事の通り行いました。groupdateもインストールしてしまいましたが、今回使わなかったです。 (正しくは、理解できず、うまく使えなかったです・・・) Turbolinksの無効化 無効化にしないと、グラフが表示されないのではないかと思います。 私は、とにかくTurbolinksの記述を全削除してしまいましたが、個別削除がベストですね。 以下の記事で全削除できます。 Viewの記述 Turbolinks全削除済みの場合 users/show.html.erb <canvas id="myChart" width="300" height="100"> </canvas> <script> var ctx = document.getElementById("myChart").getContext('2d'); var myChart = new Chart(ctx, { type: 'line', data: { labels: ['6日前', '5日前', '4日前', '3日前', '2日前', '1日前', '今日'], datasets: [{ label: "投稿数", data: [<%= @books.created_6days.count %>, <%= @books.created_5days.count %>, <%= @books.created_4days.count %>, <%= @books.created_3days.count %>, <%= @books.created_2days.count %>, <%= @yesterday_book.count %>, <%= @today_book.count%>], backgroundColor: 'rgba(255, 80, 120, 1.0)', borderColor: 'rgba(255, 80, 120, 1.0)', fill: false }] }, }); </script> Turbolinksを個別で無効化 ``` これで、折れ線グラフの表示ができました。 参考にさせていただいた記事 以下の記事でも、グラフができましたが12日分表示されてしまいました。 どうやって7日間分に抑えれば良いのだろう?? 今回、groupdate使えこなせてないですが、使えたら便利
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

railsのコントローラーでAPIの必須項目の入力チェックする

railsのコントローラーでAPIの必須項目が入力されているかチェックする方法です。 どんなケースで使うのか具体的な使い方を書いていきます。 rails guideには以下の説明がされています。 In addition, parameters can be marked as required and will flow through a predefined raise/rescue flow that will result in a 400 Bad Request being returned if not all required parameters are passed in. サンプルコード class UserController < ApplicationController rescue_from ActionController::ParameterMissing, with: :handle_parameter_missing def index @users = User.search(user_search_params) end private def user_search_params params.require(:name, :email) params.permit(:name, :email) end def handle_parameter_missing(e) render json: { message: e.original_message }, status: 400 end end コードの説明 indexアクションではユーザの入力値を使ってユーザ情報の検索を行う。 ユーザの入力値はrequireメソッドを使用して必須項目の存在確認を行う。 必須項目が存在しない場合は例外ActionController::ParameterMissingが発生するのでrescue_fromで捕捉する。 rescue_fromで例外を捕捉した後handle_parameter_missing内でエラーメッセージを抽出しレスポンスのjsonを返却する。 コードの詳細な説明 1. actionの定義 ユーザの検索アクションです。User.search引数にユーザの入力値を検証したパラメーターを指定します。 def index @users = User.search(user_search_params) end 2. 入力値の検証 def user_search_params params.require(:name, :email) params.permit(:name, :email) end requireメソッドを使ってパラメータを検証します。 requireメソッドは引数に指定したkeyが存在しない場合、例外ActionController::ParameterMissingを発生させます。 3. 例外ActionController::ParameterMissingの捕捉 rescue_from ActionController::ParameterMissing, with: :handle_parameter_missing def handle_parameter_missing(e) render json: { message: e.original_message }, status: 400 end rescue_fromでActionController::ParameterMissingを捕捉してエラー処理を行います。 エラー処理ではmessagekeyにoriginal_messageで取り出したエラーメッセージを格納します。 また、status codeに400を指定します。 エラーメッセージの抽出について original_messageメソッドを使用して簡潔なエラーメッセージのみを取り出す事ができます。 $ e.original_message => "param is missing or the value is empty: name" message メソッドだとkeyのサジェストが出てしまいます。 e.message => "param is missing or the value is empty: name\nDid you mean? target_date\n rate\n controller\n format" e.full_messageだとスタックとレースが表示されます。 参考 rails guide
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[Rails]値オブジェクトとは?〜使い方と注意点を押さえる〜

はじめに 開発の規模が大きくなればなるほど、モデルが肥大化するFat Modelという問題が発生しやすくなります。そこで、値(Value)オブジェクトという設計手法を利用することでこの問題が解決出来ますので、利用方法と注意点をしっかり押さえて導入を検討してみましょう! 値オブジェクトとは? 値オブジェクトとは、読んで字の如く、「値」を表すオブジェクトなのですが、この値とはドメイン駆動設計という設計手法に登場する概念で、同一性を判断できない情報のことを指します。 値オブジェクトを利用することで、コードを綺麗に保ち見通しが良くなることで、テストが書きやすくなり、Fat Modelの問題を解消できます。また、オープン・クローズドの原則という、あるクラスを修正したとき、他のクラスに影響が出ない設計を実装できます。 例 山田さんと田中さんがいるとします。この2人の血液型はどちらもA型です。血液型が同じだからといって、同一人物となるわけではありません。 こういった、値が同じでも同一だと断定できない情報のことを値オブジェクトと呼びます。 ※住所や名前なども同様です 前提条件 ユーザー(User)、管理者(Admin)という2つのクラスがあるとする それぞれ名前として姓と名を持つ 姓と名からフルネームを取得できる 使い方 それぞれのユーザーの名前を値オブジェクトにします。 1.名前を切り出したNameクラスを実装する。 app/values/name.rb class Name attr_reader :first_name, :last_name def initialize(first_name, last_name) @first_name = first_name @last_name = last_name end def full_name "#{first_name} #{last_name}" end end 2.それぞれのユーザーのクラスに値オブジェクトを使えるように設定する。 app/models/user.rb class User < ApplicationRecord # 第一引数に値オブジェクト名、第二引数には属性のマッピング composed_of :name, mapping: [%w(first_name first_name), %w(last_name last_name)] end app/models/admin.rb class Admin < ApplicationRecord # 第一引数に値オブジェクト名、第二引数には属性のマッピング composed_of :name, mapping: [%w(first_name first_name), %w(last_name last_name)] end 利用例 Valueオブジェクトを用いた検索 users = User.where(name: Name.new('Taro', 'Yamada')) ユースケース 複数の値を組み合わせてひとつの値を算出するもの 名前(姓・名・ミドルネーム) 住所(国や県・市区町村など) 値の表現や比較を行うもの 日付 通過 気温 商品レビューにおける星の数 注意点 導入タイミングは、値オブジェクトを複数のクラスから利用することになったとき app/values下に配置 ファイル名はValueオブジェクトの名前にする name.rb address.rb 必要最低限のインタフェースのみを公開する 公開したインタフェースに対するユニットテストを書く 終わりに 上記の通り、何もかも切り出して値オブジェクトとしても良いわけではないようですね。注意点をしっかり押さえることで、見通しが良いコードを実装出来るので、これからタイミングを見て使っていきましょう! 参考 Rails: Value Objectを検討してみよう(翻訳) Railsのデザインパターン: Valueオブジェクト composed_of を使って Rails で値オブジェクトを扱う
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

いいね機能実装 [Ruby on Rails]

完成品 投稿にいいね機能を実装する。 テーブルは、Users,Booksに加えFavoritesを追加する。 実装の手順 ①モデルの作成 ②ルーティングを追加 ③それぞれのモデルに関連付けを追加 ④コントローラを作成 ⑤Viewを作成する ①モデルの作成 terminal $rails g model Favorite user_id:integer book_id:integer user_id:userとの紐づけ book_id:book投稿との紐づけ integer:データ型の整数 ②ルーティングを追加 routes.rb resources :books do resource :favorites , only: [:create , :destroy] end favoritesのshowページが不要で、idの受け渡しも必要ないので、resourceとなっています。 今回は、resources :booksにネストします。 resources :booksの中にresource :favorites , only: [:create , :destroy]を入れるという意味です。 ネストする理由は、ルートパスにあります。 routes.rb #ネストしない場合 resources :books resource :favorites , only: [:create , :destroy] ネストしないとルートパスが、下図になります。実はこのままだと、どの投稿(book_id)にいいねを付けたか特定することができません。 ネストすることでルートパスが下図になります。投稿(book_id)を特定することができますね。 ③それぞれのモデルに関連付けを追加 app/model/user.rb has_many :favorites, dependent: :destroy app/model/book.rb has_many :favorites, dependent: :destroy def favorited_by?(user) favorites.where(user_id: user.id).exists? end app/model/favorite.rb belongs_to :user belongs_to :book アソリエーション ※ user : favorite = 1 : 多  ※ book : favorite = 1 : 多 1つのuserからみて、いいねは多数あるのでhas_many 1つのbook(投稿)からみて、いいねは多数あるのでhas_many 1つのいいねからみて、user・book(投稿)は1つしかないのでbelongs_to has_manyの後にはdependent: :destroyを付けましょう。 favorited_by?メソッドを作成します。 このメソッドで、引数で渡されたユーザidがFavoritesテーブル内に存在(exists?)するかどうかを調べます。 ④コントローラを作成 terminal rails g controller Favorites app/controllers/favorites_controller.rb class FavoritesController < ApplicationController def create   book = Book.find(params[:book_id]) favorite = current_user.favorites.new(book_id: book.id) favorite.save redirect_to request.referer end def destroy book = Book.find(params[:book_id]) favorite = current_user.favorites.find_by(book_id: book.id) favorite.destroy redirect_to request.referer end end #必要に応じてインスタンス変数を付けましょう。(book => @book) current_userはログイン中のユーザーです。 request.refererは、元のviewに戻ってきます。いいねをクリック→いいねされたviewに戻ります。 なぜparamsの中が:book_idなのか?恐らくusr_idと混同するからと推測 ⑤Viewを作成する terminal #<% books.each do |book| %> <% if book.favorited_by?(current_user) %> <%= link_to book_favorites_path(book), method: :delete do %>♥<%= book.favorites.count %> <% end %> <% else %> <%= link_to book_favorites_path(book), method: :post do %>♡<%= book.favorites.count %> <% end %> <% end %> #<% end %> #book/indexで投稿を全て表示しているので今回はインスタンス変数なし <% if book.favorited_by?(current_user) %> いいねがクリックされている状態と、されていない状態で表示を変えます。 <%= book.favorites.count %> いいねされた数を表示しています。 以上で実装完了となります。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Ruby備忘録、Rubyの特に分かりにくかったところ、メソッド呼び出しのカッコ省略等

この記事について ruby学習中のため、その備忘録です。railsの話はほぼ出てきません。 rubyを学習していて特に分かりにくかったところなどを中心に書いています。 他言語からRubyへ PHPやPython等他言語を使ってる人に対しては、Ruby公式サイトにそれぞれの言語とRubyの違いについて書かれたページがあります。 他言語からのRuby入門 メソッド呼び出しのカッコ省略、return省略 引数無しのメソッド呼び出しのカッコ省略 rubyではメソッド呼び出しの際カッコを省略することができます。 def hello puts 'hello!' end hello() # hello! hello # hello! 引数ありのメソッド呼び出しのカッコ省略 引数がある時もカッコの省略ができます。 引数が複数ある場合は,で繋ぎます。 def hello_name(name) puts "hello #{name}!" end hello_name('suzuki') # hello suzuki! hello_name 'suzuki' # hello suzuki! def hello_name2(name1, name2) puts "hello #{name1}, #{name2}!" end hello_name2('suzuki', 'sato') # hello suzuki, sato! hello_name2 'suzuki', 'sato' # hello suzuki, sato! returnの省略 また、メソッド内の最終行で戻り値を返す場合はreturnを省略できます。 def plus10(n) n + 10 # return n + 10 end def double(n) n * 2 end puts plus10 3 # 13 puts double plus10 3 # 26 ← puts double( plus10(3) ) メソッド定義のカッコ省略 メソッド定義でもカッコが省略できます。 引数無しの場合だけでなく、引数ありの場合でも省略できるみたいです。 ただ、実際に引数ありのメソッド定義でカッコを省略して書いている人は少ないように感じました。 def bye_name name puts "bye #{name}!!" end def bye_name2 name1, name2 puts "bye #{name1}, #{name2}!!" end bye_name 'suzuki' # bye suzuki!! bye_name2 'suzuki', 'sato' # bye suzuki, sato!! メソッドの別名 メソッドの別名を付ける際はaliasやalias_methodを使用します。 alias_methodはclassの外では使えません。 def method1 puts 'method!' end # これはメソッドの別名を付けてる訳ではなく、戻り値を代入している not_method = method1 # method! method1 # method! not_method # 何も出力されない puts not_method # nil ← putsの戻り地はnil alias :method2 :method1 method2 # method! メソッドのオプション引数、ハッシュの波カッコ省略 オプション引数 引数にデフォルト値を設定してオプション引数とすることで、メソッド呼び出し時に省略できるようになります。 def pow(n, m=2) n ** m # nのm乗 end puts pow 3 # 9 puts pow 3, 4 # 81 ハッシュの波カッコ省略 引数の最後がハッシュの場合は{}を省略できる def filter_high_persons(min, persons) persons.filter {|k,v| v > min} end puts filter_high_persons(170, {suzuki: 175, sato: 165, tanaka: 180}) # {:suzuki=>175, :tanaka=>180} puts filter_high_persons 170, suzuki: 175, sato: 165, tanaka: 180 # {:suzuki=>175, :tanaka=>180} railsでも基本()や{}を省略して書かれることが多いです。 例えばルーティングのところは省略せずに書くと以下のようになります。 get 'test1', to: 'tests#test1', as: 'test_action1' get('test1', {to: 'tests#test1', as: 'test_action1'}) その他 命名 識別子に!や?を使えます。 慣習的に戻り値が真偽値のメソッドには名前の最後に?を付けることが多く、isやcan等はあまり使いません。 例えばis_successではなく、success?と命名します。 慣習的に破壊的メソッドには名前の最後に!を付けることが多いです。 例えばArrayのsortメソッドは非破壊的ソートを行い、sort!メソッドは破壊的ソートを行います。 メソッド名に!が付いていなければ絶対に破壊的メソッドではない、という訳ではありません。 また、処理失敗時にfalse等を返すメソッドには!を付けず、処理失敗時に例外を発生させるメソッドには!を付けるといった命名もされています。 例えばRailsのsaveは成功したかどうか真偽値を返しますが、save!メソッドは失敗時に例外を発生させます。 標準出力 標準出力するメソッドにputs, print, pがあり、それぞれ出力の仕方が少しずつ異なっています。 主に改行の入り方が違うようです。 メソッド 引数毎の改行 配列の要素間の改行 nil 補足 puts 入る 入る 空行を出力 配列の[]の表示なし p 入る 入らない nilと出力 print 入らない 入らない 何も出力されない スペースも入らない puts 'suzuki', 'sato' # suzuki(改行)sato(改行) puts ['suzuki', 'sato'] # suzuki(改行)sato(改行) puts name: 'suzuki', age: 20 # {:name=>"suzuki", :age=>20}(改行) puts nil # (空行) p 'suzuki', 'sato' # "suzuki"(改行)"sato"(改行) p ['suzuki', 'sato'] # ["suzuki", "sato"](改行) p name: 'suzuki', age: 20 # {:name=>"suzuki", :age=>20}(改行) p nil # nil print 'suzuki', 'sato' # suzukisato print ['suzuki', 'sato'] # ["suzuki", "sato"] print name: 'suzuki', age: 20 # {:name=>"suzuki", :age=>20} print nil # 何も出力されない 式と文に違いはない 式と文に違いはなく、全ては値をもつ。 x = 10 res = if 0 <= x '0以上' else '0未満' end puts res # 0以上 シンボル シンボルは単なる軽量文字列ではない。 シンボルはオブジェクトの実体を指すもので、同じシンボルであればメモリ上の同じ場所を参照する。 puts :test.object_id == :test.object_id # true ← メモリ上の全く同じ場所にある puts 'test'.object_id == 'test'.object_id # false ← 値が同じだけでメモリ上の別々の場所にある 型、インスタンスの調べ方 型・クラスはclassメソッドで調べられます。 インスタンスが特定のクラスのものか調べる際はkind_of?やinstance_ofメソッドを用います。 kind_of?はそのクラスの直接のインスタンスか、そのクラスを継承しているクラスのインスタンスであればtrueとなります。 instance_of?はそのクラスの直接のインスタンスの時のみtrueとなります。 puts Time.class # Class puts Time.kind_of?(Class) # true puts Time.kind_of?(Time) # false time = Time.now puts time.class # Time puts time.kind_of?(Class) # false puts time.kind_of?(Time) # true class MyTime < Time end my_time = MyTime.now puts MyTime.class # Class puts my_time.class # MyTime puts my_time.kind_of?(Time) # true ← MyTimeはTimeを継承しているため puts my_time.kind_of?(MyTime) # true puts my_time.instance_of?(Time) # false ← MyTimeのインスタンスであってTimeのインスタンスではない puts my_time.instance_of?(MyTime) # true nil (null) &.演算子 nilに対して&.演算子を用いるとundefined methodエラーを回避できます。 nilが入る可能性がある変数のメソッドを直接呼び出す書き方をしているとnilになった時にエラーが出てしまう為、そういった場合に&.演算子を使うことがあります。 class Test def hello 'hello!' end end test = Test.new p test.hello # "hello!" test = nil # p test.hello # undefined method `hello' for nil:NilClass if test # nilはfalse扱い p test.hello # ここは通らないのでエラーとならない else p 'bye!' # bye! end # `&.`演算子や`||`演算子を使えば条件分岐を減らすことができる時もある p test&.hello # nil ← エラーとならずにnilが返される p test&.hello || 'bye!' # "bye!" &.演算子を使用しても、nilではないものに対して存在しないメソッドを呼び出した場合はエラーとなる now = Time.now # p now&.hello # undefined method `hello' for ~:Time tryメソッド railsのtryメソッドを用いると、nilではないものに対して存在しないメソッドを呼び出した場合でもエラーとなりません。 # rails上でしか動きません now = Time.now p now.try(:hello) 変数が定義されているか調べる方法 変数が定義されているか確認する際はdefined?メソッドを用います、未定義であればnilを返します。 a = 10 p defined?(a) # local-variable p defined?(b) # nil 可変長引数、展開 可変長引数 引数名の前に*を付けることで引数の個数を可変にすることができます。 渡された引数は配列となって可変長引数に渡されます。 def variable_arg(*args) p args.class # Array p args # [1, 2, 3] end variable_arg 1, 2, 3 def sum(*nums) nums.sum end puts sum 1, 2 # 3 puts sum 1, 2, 3 # 6 通常の引数と可変長引数を組み合わせることもできます。 def name_sum(name, *points) "#{name}さんの合計点は#{points.sum}点です" end puts name_sum 'suzuki', 10, 20, 30 # suzukiさんの合計点は60点です 展開 逆にメソッド呼び出し時の引数名の前に*を付けると配列を展開してメソッドに渡すことができます。 def five_avg(a, b, c, d, e) (a + b + c + d + e) / 5 end def avg(*nums) nums.sum / nums.length end points = [10, 20, 30, 40, 55] puts five_avg *points # 31 puts avg *points # 31 参考 ドキュメント・リファレンスマニュアル Ruby公式ドキュメント (他言語からのRuby入門 ) Ruby リファレンスマニュアル (Arrayクラス) Railsガイド (Active Recordの基礎 > 6 バリデーション(検証)) 参考にさせて頂いたQiitaの記事 Rubyの引数(オプション引数とブロック引数)について Rubyのメソッドの引数受け渡しまとめ Ruby 命名規則まとめ
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ディスク空き容量を取得するFluentdのプラグイン作った

プラグイン作りました fluentdという様々なデータ収集を統一できるオープンソースのソフトウェアがありますが、プラグインを入れることによって様々で種類のデータを取得したり、加工したりすることができるようになります。 今回は、fluentdを動かしているPCのディスク容量を取得したかったのですが、よさげなプラグインがなかったので作ってみました。RubyGemにも公開済みです。OSSなのでPR, issue歓迎です?‍♂ 使い方 プラグインをGemでインストールします。 $ gem install fluent-plugin-diskfree これでプラグインが利用できるようになるので、fluentdの設定ファイルに追記します。 <source> @type diskfree option -k refresh_interval 10 mounted_path /fluentd/etc replace_separator true trim_percent true tag_prefix hostpc.df </source> それぞれの設定値は以下の通りです。 オプション 型 デフォルト値 説明 option string -k dfコマンドに渡すオプション。デフォルトはblock-sizeを1Kとして表示するオプションが設定されています。 refresh_interval integer 5 dfコマンドを実行する間隔。デフォルトは5秒です。 mounted_path string / チェック対象のマウントパスを指定します。デフォルトはルートディレクトリとなっています。 trim_percent bool true dfコマンド結果に現れる%を削除します。trueの場合、返却される値の型はintfalseの場合は、返却される値の型はstringになります。 replace_separator bool true mounted_pathで指定したパスの/を_に変換してから返却します。 tag_prefix string diskfree fluentdのタグに接頭語を追加します。 上記のfluent.confの状態で、fluentdを実行すると以下のようなログを取得することができます。 hostpc.df._fluentd_etc: { "mounted_path":"_fluentd_etc", "disksize":250630588, "used":147889068, "used_percent":59.0, "available":102741520, "available_percent":40.99, "capacity":59 } 実装解説 fluentd公式サイトに、プラグインの作成方法が掲載されています。基本的にはその方法に従って作成します。 (※ 今回のプラグインを作るときには、fluentd公式の方法を見つけていなくて普通のGemを作る方法で実装してました...?) このプラグインの主要な部分だけ軽く解説しておきます。ソース全体はGithub上に公開されています。 # Get df output. splited by line. result = `#{@execute_command}`.split(/\R/) # Remove df output header. result.shift @execute_command には実行する df コマンドを指定します。@execute_command の定義はこんな感じです。 @execute_command = "df -P #{@option} #{@mounted_path} 2> /dev/null" fluent.conf で指定した option や mounted_path を展開して実行する df コマンド作りあげます。上記のconf設定だと、このような df コマンドが実行されます。 @execute_command = "df -P -k /fluentd/etc 2> /dev/null" このコマンドを実行すると以下のような結果が返ってきます。それを result の中に格納します。 (※ 表示内容は実行している端末によって異なります。) Filesystem 1024-blocks Used Available Capacity Mounted on /dev/mapper/centos-home 250630588 149553004 101077584 60% /fluentd/etc そして result.shift を実行することで、df コマンドのヘッダー部分を削除して、必要な情報だけが result の中に残るようにします。 # resultの中身 Filesystem 1024-blocks Used Available Capacity Mounted on /dev/mapper/centos-home 250630588 149553004 101077584 60% /fluentd/etc ↓ ↓ result.shift を実行すると先頭(ヘッダー)が削除されます。 ↓ /dev/mapper/centos-home 250630588 149553004 101077584 60% /fluentd/etc ヘッダーを削除した状態で、データを分割して配列化します。 結果を出力するために必要なデータを取得できなかった場合には、エラーログを出力するようにしておきます。 data_list = line.split(/\s+/) log.error("Invalid df output format. #{line}") unless data_list.length == DF_HEADER_COLMUS_LENGTH あとは必要なデータから、出力するデータを生成して終了です。 used_percent = ((data_list[2].to_f / data_list[1].to_f) * 100).floor(2) available_percent = ((data_list[3].to_f / data_list[1].to_f) * 100).floor(2) disk_info = { 'mounted_path' => replace_separator?(data_list[5]), 'disksize' => data_list[1].to_i, 'used' => data_list[2].to_i, 'used_percent' => @trim_percent ? used_percent : "#{used_percent}%", 'available' => data_list[3].to_i, 'available_percent' => @trim_percent ? available_percent : "#{available_percent}%", 'capacity' => data_list[4].to_i } disk_info
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む