20210513のRubyに関する記事は21件です。

知らない人に勝手に出品した商品を編集させない!

はじめに 現在フリマアプリを作成中です。 商品の出品者ではない人が編集できるURLを直接打ち込み、編集できるという問題を解決していきます。 想像してみて下さい。 自分が30,000円で出品した商品が勝手に1,000円に編集されて売れてしまった場合... そんな事にならないように利用して下さるユーザーが安心して使えるように記述していきましょう! 現在のコントローラの状況 itemテーブルには出品された商品情報が入っています。 (名前・値段・商品説明・商品状態など) 編集できるeditアクションと更新ができるpdateアクションを見ていきます。 def edit @item = Item.find(params[:id]) end def update if @item.update(item_params) redirect_to item_path else render :edit end editアクションでは編集したいレコードを@itemに代入し、ビューに受け渡すことで編集画面で利用できるようにします。 findはデータベースからデータを取り出したり、検索したりするためのメソッドです。 idを取得して編集ページは/items/[:id]/editとなります。 今のままでは直接上記のURLを打ち込むと出品者ではない人が編集できてしまいます。 unless文とdeviseのヘルパーメソッド! まずはunless文の紹介. if文が条件式がtrueの時に実行したのに対し、unless文は条件式がfalseの時に実行する構文です。 そしてdeviseメソッド current_user #deviseのヘルパーメソッドde"現在ログインしているユーザー"という意味 current_user == @item.user #現在ログインしているユーザーは商品を出品ユーザーと同じという意味 この2つを用いて記述すると以下になります def edit @item = Item.find(params[:id]) #もし、現在ログインしているユーザーは商品を出品ユーザーではなかった時、トップページに遷移する unless current_user == @item.user redirect_to root_path end end def update if @item.update(item_params) redirect_to item_path else render :edit end このような記述になります。 もちろんこれはupdateアクションにも使うのでbefore_actionでまとめて記述するとより可読性が上がります。 before_action :contributor_confirmation, only: [:edit, :update] def edit end def update if @item.update(item_params) redirect_to item_path else render :edit end end private def contributor_confirmation redirect_to root_path unless @item.user == current_user end
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

総合振込の全銀フォーマットファイルを作成する方法(Ruby)

総合振込で使用する「全銀フォーマット(全銀協規定形式)」のファイルを作成する方法を雑にまとめてました。 全銀フォーマットはどの銀行も似通っているかと思いますが、実装する際は必ず該当銀行の資料を読み込む事をお勧めします。 ※ 下記は GMOあおぞらネット銀行 のフォーマットになります。だいぶ愚直に書いた例です。 File.open("payout-example.txt", "w", encoding: "Shift_JIS") { |f| # 1. ヘッダー・レコード h_01 = 1 # データ区分(固定値) h_02 = 21 # 種別コード(固定値) h_03 = 0 # コード区分(固定値) h_04 = 9999999999 # 振込依頼人コード(固定値) h_05 = "#{振込依頼人名}".ljust(40) # 振込依頼人名 h_06 = Date.today.strftime("%m%d") # 振込実施日 h_07 = "0310" # 仕向銀行番号(固定値) h_08 = "ジーエムオーアオゾラネツト" # 仕向銀行名(固定値) h_09 = "#{仕向支店番号}" # 仕向支店番号 h_10 = "#{仕向支店名}".ljust(15) # 仕向支店名 h_11 = 1 # 預金種目(依頼人)(固定値) h_12 = "#{口座番号}" # 口座番号(依頼人) h_13 = "".ljust(17) # ダミー f.write("#{h_01}#{h_02}#{h_03}#{h_04}#{h_05}#{h_06}#{h_07}#{h_08}#{h_09}#{h_10}#{h_11}#{h_12}#{h_13}\r\n") # 2. データ・レコード payouts = ... payouts.each do |payout| d_01 = 2 # データ区分(固定値) d_02 = "#{payout.被仕向銀行番号}".rjust(4, "0") # 被仕向銀行番号 d_03 = "".ljust(15) # 被仕向銀行名 d_04 = "#{payout.被仕向支店番号}".rjust(3, "0") # 被仕向支店番号 d_05 = "".ljust(15) # 被仕向支店名 d_06 = "".ljust(4) # 統一手形交換所番号(固定値) d_07 = 1 # 預金種目 d_08 = "#{payout.口座番号}".rjust(7, "0") # 口座番号 d_09 = "#{payout.受取人名}".ljust(30) # 受取人名 d_10 = "#{payout.振込金額}".rjust(10, "0") # 振込金額 d_11 = 1 # 新規コード d_12 = "".ljust(10) # 顧客コード1 d_13 = "".ljust(10) # 顧客コード2 d_14 = "".ljust(1) # 振込指定区分 d_15 = "".ljust(1) # 識別表示 d_16 = "".ljust(7) # ダミー f.write("#{d_01}#{d_02}#{d_03}#{d_04}#{d_05}#{d_06}#{d_07}#{d_08}#{d_09}#{d_10}#{d_11}#{d_12}#{d_13}#{d_14}#{d_15}#{d_16}\r\n") end # 3. トレーラ・レコード t_01 = 8 # データ区分(固定値) t_02 = payouts.count.to_s.rjust(6, "0") # 合計件数 t_03 = payouts.sum(:振込金額).to_s.rjust(12, "0") # 合計金額 t_04 = "".ljust(101) # ダミー f.write("#{t_01}#{t_02}#{t_03}#{t_04}\r\n") # 4. エンド・レコード e_01 = 9 # データ区分(固定値) e_02 = "".ljust(119) # ダミー f.write("#{e_01}#{e_02}\r\n") } 参照 総合振込 -アップロードファイル作成ガイド - Ver 1.0.4 | GMOあおぞらネット銀行 全銀協規定形式(振込ファイル)| 住信SBIネット銀行
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Ruby on Rails】郵便番号にバリデーションをかけたい!【正規表現】

はじめに Ruby on Railsの学習中です。携帯番号は下記の参考文献と出会えたので解決しましたが、正規表現で郵便番号にいい感じのバリデーションをかけたいと思ったのですが、なかなかベストな文献が見当たりませんでした。そこでこちらの文献を参考に郵便番号正規表現を作成しました。 参考文献 テストするならココ 今回の理想 郵便番号は以下ならOKとします。 000-0000(数字7桁と間にハイフンが含まれる) 0000000(数字7ケタのみ) テスト環境 Rails 5.2.5 ruby 2.6.3 ①正規表現を作る 郵便番号の正規表現 \A\d{3}[-]?\d{4}\z これで\Aから始まり\zに終わる\d{3}3桁と\d{4}4桁の数字で[-]?間にハイフンが入っていても入ってなくてもOK という意味になります。 ②正規表現を試す rubular.comに移動 ①Your regular expression:に先ほどの正規表現を記載する ②Your test string:にテストしたい文字列を入れる ③Match result: マッチするか確認する ③モデルに実装する models/user.rb VALID_POSTAL_CODE_REGEX = /\A\d{3}[-]?\d{4}\z/ #正規表現を//で/正規表現/とサンドすることを忘れないよう validates :postal_code, presence: true, format: { with: VALID_POSTAL_CODE_REGEX } 以上で実装できました。 正規表現はPHP: preg_match() で何回か触れたことはありましたが、すぐ忘れるし、まだまだゼロから手書きはできません... 何かから見て学び、応用を効かせて、rubular.comで試すというルーティンで今後も正規表現と向き合って行こうと思います! ちなみにハイフンの有り無しはDB上では統一したいのでjavascriptのinputイベントで足すという方法を考えています。(ということはハイフンありの完全一致のバリデーションでもいいのでは?)
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Ruby 学習メモ

シンボル ハッシュ(連想配列)で使われることが多い exam = {'subject'=>'japanese', 'score'=>70} これを exam = {:subject=>'japanese', :score=>70} や exam = {subject: 'japanese', score: 70} と記述することができる。 また取り出す時や更新するときは puts exam[:subject] とする。 キーワード引数 メソッド作成の引数指定のこと。 def person_info(name:, age:, hometown:) puts "私の名前は#{name}で年齢は#{age}で出身は#{hometown}です" end person_info(name: "太郎", age: 23, hometown: "東京") attr_accessor クラスのインスタンス変数を読み書きできるようにする class Person def initialize(name) @name = name end end a = Person.new('mike') puts a.name このように記述してもインスタンス変数は出力することができない。 読み書きを可能にするためにはattr_accessorメソッドでインスタンス変数を読み書き可能にしなければならない。 attr_accessor :インスタンス変数もしくは'インスタンス変数' シンボルもしくは文字列で記述 class Person attr_accessor :name #'name'でもよい def initialize(name) @name = name end end a = Person.new('mike') puts a.name
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Rails6】新・JavaScriptによる「入力フォームの内容のリアルタイムチェック機能」の実装例

以前、【Rails6】JavaScriptによる「入力フォームの内容のリアルタイムチェック機能」の実装例という記事で、入力フォームのリアルタイムチェック機能の実装方法を紹介しましたが、この実装方法には以下の問題がありました。 エラーメッセージのタグをhiddenで隠しているので、フォームの中に不自然な空白がある 複数のタイプのエラーメッセージを表示しようとすると空白がさらに大きくなってしまう 今回はこれを改善し、しかもパワーアップしました。 前回と同様にjQueryのようなライブラリは使用せず、そのままのJavaScriptで実装したことが今回もポイントです。 実行環境 Rails 6.0.3.6 動作確認 今回のリアルタイムチェック機能の仕様は以下の通りです。 入力された値によって以下のエラーメッセージが表示される 半角数字以外の場合→「価格は半角数字で入力してください」 300〜9,999,999の範囲外の場合→「価格は300〜9,999,999の範囲で設定してください」 正しい値を入力するとメッセージが非表示になる Javascriptのコード メインとなるJavaScriptのコードは以下の通りです。 app/javascript/validation.js //validationイベントを定義 const validation = () => { //エラーメッセージを表示するための要素を取得して変数化 const priceErrorElement = document.getElementById("price-error"); //フォームの値が入る要素を取得して変数化 const itemPrice = document.getElementById("item-price"); //ここから半角数字での入力を促すイベント //半角数字でないものにマッチする正規表現を変数化 const pricePattern = /^\d+$/; //入力フォームでキーが離されたときにイベントが発生 itemPrice.addEventListener("keyup", e => { //idがprice-character-errorの要素(エラーメッセージ)を取得して変数化 const errorMessageCharacter = document.getElementById("price-character-error"); //入力された値が正規表現にマッチしている or 空白のとき if (pricePattern.test(itemPrice.value) || itemPrice.value == "") { //エラーメッセージが存在しているとき if (errorMessageCharacter != null) { //エラーメッセージを削除 errorMessageCharacter.remove(); } //入力された値が正規表現にマッチしていないとき } else { //エラーメッセージが存在していないとき if (errorMessageCharacter === null) { //エラーメッセージを挿入 priceErrorElement.insertAdjacentHTML('afterend', '<div id="price-character-error" class="price-error">価格は半角数字で入力してください</div>' ); } } }); //ここまで半角数字での入力を促すイベント //ここから300〜9,999,999の範囲での入力を促すイベント //最小値と最大値を変数化 const minimumPrice = 300; const maximumPrice = 9999999; //入力フォームでキーが離されたときにイベントが発生 itemPrice.addEventListener("keyup", e => { //idがprice-range-errorの要素(エラーメッセージ)を取得して変数化 const rangeErrorMessage = document.getElementById("price-range-error"); //入力された値が300より小さい or 9,999,999より大きいとき if (itemPrice.value < minimumPrice || itemPrice.value > maximumPrice ) { //エラーメッセージが存在していないとき if (rangeErrorMessage === null) { //エラーメッセージを挿入 priceErrorElement.insertAdjacentHTML('afterend', '<div id="price-range-error" class="price-error">価格は300〜9,999,999の範囲で設定してください</div>' ); } //入力された値が300以上 or 9,999,999以下のとき } else { //エラーメッセージの要素が存在しているとき if (rangeErrorMessage != null) { //エラーメッセージを削除 rangeErrorMessage.remove(); } } }); //ここまで300〜9,999,999の範囲での入力を促すイベント } //ページが読み込まれた(load)ときに、validationイベントを実行 window.addEventListener("load", validation) 上記validation.jsをapplication.jsで読み込むことを忘れないようにしましょう。 app/javascript/packs/application.js require("../validation") Viewのコード エラーメッセージを入れたい箇所に以下の要素を記述します。 new.html.erb <div id="price-error"></div>
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

学習ノート:システムテスト再入門

この記事の内容 プロダクトの作成中、設定がいまいちだったためにシステムテストに徐々に不具合が出てくるようになった。リファクタリングをするとともに、システムテストについて今一度しっかり勉強して、ノートにまとめてみた。 対象読者は、今までコピペでテスト周りの設定をしていたけれど、それをしっかり理解しながら自分でやってみたい人。 システムテストを構成する要素 この記事はいくつかのパートに分かれていますが、前半のこの部分は、主にこちらの記事の内容をまとめたもの。 2020年のRailsでブラウザテストを「正しく」行う方法(翻訳) システムテストには、以下の三つの要素が必要とのこと。 テストランナー ... RSpec, Minitest など テストサーバー ... WEBrick, Puma など ブラウザー ... 後述 テスト用のブラウザについて 上記のうちブラウザについては、テスト用のブラウザもいくつか開発された。一方で、「現実のブラウザを使う」という体験に追いつくのは難しかった。 Seleniumとは ブラウザの自動化テストで勝ち残ってきたソフトの一つ。ブラウザごとの差異に対応してテストを実施できた。 転機とCDP ChromeがCDPプロトコルを提供して、ブラウザを直接操作できるようになった。 CDPを利用したプロジェクト代表例 Pupetter ... Node.js用ブラウザ自動化ライブラリ Ferrum ... Ruby向けCDPライブラリ このうちFerrumについては、以下の利点もある。 Pupetterとの互換性も保たれている。 Cuprite(CupriteはピュアRuby製Capybaraドライバ、CDP使用)も同梱されている。 WebDriverとは WebDriverとは本来はプロトコルらしい(ソースはこちらの記事)。そして、そのプロトコルを使って操作をするのが、WebDriverToolであるとのこと。 主要ブラウザごとに Chrome ...chromedriver Firefox ... geckodriver MS Edge ... edgedriver Safari ... safaridriver があるそう。 Rails6では、デフォルトでそれらをまとめてwebdriversというGemでDLしてくる。そして、Capybaraのデフォルトの設定でそれを使うようになっている。 WebDriverとSelenium-Webdriber WebDriverはそれが呼び出された時に、Selenium-Webdliverを拡張して呼び出す。 ブラウザごとに最新のWebDriverツールをDLしてきて、それらがSelenium-Webdliverで使えるようにする。 システムテスト関連の、設定ファイルの読み方 このように、システムテストには色々なツールが関わっている。 そして、「色々なツールが関わっている」ためにシステムテストの設定ファイルを読み解くのが、当初は少し難しかった。 例えば、こんなコードがあったとする Selenium::WebDriver::Remote::Capabilities.chrome( ... ) Capybara::Selenium::Driver.new( ... ) この時、1行目はSeleniumの設定で、2行目はCapybaraの設定になる。 上記で、.chromeはSeleniumの下位クラスのメソッドで、や.newはCapybaraの下位クラスのメソッド。 つまり、機能の詳細を知りたいときは一番左に書いてある名前のもののドキュメントを見れば良いのだが、どれも同じような名前なので、最初はとてもわかりにくかった。 ちなみに、参考にしたドキュメントはこちら。 Capybara ... GithubのReadme Selenium ... Seleniumのドキュメントページ なお、設定ファイル中に、こんな記述もよく出てくると思う。 RSpec.configure do |config| config.fixture_path = "#{::Rails.root}/spec/fixtures" # さまざまな設定が続く ... end この時のconfigはブロックを囲んでいるRspecの設定で、fixture_pathはRspecのメソッド。こちらも似たような記述が多いので、今、何の設定をしているのかを見失わないように注意。 rails_helper と spec_helper 設定ファイルを書く場所には rails_helperとspec_helperがありますが、基本的にはrails_helperに書けば良さそう。 spec_helper ... Railsに依存しないSystem Testを書くためのファイル rails_helper ... RailsにおけるSystem Testの設定を書くためのファイル らしいのだけど(参考:「RSpec 3 時代の設定ファイル rails_helper.rb について」)、あまりRailsに依存しないsystem specを書く人はいないと思うので。。。 rails_helperの自動生成されるコードを見ても、上の方に spec/rails_helper require 'spec_helper' と入っている。spec_helperの設定を読み込んでからrails_helperを動かしているのがわかる。 そして、それぞれのspecファイルでは require 'rails_helper' RSpec.describe 'SomeModelSpec', type: :model do # ... end というように、rails_helperを読み込んでいるので、両者の設定が反映される。 ちなみに、どちらかの設定ファイル(大概rails_helper)にこのような記述があれば Dir[Rails.root.join('spec/support/**/*.rb')].sort.each { |f| require f } これはspec/supportディレクトリ下にある設定も読み込むということなので、そちらの設定も確認する。 余談:Systemテストになって不要だったもの なお、システムテストに関しては古い記事もたくさんあり、コピペでなんとなく導入していたら、実際には不要になったものもたくさんあった。 system specが導入された当時に、その新機能を紹介した記事はこちら。 Rails 5.1以降のシステムテストをRSpecで実行する(翻訳) システムテストでは、「データベースのロールバック」「テストが失敗したときのスクリーンショット自動撮影」など機能が備わっているので、もし、以下の導入を紹介する記事があったら、それらは基本的には不要です。 capybara-screenshot ... capybaraでscreen shotをとってくれるGem database_cleaner ... テスト後、データベースの掃除をしてくれるgem 以上、まとまらない内容ですが、システムテストの設定ファイルをしっかり読みたい人の助けになればと思います。。。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Capistrano自動デプロイ時に (SSHKit::Runner::ExecuteError)エラーの解決法

はじめに Capistrano自動デプロイ時に (SSHKit::Runner::ExecuteError)エラーが出たのでその解決法を書いておきます。 エラー内容 Terminal # プロジェクトのディレクトリ $ bundle exec cap production deploy SSHKit::Runner::ExecuteError: Exception while executing as ec2-user@ElasticIP: Authentication failed for user ec2-user@ElasticIP Caused by: Net::SSH::AuthenticationFailed: Authentication failed for user ec2-user@ElasticIP Tasks: TOP => rbenv:validate (See full trace by running task with --trace) 原因 インスタンスを再起動したことで、 sshディレクトリにキーペアがなくなってしまったことが原因だったので 再度追加します。 以下方法です。 解決法 Terminal # [~/.ssh] $ ssh-add ~/.ssh/peachbranch.pem
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Errno::ENOSPCが表示された時

rails sでサーバーを立ち上げようとすると、Errno::ENOSPCの表示が。 エラー内容 まずこのエラーの内容を確認すると、「No space left on device」の文字が確認でき、これは容量不足を示しています。 こいつが起きると何も操作ができなくなってしまい、だいぶやっかいです。 この容量不足には、ディスクの容量不足とinodeの容量不足の2パターンがあります。 解決に向けて  ※出力結果は例となります。 まずは以下コマンドにて、現在の使用容量を確認します。 ターミナル $ df >ファイルシス 1K-ブロック 使用 使用可 使用% マウント位置 devtmpfs 492676 0 492676 0% /dev tmpfs 503448 0 503448 0% /dev/shm tmpfs 503448 472 502976 1% /run tmpfs 503448 0 503448 0% /sys/fs/cgroup /dev/xvda1 8376300 5655364 2720936 68% / tmpfs 100692 0 100692 0% /run/user/1000 ここでは使用%という部分が、現在のディスク使用率を表示しています。 ここが100%になっていれば、ディスク容量が一杯になっています。 ※ここでは容量不足解消後の出力結果なので、100%のものはありません。 続いてinodeの容量確認ですが、こちらは先ほどのコマンドに-iを追加します。 ターミナル $ df -i >ファイルシス Iノード I使用 I残り I使用% マウント位置 devtmpfs 123169 284 122885 1% /dev tmpfs 125862 2 125860 1% /dev/shm tmpfs 125862 373 125489 1% /run tmpfs 125862 16 125846 1% /sys/fs/cgroup /dev/xvda1 4193216 127452 406576 4% / tmpfs 125862 1 125861 1% /run/user/1000 こちらもI使用%という部分を確認して、ここが100%になっていれば、inodeの容量不足となります。 上記コマンドで容量不足の確認ができたところで、不要なファイルを削除していきます。 まず、どのファイルが容量を圧迫しているか確認する必要があるので、以下コマンドで確認します。 ターミナル $ find / -xdev -type f | cut -d "/" -f 2 | sort | uniq -c | sort -nr > 59177 usr 33328 home 4025 var 526 etc 16 opt 13 boot 1 swapfile1 1 .autorelabel こんな感じで、左側にファイル数、右側にディレクトリが表示されるかと思います。 ファイル数が多いものが容量を圧迫しているので、更にその中で圧迫の原因となっているものを探っていきます。 先ほどの出力結果だと、usrディレクトリのファイル数が多かったので、これを更に深めていきます。(findの後に確認したいディレクトリ名を記載します。) ターミナル $ find /usr -xdev -type f | cut -d "/" -f 3 | sort | uniq -c | sort -nr > 28277 share 17869 lib 7387 lib64 3676 include 929 bin 526 local 377 sbin 136 libexec ここではディレクトリ別のファイルが表示されています。この操作によって、ファイル数が多く、不要なディレクトリを探します。 上記コマンドでディレクトリを特定できれば、次はそれを削除していきます。 削除する時は、以下コマンドを使用します。 ターミナル $ sudo rm -rf ディレクトリ名 例えば先ほどの出力結果だと、usr/shareが多かったので、これを削除する場合、 「$ sudo rm -rf usr/share」となります。 このコマンドは-rfがついているため、コマンドを実行すると強制的に削除が実施されるので、必要なファイルを削除しないようにご注意ください。 不要なファイルを削除したらもう一度、「df (-i)」コマンドにて使用率を確認して、使用容量が減っているか確認してみてください。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Vite Ruby で 爆速で Rails + Vue3 + TypeScript 環境を作成する!

Introduction みなさん、Vitejs というのはご存知でしょうか? https://vitejs.dev/ 手間のかかるフロントエンド環境の構築をまとめてやってくれる優れものです。 お好みのフレームワークと開発言語(js or ts)を選択すれば爆速で構築してくれます。 こちらの Ruby統合環境 (Vite Ruby) を作成されている方がいるようでしたので 早速試していこうと思います♪ (個人的には Rails + Vue3 環境が素早く構築できると 嬉C) 初期リリースは2021年1月のようですね。 ? Commits on Jan 19, 2021 https://github.com/ElMassimo/vite_ruby/releases/tag/v1.0.0 Getting Started 早速、試そうとドキュメントを漁ります。 https://vite-ruby.netlify.app/guide/ これ見た限り、既存のRailsプロジェクトにインストールするスタイルみたいですね とりあえず、通常の Rails + Vue 構成でセットアップしてみますか Railsプロジェクトの作成 # 個人の環境に合わせてください $ mkdir -p ~/projects/vite_ruby_sample $ cd ~/projects/vite_ruby_sample # オプションはお好みで... (今回は Rails + Mysql + Vue) $ bundle exec rails new . --database=mysql --webpack=vue --skip-turbolinks --skip-test-unit --skip-coffee --skip-test --skip-active-storage # とりあえずDBのセットアップもやっておく $ mysql.start $ bin/rails db:prepare ViteRubyのインストール vite-rubyのinstallationに従います。 https://vite-ruby.netlify.app/guide/#installation-%F0%9F%92%BF Gemfile gem 'vite_rails' $ bundle $ bundle exec vite install Creating binstub Check that your vite.json configuration file is available in the load path: No such file or directory @ rb_sysopen - ~/projects/vite_ruby_sample/config/vite.json Creating configuration files Installing sample files Installing js dependencies yarn add v1.22.10 [1/4] Resolving packages... [2/4] Fetching packages... [3/4] Linking dependencies... [4/4] Building fresh packages... success Saved lockfile. success Saved 14 new dependencies. info Direct dependencies ├─ vite-plugin-ruby@2.0.4 └─ vite@2.3.2 info All dependencies ├─ @nodelib/fs.scandir@2.1.4 ├─ @nodelib/fs.stat@2.0.4 ├─ @nodelib/fs.walk@1.2.6 ├─ esbuild@0.11.20 ├─ fast-glob@3.2.5 ├─ fastq@1.11.0 ├─ merge2@1.4.1 ├─ nanoid@3.1.23 ├─ queue-microtask@1.2.3 ├─ reusify@1.0.4 ├─ rollup@2.47.0 ├─ run-parallel@1.2.0 ├─ vite-plugin-ruby@2.0.4 └─ vite@2.3.2 Done in 12.04s. Could not install JS dependencies. npx: 1個のパッケージを3.803秒でインストールしました。 warning " > vue-loader@15.9.7" has unmet peer dependency "css-loader@*". Adding files to .gitignore Vite ⚡️ Ruby successfully installed! ? これで vitejs もインストールされるようですね。 【追加されたファイル】 bin/vite vite.config.ts config/vite.json 【変更があったファイル】 app/javascript/entrypoints/application.js // To see this message, add the following to the `<head>` section in your // views/layouts/application.html.erb // // <%= vite_client_tag %> // <%= vite_javascript_tag 'application' %> console.log('Vite ⚡️ Rails') // If using a TypeScript entrypoint file: // <%= vite_typescript_tag 'application.jsx' %> // // If you want to use .jsx or .tsx, add the extension: // <%= vite_javascript_tag 'application.jsx' %> console.log('Visit the guide for more information: ', 'https://vite-ruby.netlify.app/guide/rails') // Example: Load Rails libraries in Vite. // // import '@rails/ujs' // // import Turbolinks from 'turbolinks' // import ActiveStorage from '@rails/activestorage' // // // Import all channels. // import.meta.globEager('./**/*_channel.js') // // Turbolinks.start() // ActiveStorage.start() // Example: Import a stylesheet in app/frontend/index.css // import '~/index.css' app/views/layouts/application.html.erb <!DOCTYPE html> <html> <head> <title>ViteRubySample</title> <meta name="viewport" content="width=device-width,initial-scale=1"> <%= csrf_meta_tags %> <%= csp_meta_tag %> <%= stylesheet_link_tag 'application', media: 'all' %> <%= javascript_pack_tag 'application' %> <%= vite_client_tag %> <%= vite_javascript_tag 'application' %> <!-- If using a TypeScript entrypoint file: vite_typescript_tag 'application' If using a .jsx or .tsx entrypoint, add the extension: vite_javascript_tag 'application.jsx' Visit the guide for more information: https://vite-ruby.netlify.app/guide/rails --> </head> <body> <%= yield %> </body> </html> Viteのセットアップ とのことで、上記からプラグインを選んでインストールします 今回は Vue3 を利用するので下記を選択しました $ yarn add -D @vitejs/plugin-vue その他依存関係もインストールします $ yarn add -D @vue/compiler-sfc $ yarn add -D typescript # Rails作成時のvueが2系なのでアップデート $ yarn add vue@next # vue3 vite.config.ts import { defineConfig } from 'vite' import RubyPlugin from 'vite-plugin-ruby' import vue from '@vitejs/plugin-vue' // https://vitejs.dev/config/ export default defineConfig({ plugins: [ RubyPlugin(), vue() ], }) とりあえず実行してみる 下記によると bin/vite でviteサーバーを起動できるようなので試してみましょう! https://vite-ruby.netlify.app/guide/development.html#developing-with-vite $ bin/vite Commands: vite build # Bundle all entrypoints using Vite. vite clobber # Clear the Vite cache, temp files, and builds vite dev # Start the Vite development server. vite install # Performs the initial configuration setup to get started with Vite Ruby. vite version # Print version っと、さらにオプションがある模様ですね $ bin/vite dev vite v2.3.2 dev server running at: > Local: http://localhost:3036/vite-dev/ > Network: use `--host` to expose ready in 404ms. 起動したみたいですが、よくわからないですね? (webpack-dev-serverみたいなものと思っておきましょう) 気にせず、いつものRails&Vueのようにアクション作成しましょうか... layouts/application.html.erbでコンパイルしたjsが返るようになってますので、下記だけでいいですね。 $ bin/rails g controller vue index とりあえず、これだけ。 さっそく、実行してみましょう! $ bin/rails server -b 0.0.0.0 -p 3000 => Booting Puma => Rails 6.1.3.2 application starting in development => Run `bin/rails server --help` for more startup options Puma starting in single mode... * Puma version: 5.3.1 (ruby 2.7.2-p137) ("Sweetnighter") * Min threads: 5 * Max threads: 5 * Environment: development * PID: 49577 * Listening on http://0.0.0.0:3000 Use Ctrl-C to stop $ open 'http://0.0.0.0:3000/vue/index' 下記のように表示されました! ちゃんと 'Vite ⚡️ Rails' と表示されてます 接続は大丈夫そうですね! Vueを表示してみる いよいよ本番と、vue3 + ts で記述して表示できるか試してみましょう! app/views/vue/index.html.erb <div id="app"></div> app/javascript/entrypoints/application.js import { createApp } from 'vue' import App from '../app.vue' document.addEventListener('DOMContentLoaded', () => { createApp(App).mount('#app') }) app/javascript/app.vue <template> <p>{{ state.message }}</p> </template> <script lang="ts"> import { defineComponent } from 'vue' export default defineComponent({ name: 'App', setup() { return { state: { message: "Hello Vue3 + TypeScript!" } } } }) </script> <style scoped> p { font-size: 2em; text-align: center; } </style> ページを更新して、いざ、表示! おぉー、表示されましたね。 これで気軽に Rails + Vue3 + TypeScript 環境で開発できますね! まとめ 今回は、爆速で Rails + Vue3 + TypeScript 環境 を構築してみました Vite Ruby を利用することで Rails 環境でも vitejs が気軽に導入できるようになりました 移り変わりの早いフロントエンドに対応していくためにも Vite Ruby で Rails環境を構築してみてはいかがでしょうか? ではでは ? LINKS vitejs https://vitejs.dev/ vite ruby https://vite-ruby.netlify.app/
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Rails in Docker × Rspec with Capybara × selenium_driver

概要 これらの記事を参考にCapybaraのテスト実行環境を :rack_test → :seluniumへ変更致しました。(とても参考になりました。ありがとうございました!) この記事では変更点だけを羅列しますが、注意点としましては、gem 'rspec-rails', '>= 4.0.2'こいつだけバージョンの指定が必要である、という事です。 これは2個目の記事に参考にさせていただきました! 動作環境とバージョンについて ruby 2.6.6 Rails 6.1.3 rspec-rails 5.0.1 selenium-webdriver 3.142.7 capybara 3.35.3 結論 Gemfile + gem 'rspec-rails', '>= 4.0.2' + gem 'capybara' + gem 'selenium-webdriver' docker-compose.yml version: '3' services: db: image: mysql:8.0 environment: MYSQL_ROOT_PASSWORD: password ports: - '3306:3306' command: --default-authentication-plugin=mysql_native_password volumes: - mysql-data:/var/lib/mysql web: build: . command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'" volumes: - .:/myapp ports: - "3000:3000" depends_on: - db + - chrome stdin_open: true tty: true + chrome: + image: selenium/standalone-chrome:latest + ports: + - 4444:4444 stdin_open: true tty: true chrome: image: selenium/standalone-chrome:latest ports: - 4444:4444 volumes: mysql-data: driver: local rails_helper.rb -# Dir[Rails.root.join('spec', 'support', '**', '*.rb')].sort.each { |f| require f } +Dir[Rails.root.join('spec', 'support', '**', '*.rb')].sort.each { |f| require f } : +Capybara.register_driver :remote_chrome do |app| + url = "http://chrome:4444/wd/hub" + caps = ::Selenium::WebDriver::Remote::Capabilities.chrome( + "goog:chromeOptions" => { + "args" => [ + "no-sandbox", + "headless", + "disable-gpu", + "window-size=1680,1050", + ], + } + ) + Capybara::Selenium::Driver.new(app, browser: :remote, url: url, desired_capabilities: caps) +end RSpec.configure do |config| + config.before(:each, type: :system) do + driven_by :rack_test + end + + config.before(:each, type: :system, js: true) do + driven_by :remote_chrome + Capybara.server_host = IPSocket.getaddress(Socket.gethostname) + Capybara.server_port = 3000 + Capybara.app_host = "http://#{Capybara.server_host}:#{Capybara.server_port}" + end config.include FactoryBot::Syntax::Methods # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures config.fixture_path = "#{::Rails.root}/spec/fixtures" .rspec ---require spec_helper +--require rails_helper --format documentation 最後まで目を通していただきありがとうございました!!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

フォームからパラメータとしてコントローラーに値を送る方法

プルダウンで選択したユーザーの情報をparamsで扱えるようにパラメーターを送ります。 <select name="room[user_ids][]"> <option value="">チャットするユーザーを選択してください</option> <% User.where.not(id: current_user.id).each do |user| %> <option value=<%= user.id %>><%= user.name %></option> <% end %> </select> select要素のname属性に"room[user_ids][]"を指定し、option要素のvalue属性にuser.idを指定しました。このように記述することでparamsは以下のようになります。 {"room" => {"user_ids" => ["選択したユーザーのid"]}} room[user_ids]という記述は値としてハッシュをさらに入れ子にすることを示しています。 room[user_ids]で送られるparamsの中身↓ {"room" => {"user_ids" => "値"}} 次に、末尾の[]の記述はキーに対する値を配列として格納することを示しています。これにより1つのキーに対して、複数の値を受け取ることができます。 room[user_ids][]で送られるparamsの中身↓ {"room" => {"user_ids" => ["値"]}} 以上の仕組みを利用して、選択したユーザーの情報をコントローラーへ送信できました。 しかし、現状のままですと現在ログインしているユーザーのidをparamsで送信することができていません。 (User.where.not(id: current_user.id)としているためです。) 現在ログイン中のユーザーのidも一緒にparamsでコントローラーへ送信できるように以下の記述を追加しました。 <select name="room[user_ids][]"> <option value="">チャットするユーザーを選択してください</option> <% User.where.not(id: current_user.id).each do |user| %> <option value=<%=user.id%>><%= user.name %></option> <% end %> </select> <input name="room[user_ids][]" type="hidden" value=<%= current_user.id %>> type属性に"hidden"を指定することで画面上には表示されないinput要素を作成できます。 name属性に"room[user_ids][]"を指定し、value属性にはcurrent_user.idを指定しています。 この記述でparamsは以下のようになります。 {"room" => {"user_ids" => ["選択したユーザーのid", "現在ログインしているユーザーのid"]}} room[user_ids]に2種類のユーザーidを格納することができました。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Railsで全ユーザーにメールを送信する

はじめに メールの送信機能を初めて実装したので、躓いたところや実装方法をメモとして残しておきます。 質問回答アプリで新規質問が投稿された際に、全員に対して質問があった旨をメールで通知する。 Action Mailer Action Mailerを使うと、アプリケーションのメイラークラスやビューでメールを送信することができる。メイラーの動作はコントローラときわめて似通っている。メイラーはActionMailer::Baseを継承し、app/mailersに配置され、app/viewsにあるビューと結び付けられる。 Mailer作成手順 メイラーを作成 rails g mailer QuestionMailer app/mailers/application_mailer.rb class ApplicationMailer < ActionMailer::Base default from: "from@example.com" layout 'mailer' end 開発環境でメール送信を確認する方法 mailcatcher シンプルなsmtpサーバを立てて、送信されたメールをブラウザ上で確認できるようにしてくれる。 (cloud9でmailcatcherを実行しようとしたら、うまく実行出来ず原因はcloud9ではないかと考えられる。なので、メール確認のために代わりにletter_opener_webを使用しました。) letter_opener_web ローカル開発環境で送信したメールをブラウザ上で確認することができる http://localhost:3000/letter_openerにアクセスすることで送信されたメールを確認できる cloud9で使う方法 gemを追加 Gemfile group :development do gem 'letter_opener_web' end ルーティング config/routes.rb mount LetterOpenerWeb::Engine, at: '/letter_opener' if Rails.env.development? config デフォルトURLを指定(cloud9バージョン) config/environments/development.rb config.action_mailer.default_url_options = { host: 'myapp.c9users.io/', port: $PORT, protocol: 'https' } config.action_mailer.delivery_method = :letter_opener_web 質問があった際に全員に対して質問があった旨をメールで通知する app/mailers/question_mailer.rb class QuestionMailer < ApplicationMailer default from: 'qanda@example.com' def creation_email(user) @user = user mail(subject: '新規質問です',to: user.email, from: "qanda@example.com") end def self.creation_email_questions @users = User.all @users.each do |user| QuestionMailer.creation_email(user).deliver_now end end end app/controllers/questions_controller.rb def create @question = current_user.questions.new(question_params) if @question.save QuestionMailer.creation_email_questions redirect_to questions_url, notice: "質問を「#{@question.title}」投稿しました。" else render :new end end 躓いたところ これでも、全ユーザーにメールを送信することは可能だが、考え方が少し複雑な上にメイラーのビューで質問のタイトルや内容を表示するために@question使えない。あと、メーラにクラスメソッドを定義するやり方はあまりやらない。 改善するには メーラのクラスメソッドで定義されている全ユーザーを取り出す処理をquestions_controllerで定義すれば、メーラにクラスメソッドを定義しなくても良くなる! app/controllers/questions_controller.rb def create @question = current_user.questions.new(question_params) if @question.save User.all.each do |user| QuestionMailer.with(user: user, question: @question).creation_email.deliver_now end redirect_to questions_url, notice: "質問を「#{@question.title}」投稿しました。" else app/mailers/question_mailer.rb def creation_email @user = params[:user] @question = params[:question] mail(subject: '新規質問',to: @user.email, from: "qanda@example.com") end このようにwith(question: @question)と書くことでメイラーのアクションでparams[:question]が使えるようになり、ビューでも@questionが使えるのでメールの内容を表示することができるようになる。あとはビューを編集して完成。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Ruby技術者認定試験Silverに合格したので概要と勉強法などを載せておく

この度Ruby技術者認定試験Silver (正式名称:Ruby Association Certified Ruby Programmer Silver version 2.1)に合格したので勉強法を載せておきます。 この記事はSilverに特化して書いています。 この記事の対象者 Rubyを扱っている方 Silverを取得するために勉強中の方 I love Rubyな方 はじめに 所要日数:約2ヶ月 使用した書籍:[改訂2版]Ruby技術者認定試験合格教本(Silver/Gold対応)Ruby公式資格教科書 上記書籍における正誤表はこちらを参照してください。 試験概要 試験概要の詳細や試験申し込み方法、Gold等については公式HPをご覧ください。 合格ラインは50問中およそ37問です。 Silver 試験時間     90分 試験方法     コンピュータ試験(CBT:Computer Based Testing) 問題数(方式) 50 問(選択式) 合格ライン    75 % 対象バージョン Ruby2.1.x 出題範囲     文法 コメント、リテラル (数値、真偽値、文字列、文字、配列、ハッシュ等)、変数/定数とスコープ、演算子、条件分岐、ループ、例外処理、メソッド呼び出し、ブロック、メソッド定義、クラス定義、モジュール定義、多言語対応組み込みライブラリ よく使用されるクラス、モジュール (Object、数値クラス、String、Array、Hash、Kernel、Enumerable、Comparable等) オブジェクト指向 ポルモルフィズム、継承、mix-in 料金       16,500円(税込) (2021年 5月時点) [改訂2版]Ruby技術者認定試験合格教本におけるSilverの範囲について 今回使用した書籍はGoldの範囲含めて全6章(ただし基礎力確認問題、模擬試験を除く)で構成されていますが、Silverの出題範囲が判りにくかったので大まかにまとめておきます。 書籍内の各章の範囲とは若干のズレがありますがご了承ください。 1〜2章は試験概要と実行環境、6章はGoldの範囲なので「-」とします。 章 ページ数 1 - 2 - 3 28〜98, 107〜112 4 116〜120, 132〜134 5 174〜284, 299〜308 6 - 勉強法 2ヶ月間、1をしながら2, 3をするイメージで4までを繰り返し実行していきます。 各章を多少集中しながら流し読み 書籍内で解らない箇所はネットで調べる 書籍内にコードが出てきたらターミナルでirbを実行して実際にコードを動かしてみる 試験当日の2週間前から基礎力確認問題、模擬試験を満点になるまで解く ポイントはとにかく繰り返すことです。 5章は特に出題されやすく、且つ覚える事が多いのでより実際に手を動かしつつ集中して取り組む必要があると思います。 また、正規表現は日頃あまり馴染みがない分どうしても記憶に定着しづらいと思うので、ドットインストールの正規表現を一度目を通しておくのも良いと思います。 基礎力確認問題、模擬試験の答え合わせの際は間違えた部分の解説を読むだけでなく正解した問題の解説も読むようにするとポイントなどが記載されている場合があるので記憶が強化されます。 何度でも間違えたりわからない部分については手書きのノートやメモ帳などにまとめておくのも効果的です。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

��【Ruby演算子】「&&、&、and」や「|| 、| 、or」 の違い

はじめに 下記の各式の違いがわからず、調べた際に時間がかかったため、調べたことをまとめておきます。 「普段「&&」や「&」を雰囲気で使っているが、実際どう違うの?」という方の参考になれば幸いです。 (p false) && (p true) (p false) and (p true) (p false) & (p true) この記事を書いている人 実務経験1年未満のエンジニア 対象読者 上記各式の実行結果に確信がない方(一番最後に実行結果書いています) 「&&、&、and」や「|| 、| 、or」がどう違うか改めて確認したい方 環境 Ruby 2.4.9 分類早見表 (これを見てわかる方はここまでで大丈夫です。下記の分類についての説明をこれ以降します。) 記号 分類① 分類② &&、and 制御構造 論理演算子(これらの違いは演算子の優先順位) ‖、or 制御構造 論理演算子(これらの違いは演算子の優先順位) & メソッド Integer#&、Array#&、True(False,Nil)#& ❘ メソッド Integer#&、Array#&、True(False,Nil)#& *演算子の優先順位 参考: Ruby リファレンスマニュアル *レシーバー メソッドの呼び出し元のオブジェクト 分類①について 演算子は制御構造とメソッドの2種類に分類される 制御構造 = ?: .. ... not && and || or :: メソッド | ^ & <=> == === =~ > >= < <= << >> + - * / % ** ~ +@ -@ [] []= ` ! != !~ 参考: Rubyリファレンスマニュアル(演算子式) *制御構造 コンピュータプログラムで、命令が実行される流れを定めたもの 参考: Rubyリファレンスマニュアル(制御構造) 分類②について 論理演算子 複数の式に対して、式全体の真偽を判定するもの(この判定の仕方が論理演算子毎に異なる) 式の評価は式全体の真偽が決定した時点で終わり、最後に評価した式の戻り値が式全体の戻り値となる &&(論理積) 式の全てが、真の場合に真 ||(論理和) 式の少なくとも1つが、真の場合に真 参考: 論理演算子 Integer#&、Array#&、True(False,Nil)#& 「&」や「|」はメソッドのため、レシーバー(呼び出し元のオブジェクト)によって挙動が変わる点に注意 (* 「Integer#&」、「Array#&」はここでは直接関係ない内容のため説明を省略します。) True(False,Nil)#& 「true、false、nil」に対して呼び出す場合は、True(False,Nil)クラスのインスタンスメソッド ポイントしては、両辺(厳密にはレシーバーと引数の両方)の式が評価される (各メソッドの挙動については下記参照) #「True#&」は引数が偽であれば、falseを返す (p true) & (p "hoge") true "hoge" => true (p true) & (p false) true false => false #「False#&、Nil#&」は引数に関わらず、falseを返す (p false) & (p true) false true => false (p false) & (p false) false false => false 参考: Rubyリファレンスマニュアル(True#&) 参考: Rubyリファレンスマニュアル(False#&) 参考: Rubyリファレンスマニュアル(Nil#&) まとめ 上記を踏まえ、両辺(の式の戻り値)が「true、false、nil」となる場合に実際の評価の流れがどうなるか 式 実行結果 左辺 && 右辺 左辺が「false、nil」ならそこで評価終了 (「and」も同様) 左辺 & 右辺 左辺が「false、nil」でも右辺を評価 左辺 ‖ 右辺 左辺が「true」ならそこで評価終了 (「or」も同様) 左辺 ❘ 右辺 左辺が「true」でも右辺を評価 備考:実行結果(irb) (p false) && (p true) false => false (p false) and (p true) false => false (p false) & (p true) false true => false
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

引数の種類

引数には種類があって、区別できていなかったので基本的なことを整理する。 引数 定義における値の受け渡しの基本 def メソッド名(仮引数) # メソッドの定義 式... end メソッド名(実引数) # メソッドの呼び出し 仮引数 メソッド定義において、メソッド呼び出しで与えられた実引数を受け取る変数。 スコープはローカル変数と同じで再代入できる。 仮引数に代入を行っても呼び出し側には影響を与えない。 仮引数にデフォルト式が与えられた場合は、実引数の省略時にデフォルト値となる。 def foo(par = 'hoge') #デフォルト式(=)、値('hoge') puts par end foo #実引数を省略した時 #=> "hoge"  foo(bar) #実引数を明示した時 #=> "bar" 実引数 メソッド呼び出しにおいてメソッドに与えられる値。 実引数には式を与える 全ての式が評価されてからメソッドが呼び出される。 キーワード引数 キーワードによって特定される引数。 ハッシュ形式で引数を設定できる。 呼び出しは、「シンボル:値」の形式で指定する。 デフォルト値が設定されている場合は実引数を省略できる。 定義時にデフォルト値の指定がなければ実引数を省略するとエラーになる。 def person(name: 'taro', age: '20' ) puts "#{name}, #{age}" end person #=> "taro, 20" person(name: 'hana', age:) #=> "hana, 20" person(country: 'japan') #=> ArgumentError (unknown keyword: country) 可変長引数(rest引数) *仮引数名で、複数の引数を設定できる。 引数は配列として格納される。 def foo(x, *xs) puts "#{x}:#{xs.inspect}" # inspectは、オブジェクトや配列を分かりやすく返すメソッド。 end foo(1) #=>1:[] foo(1,2) #=>1:[2] foo(1,2,3) #=>1:[2,3] オプション引数 **仮引数名で、可変長引数と同じように制限なく引数を設定できる。 キーを引数として渡すことができる。 ハッシュ形式で値を扱う。 def foo(**bar) puts bar end foo #=> {} foo(key1: '1', key2: '2') #=> {:key=>"1", :key2=> "2" } ブロック引数 &仮引数名でブロックを引数として受け取ることができる。 def foo(cnt, &block_arg) cnt.times { block_arg.call } end #.timesは、繰り返し処理を行うメソッド #.callは、ブロックを呼び出すメソッド foo(3) { print "Ruby!" } # {}ブロックの部分 #=> Ruby!Ruby!Ruby! Ruby 2.3.0 リファレンスマニュアル > クラス/メソッドの定義 プロを目指す人のためのRuby入門/著者:伊藤淳一
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

FeedjiraでRSSの独自タグ拡張

FeedjiraでRSSの独自タグ拡張 feedjira gemを利用した独自タグ拡張の方法について説明します。 Feedjiraには add_common_feed_entry_element というメソッドがあります。 https://www.rubydoc.info/github/feedjira/feedjira/master/Feedjira/Feed#add_common_feed_entry_element-class_method ドキュメントがなくコードを読んでも https://github.com/feedjira/feedjira/blob/master/lib/feedjira/feed.rb#L18 だいぶ深追いしないと把握できないのでとりあえずどういう動きをするのかを説明します。 シンプルな構造の場合(ネストしていない) 以下のような my:tag という独自タグが含まれるRSSがあったとします <?xml version="1.0" encoding="UTF-8"?> <rss version="2.0" xmlns:media="http://search.yahoo.com/mrss/" xmlns:content="http://purl.org/rss/1.0/modules/content/" > <channel> <title>サイトタイトル</title> <link>https://example.com/</link> <description>サイト説明</description> <pubDate>Mon, 19 Jun 2020 09:00:00 7JunJST</pubDate> <language>ja</language> <copyright>誰か</copyright> <item> <title><![CDATA[タイトル]]></title> <link>https://example.com/item/1</link> <guid>https://example.com/item/1</guid> <description><![CDATA[ディスクリプション]]></description> <pubDate>Mon, 19 Jun 2020 02:55:52 2JunJST</pubDate> <content:encoded><![CDATA[ コンテンツ本文 ]]></content:encoded> <!-- 独自タグ --> <my:tag link="https://example.com/" title="example">独自タグ</my:tag> <!-- /独自タグ --> </item> </channel> </rss> 独自タグ部分をparseしてFeedjiraのentryオブジェクトに追加したい場合 <my:tag link="https://example.com/" title="example">独自タグ</my:tag> 普通にFeedjira::parseしただけでは取得できません。 そこで add_common_feed_entry_element の登場です。 Feedjira::Feed.add_common_feed_entry_element("my:tag", as: :my_tag) このように書くことでFeedjiraのentryオブジェクトにmy_tagという名前で追加されタグのinner textを取得することが出来ます。 Feedjira::Feed.add_common_feed_entry_element("my:tag", :as => :my_tag) resp = Faraday.get('http://example.com/feed') feed = Feedjira.parse(resp.body) feed.entries.each do |entry| puts entry.my_tag # stdout: 独自タグ end link アトリビュートや title アトリビュートが必要な場合は value にアトリビュート名を設定します。 Feedjira::Feed.add_common_feed_entry_element("my:tag", as: :my_tag) Feedjira::Feed.add_common_feed_entry_element("my:tag", as: :my_tag_title, value: :title) Feedjira::Feed.add_common_feed_entry_element("my:tag", as: :my_tag_link, value: :link) resp = Faraday.get('http://example.com/feed') feed = Feedjira.parse(resp.body) feed.entries.each do |entry| puts entry.my_tag # stdout: 独自タグ puts entry.my_tag_title # stdout: example puts entry.my_tag_link # stdout: https://example.com/ end ネストしていないシンプルな構造の独自タグの場合は add_common_feed_entry_element で簡単に取得することが出来ます。 複雑な構造の場合(ネストしている) 以下のようなRSSがあったとします。 <?xml version="1.0" encoding="UTF-8"?> <rss version="2.0" xmlns:media="http://search.yahoo.com/mrss/" xmlns:content="http://purl.org/rss/1.0/modules/content/" > <channel> <title>サイトタイトル</title> <link>https://example.com/</link> <description>サイト説明</description> <pubDate>Mon, 19 Jun 2020 09:00:00 7JunJST</pubDate> <language>ja</language> <copyright>誰か</copyright> <item> <title><![CDATA[タイトル]]></title> <link>https://example.com/item/1</link> <guid>https://example.com/item/1</guid> <description><![CDATA[ディスクリプション]]></description> <pubDate>Mon, 19 Jun 2020 02:55:52 2JunJST</pubDate> <content:encoded><![CDATA[ コンテンツ本文 ]]></content:encoded> <!-- ここから独自拡張 --> <my:nested_tag> <my:child link="https://exmaple.com/1" title="example1" /> <my:child link="https://exmaple.com/2" title="example2" /> <my:child link="https://exmaple.com/3" title="example3" /> </my:nested_tag> <!-- /ここまで独自拡張 --> </item> </channel> </rss> このような場合は add_common_feed_entry_element を普通に使用しただけでは思った通りに取得が出来ません。 Feedjira::Feed.add_common_feed_entry_element("my:nested_tag", as: :nested_tag) # valueを指定しないとinner textを返すのでブランクになる Feedjira::Feed.add_common_feed_entry_element("my:child", as: :sponsored_link, value: :link) # my:childから取得を試みた場合は3件のうち1件目のみが取得できる どうするか? add_common_feed_entry_element には class オプションにparserを渡せる仕組みがあります。 ドキュメントにはありませんが以下のコードから class を渡せるということがわかります。 公式のコードを参考にして独自parserクラスを定義 module Feedjira module Parser class MyNestedTag include SAXMachine elements :"my:child", as: :link, value: :link elements :"my:child", as: :title, value: :title end end end classに独自parserクラスを指定してみる Feedjira::Feed.add_common_feed_entry_element("my:nested_tag", as: :nested_tag, class: Feedjira::Parser::MyNestedTag) resp = Faraday.get('http://example.com/feed') feed = Feedjira.parse(resp.body) feed.entries.each do |entry| entry.nested_tag.each do |ads| puts ads.link puts ads.title end # stdout: # https://exmaple.com/ads/1 # example1 # https://exmaple.com/ads/2 # example2 # https://exmaple.com/ads/3 # example3 end 意図した通りに動きました。 parserクラスの書き方自体は公式のparserが参考になるのでそちらを参考にすると良いと思います 公式parser: https://github.com/feedjira/feedjira/tree/master/lib/feedjira/parser
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Ruby on Railsの開発環境手順(Windows10、バージョン6)

始めに参考にしたもの ・Rubyの環境構築 https://prog-8.com/docs/ruby-env-win ・Railsの環境構築 https://prog-8.com/docs/rails-env-win 必要なもの Ruby SQLite3 Node.js Yarn Rubyのインストール Ruby公式から推薦バージョンをインストール 推奨バージョン「=>」つきのもの 今回はこれ「=>Ruby+Devkit 2.7.3-1 (x64)」 バージョン確認 ruby -v バージョンが表示されればOK SQLite3のインストール SQLite公式からインストール DownloadからSQLite Download Pageへ移動し 「Precompiled Binaries for Windows」下 自分のPCのbitに合わせて「SQLite version 3.35.5.」をダウンロード ※今回は64bit 「sqlite-tools-win32-x86-3350500.zip」もダウンロード 展開し「sqlite3.dll」「sqlite3.exe」を「C:\Ruby27-x64\bin」へ配置 Ruby on Railsのインストール バージョンを指定してインストール gem install rails -v "5.2.3" エラー発生 ERROR: Error installing rails: ERROR: Failed to build gem native extension. 色々試してみる https://dannex.jp/rails%E3%82%A8%E3%83%A9%E3%83%BC%E3%80%8Cerror-failed-to-build-gem-native-extension%E3%80%8D https://commte.net/7162 やっぱり同じエラーになるのでRailsガイドを参考にしバージョン指定なしで実行 gem install rails インストールできた... バージョン確認 ruby -v バージョンが表示されればOK Node.jsのインストール Node.jsのサイトからインストール 「Windows Installer」をクリックしダウンロード バージョン確認 node --version バージョンが表示されればOK yarnのインストール npm install --global yarn バージョン確認 yarn --version バージョンが表示されればOK 動作確認 アプリケーションを作成する rails new "アプリケーション名" my_appの作成 rails new my_app C:\を確認 Railsサーバを立ちあげる アプリケーションのディレクトリに移動 cd sample_app Railsサーバー起動 rails s ブラウザでページにアクセス localhost:3000 成功! 終了 control + c
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Rails】カラムの設定を変更する方法

目的 適用済みのマイグレーションファイルに記載されたカラムの型を変更すること 手順 ■ 実行予定の手順 1.既存のマイグレーションファイルをロールバックする 2.変更したいマイグレーションファイルのステータスを確認 3.対象のマイグレーションファイルを書き換える 4.マイグレーションコマンドの実行 5.マイグレーションファイルのステータスがupになっているか確認 1.既存のマイグレーションファイルをロールバックする 前提として適用済みのマイグレーションを編集してはいけません。 必ずロールバックをしてから編集する必要があります。 ターミナル rails db:rollback 2.変更したいマイグレーションファイルのステータスを確認 変更したいマイグレーションファイルのステータスがdownになっているか確認します。 ターミナル rails db:migrate:status 実行すると以下のようにターミナルにマイグレーションファイルのステータスが表示されます。 ターミナル Status Migration ID Migration Name -------------------------------------------------- up 222222222222 Devise create users down 222222222222 Create items rails db:rollbackコマンドでは直近のマイグレーションのみロールバックがされます。 変更したいマイグレーションファイルをdownにしたい場合は、複数回rails db:rollbackコマンドを実行してください。 マイグレーションファイルを一度に複数ロールバックする方法はこちらの記事をご参考ください。 3.対象のマイグレーションファイルを書き換える 対象のマイグレーションファイルのステータスがdownになっていることが確認できましたら、マイグレーションファイルのカラムの型を変更していきます。 例: integer → float に変更 元の記述 t.integer :time, null: false 変更後の記述 t.float :time, null: false 4.マイグレーションコマンドの実行 変更したいカラムの型を書き換えたらマイグレーションコマンドを実行します。 ターミナル rails db:migrate マイグレーションコマンドはdownになっているマイグレーションファイルをすべてupにしてくれます。 5.マイグレーションファイルのステータスがupになっているか確認 念の為マイグレーションファイルのステータスを確認します。 ターミナル rails db:migrate:status ステータスがupになっていることが確認できたら終了です。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Mysql2::Error: Specified key was too long; max key length is 767 bytes

概要 ユーザ管理機能実装のため、deviseによるテーブルの作成時に発生した下記エラーを解消します。 Mysql2::Error: Specified key was too long; max key length is 767 bytes 結論 下記コマンドを実行する。 rails db:migrate:reset 詳細 コマンド rails db:migrate:reset は、テーブル削除、再作成、マイグレートを実施します。 処理内容としては、下記と同じです。 rails db:drop rails db:create rails db:migrate database.ymlのencoding :utf8mb4をencoding :utf8に変更することでエラー解消できない場合に試してみましょう。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Ruby】任意の文字列に"code"が、左から何文字目に出てくるかを返し、その数を出力するメソッドを作れ。

def count_code(str) puts (str.index("code") + 1) end count_code("aaacodebbb") 出力結果 4
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Railsにおけるリクエストからレスポンスの流れ

はじめに  Webページを表示したり、タスクの新規作成をする際にrailsのなかでどのような処理が行われているのかをまとめました。 ユーザーの一覧ページを表示する(GETメソッド) /usersというパスに対してGETリクエストがWebサーバに送られる。 (POSTではなくGETを使う理由は、一覧表示ではデータの書き換えは必要ではなく、データを取得したいだけなのでGETを使う) WebサーバがGETリクエストを受け取りroutes.rbのresources :usersにより、それに対応するコントローラのアクションが呼び出される。 コントローラのindexアクションで全ユーザーのデータを取得する。 def index @users = User.all end (この記述だけでデータベースからデータを取得できる理由は、RailsにはモデルにActiveRecordが継承されているので、Rubyを用いてデータベースからデータを探したり、持ってくることができる。) indexアクションに紐づくindex.html.erbを編集する @users.eachでuserオブジェクトを一つずつ取り出し、その情報がHTMLタグの中に動的に埋め込まれ、HTMLを組み立てる。 <% @users.each do |user| %> <li> <%= user.name, user %> </li> <% end %> (データベースに検索されるタイミングはindexアクションでUser.allされたときではなく、検索結果が必要なタイミングで行われるので、今回の場合は@users.eachが呼ばれた時) Webサーバからindex.html.erbで組み立てたHTMLをHTTPのレスポンスボディにのせてレスポンスを返す。 Webブラウザがレスポンスを受け取り、処理して画面にユーザー一覧が表示される。 タスクを新規作成する(POSTメソッド) 新規作成ページを表示する /tasks/newというパスに対してGETリクエストがWebサーバに送られる。 WebサーバがGETリクエストを受け取りroutes.rbのresources :tasksにより、それに対応するコントローラのアクションが呼び出される。 コントローラのnewアクションで新しいオブジェクトを作成 def new @task = Task.new end タスク名(name)を入力する 入力フォームのHTMLを生成するためnewアクションに紐づくnew.heml.slimを編集する。 = form_with model: @task, local: true do |f| .form-group = f.label :name = f.text_field :name, class: 'form-cotrol' = f.submit nil, class: 'btn btn-primary' form_withによってこのようなHTMLが生成される。 <form action="/tasks" accept-charset="UTF-8" method="post">      <input name="utf8" type="hidden" value="✓">      <input type="hidden"name="authenticity_token"value="0/MwK3LxN24WXfQNV5cFYZkbRSoRsL9QEomdh2h+Hr2BpWQqeW95LO7MM4ZZGoz56y+mHx0hMETSwAW18fqKvw==">   <div class="form-group">      <label for="task_name">Name</label>   <input class="form-cotrol" type="text" name="task[name]" id="task_name"> </div> <input type="submit" name="commit" value="登録" class="btn btn-primary" data-disable-with="登録"></form> 作成ボタンを押す form_withで生成されるmethod: postによって、フォーム内容を送信するときにPOSTメソッド指定される。/tasksに対してPOSTリクエストが送られるとroutes.rbのresources :tasksで対応するtasks_controllerのcreateアクションが実行される。 task_paramsで取得したデータをTask.newの引数にしてインスタンスを作成 def create @task = Task.new(task_params) if @task.save redirect_to @task else render :new end end private def task_params # require(:task)は生成されたHTMLのname="task[name]"のtaskと関連している。 # permit(:name)で指定したカラムのみ取得する。 # リクエストボディの「入力されたタスク名」がRailsによりparamsオブジェクトの中にハッシュのような構造で入る params.require(:task).permit(:name) end タスク詳細ページに遷移する データベースへの保存が成功した場合、リダイレクト先を@taskとすることで詳細ページに遷移する(redirect_to @taskはredirect_to task_url(task.id)と同じ意味を持つ)
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む