20211009のRubyに関する記事は14件です。

Rubyのオブジェクト指向について

Rubyはオブジェクトでできている Rubyはものを作る時に、 『コンピューターに、こうやって作れ』と指示を出しながらサービスを作っていく言語です。 そのようなRubyはオブジェクトでできています。 オブジェクトとは何かを一言で表現すうるのは難しいのですが、 何かのクラスのインスタンスです。 Rubyにはそれぞれインスタンス、メソッド、クラスを持っています。 この3つをもとに説明して行きます。 クラスとインスタンス オブジェクト指向を理解するにはクラスとインスタンスの理解は必須です。 クラスとは設計図のことです。 インスタンスは設計図をもとに作られた実体です。 ●家を例にします。 家の設計図がクラス。その設計図をもとに作られた家がインスタンスです。 設計図があればいろいろな家を作れますよね。 赤い色の家も作れますし、黄色い家も作れます。 設計図があれば同じような家をたくさん作れます。 もっといい性能の家を作りたければ、設計図を修正すれば 1つ1つの家を建て替えたりする必要はなくなり、毎回毎回性能のいい家に住めます。 このような考えをコードでも実践できます。 オブジェクト指向の3大要素 1クラス(カプセル化) メソッドを定義することにより何をやっているのかをわかるようにする 2ポリモーフィズム メッセージの送り方を共通にするものです。 身近な例で例えると、車,バス、トラックで例えます。 〇〇のエンジンをつける。〇〇は上の3台の乗り物が当てはまりますよね。 3台共通の動作をします。 このようなイメージです。 3継承 設計図をもとに同じような性能を持ったものを作ることです。 例えば、 設計図が車だとすると、その車をもとに、 フェラーリやランボルギーニを作れます。 車に少し性能を加えたものを作ることができます。 最後に 説明が足りない部分もありましたが 一通りのことはまとめました。 大事な概念なのでいろいろ調べてみてください。 ⚫︎参考資料 https://www.sejuku.net/blog/124336 https://pikawaka.com/ruby/class https://qiita.com/Hashimoto-Noriaki/items/e94a27c3d5d40ba4d41c https://qiita.com/shogo-1988/items/e749208c0733bbe025c0
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Prefixについて!

①.結論! Prefixとは、ルーティングのURI Patternに名前をつけて変数化したものです! これにより、URI Patternの代わりにPrefixを用いてパスを表現できます! 簡単に言うと、遷移する指定先をパスで視覚化した事です! 細かく説明していきます! ②.解説! 例として、ターミナルでrails routesコマンドを実行して有効なルーティングを探すと、以下のような表示になります! Prefix Verb URI Pattern Controller#Action eats GET /eats(.:format) eats#index 他省略 一番左上の列を確認します! 一番上にはPrefixという文字があり、その配下にはPrefix名が出力されていることが確認できます! つまり、下記のようにURI Pattern(パス)が変数化したと言う事です! Prefix Verb URI Pattern -> eats GET /eats(.:format) このPrefix名に続けて_pathと記述を付け加えることによって、URI Patternのパスとして認識されます! 例えば、rootにアクセスしたいとき、'/'と表現出来ましたが、root_pathとも表記できます! 下記が例です! # Prefix未使用 <%= link_to "link_button", '/', class: "header__title--text" %> # Prefix使用 <%= link_to "link_button", root_path, class: "header__title--text" %> このような形で完成となります! ③.まとめ! 流れとしてはターミナルでrails routesをして、パスを確認して記述すると言う事です! パスの指定は必ず必要なので、このやり方は覚えておくべきですね! 何か説明で間違っていたらご指導お願い致します(_ _)
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AWS CLIとSAN証明書を駆使してELB利用料金を50万円節約した話

全体の流れ 背景 開発サービスの仕様 と AWSの仕様 について Service Quotas編 ELB:紐づけれる証明書の上限を26→51にアップ ACM:SANs証明書のサブジェクト別名に指定できるドメイン数を10→100にアップ スクリプト編 ロードバランサー に紐付く証明書を全て取得する 証明書に設定したドメインを全て取得する 既に100個にバンドルされたドメインを取得する 未だ100個にバンドルされていないドメインを100個ごとにバンドルし、SANs証明書を発行する SANs証明書をロードバランサー に設定する。 ドメインの証明書がSANs証明書に変更されているか確認する。 手作業編 ブラウザチェック ELBから不要な証明書の紐付け解除 スクリプトを組むべき理由 1. 背景 三段論法で行きます。 顧客企業ごとに独自ドメインを発行 するサービスを開発しています。 1つのELBに紐づけられる証明書の上限数が26個だった!(AWS仕様) 顧客数が500社を超えてELBが20個になっていた!!! ELBは複数あっても無駄ですし、1台2000円ぐらいの固定費がかかります。 20台もあれば月4万円 → 年間50万です。 ベンチャーに無駄遣いしてる余裕はないので節約していくことになりました。 2. 開発サービスの仕様 と AWSの仕様 について 開発サービスの仕様 顧客企業ごとに独自ドメインを発行する必要がある。 AWSの仕様 1つのELBに紐づけられる証明書の上限数は26個(デフォルト証明書1個 + 追加25個) 1つのSANs証明書に設定できるサブジェクト別名の上限数は10個 3. Service Quotas編 上記で説明したようにAWSサービス毎に様々な制限があります。 しかし、Service QuotasというAWSサービスを使うことで上限緩和ができます。 画面遷移図と共に説明します。 ELB:紐づけれる証明書の上限を26→51にアップ マネジメントコンソールより「Service Quotas」で検索 Service Quotasのダッシュボードページの左部サイドメニューより「AWSのサービス」をクリック 検索窓に「ELB」と入力して検索結果をクリック 検索窓に「certificate」と入力して「Certificates per Application Load Balancer」をクリック ちなみに「適用されたクォータ」が現在の上限値で、「AWSのデフォルトのクォータ値」がデフォルトの上限値になります。 僕のAWSアカウントは上限緩和済みですので「50」となっていますが、未設定の場合は何も表示されなかったはずです。 「クォータの引き上げをリクエスト」をクリック 「クォータ値を変更」というフィールドに「50」と入力してリクエスト 50以上は上げれないと公式から言われました。 リクストの承認には数日かかることがあります。 これで承認されればあとはなにもしなくても上限がアップされています。 ACM:SANs証明書のサブジェクト別名に指定できるドメイン数を10→100にアップ 同じくService Quotas上のAWSサービス検索窓に「ACM」と入力し「AWS Certificate Manager」をクリック 「Domain names per ACM certificate」をクリック 「クォータの引き上げをリクエスト」をクリック 「クォータ値を変更」というフィールドに「100」と入力してリクエスト 100以上は上げれないと公式から言われました。 リクストの承認には数日かかることがあります。 これで承認されればあとはなにもしなくても上限がアップされています。 4. スクリプト編 AWS CLIが設定されていることが前提です。 処理がかなり複雑なので、まずは流れをまとめます。 ロードバランサー に紐付く証明書を全て取得する(ここで取得できる情報は証明書の Arn のみ。どのドメインの証明書かは記載されていない)。 証明書に設定したドメインを全て取得する(証明書の詳細情報を取得すると、設定されているドメイン情報も全て取得できる)。 既に100個にバンドルされたドメインを取得して無視する(既に100個にバンドル済みなので処理する必要はない)。 未だ100個にバンドルされていないドメインを100個ごとにバンドルし、SANs証明書を発行する(100個に満たない場合は、その時の数でSANs証明書を発行する)。 SANs証明書をロードバランサー に設定する。 ドメインの証明書がSANs証明書に変更されているか確認する。 まずここまでで、それぞれのロードバランサーに紐づく26個の証明書を1つのSANs証明書にまとめることができます。 今度は、 シェルスクリプトだけで複雑な条件分岐・ループ処理を書くのが難しかったので、Rubyで書いてます。 AWS CLIコマンドの戻り値を、Rubyで受け取って処理しています。 ちょっと見にくいですが、ご了承ください。。。 1. まずはロードバランサー に紐付く証明書を全て取得します。 ここで取得できる情報は証明書の Arn のみ。どのドメインの証明書かは記載されていない。 require "json" require "faraday" puts `aws --version` #=> aws-cli/2.2.7 Python/3.8.8 Darwin/20.6.0 exe/x86_64 prompt/off # ELB のHTTPSリスナーのArnを記入 elb_https_arn = "arn:aws:elasticloadbalancing:ap-northeast-1:#XXXXXX:listener/app/XXXXXXXX/XXXXXX" elb_certificates = JSON.parse(`aws elbv2 describe-listener-certificates --listener-arn #{elb_https_arn} --query 'Certificates[].CertificateArn'`) #=> [ # arn:aws:acm:ap-northeast-1:XXXXXX:certificate/XXXXXX, # arn:aws:acm:ap-northeast-1:XXXXXX:certificate/XXXXXX, # arn:aws:acm:ap-northeast-1:XXXXXX:certificate/XXXXXX, # .... # ] 2. 証明書に設定したドメインを全て取得する Arnを使うことで証明書の詳細情報を取得できる。そこからドメイン情報も全て取得できる。 all_domains = elb_certificates.map do |cert| res = JSON.parse(`aws acm describe-certificate --certificate-arn #{cert} --query Certificate`) main_domain = res.dig("DomainName") sans = res.dig("SubjectAlternativeNames") [main_domain, sans] end.flatten.compact.uniq #=> ["example1.com", # "example2.com", # "example3.com", # ... # ] 3. 既に100個にバンドルされたドメインを取得 既に100個にバンドル済みなので処理する必要はないので、後々の処理で無視する為に取得する。 already_bundled_domains = elb_certificates.map do |cert| res = JSON.parse(`aws acm describe-certificate --certificate-arn #{cert} --query Certificate`) main_domain = res.dig("DomainName") sans = res.dig("SubjectAlternativeNames") # SubjectAlternativeNames の配列には MainDomain も含まれるので、[main_domain + sans].size と記述しなくてOK。 [main_domain, sans] if [sans].flatten.size == 100 end.flatten.compact.uniq 4. 未だ100個にバンドルされていないドメインを100個ごとにバンドルし、SANs証明書を発行する 100個に満たない場合は、その時の数でSANs証明書を発行する。 require 'active_support/core_ext/array/grouping' not_bundled_domains = (all_domains - already_bundled_domains) sans_certificates = not_bundled_domains.in_groups_of(100, false).map do |domains| main_domain = domains.first sans = domains[1..-1] sans_certificate = JSON.parse(`aws acm request-certificate \ --domain-name #{main_domain} \ --validation-method DNS \ --subject-alternative-names #{sans.join(" ")} \ --tags #{tags}`) sans_certificate end # SANs証明書が発行できたかどうかステータス確認 sans_certificates.each do |sans_certificate| puts 'レスポンスJSONの ["Certificate"]["DomainValidationOptions"] で各ドメインの検証ステータスを確認できる。検証成功している場合は「SUCCESS」となっている。' loop.with_index(1){ |_, i| puts i # 100ドメインの検証をするので、発行完了まで1分ぐらいかかる。 # 検証成功するまで証明書を使えないので、成功するか随時チェックする。 # 5分経っても検証成功しない場合は何かおかしい可能性があるのでコンソールからチェックしてください。 raise if i == 10 sleep 30 res = JSON.parse`aws acm describe-certificate --certificate-arn #{sans_certificate["CertificateArn"]}` if res.dig("Certificate", "DomainValidationOptions").select{|v| v["ValidationStatus"] != "SUCCESS"} == [] break end } end 5. SANs証明書をロードバランサー に設定する。 sans_certificates.map.with_index(1) do |sans_certificate, index| puts index JSON.parse(`aws elbv2 add-listener-certificates --listener-arn #{elb_https_arn} --certificates CertificateArn=#{sans_certificate["CertificateArn"]}`) end 6. ドメインの証明書がSANs証明書に変更されているか確認 require 'socket' require 'openssl' def get_certificate(domain) certificate = nil TCPSocket.open(domain, 443) do |tcp_client| ssl_client = OpenSSL::SSL::SSLSocket.new(tcp_client) ssl_client.hostname = domain ssl_client.connect certificate = ssl_client.peer_cert ssl_client.close end certificate end used_certificates = [] error_domains = [] all_domains.each.with_index(1) do |domain, index| domain = domain.gsub("*.", "") puts index, domain begin used_certificates << [ get_certificate(domain.gsub("*.", "") ).subject.to_s.gsub("/CN=", "") ] rescue => e error_domains << [ domain, e ] end end used_certificates.flatten.compact.uniq.sort 5. 手作業編 ブラウザチェック どっちでもOKです。 スクリプトだけでのチェックが怖い人はやってください。 ELBから不要な証明書の紐付け解除 間違って使用中の証明書を削除してしまうのでは怖いので、流石にここは手作業でします。 6. スクリプトで処理を実行するべき理由 ヒューマンエラーの回避するため AWS ACMのコンソールからSANs証明書を発行する場合、100個のドメインを全て入力しないといけない。 人間は単純作業が苦手なので機械にやらせましょう。 SANs証明書は更新できないから SANs証明書は更新できません。 例えば、1つのSANs証明書に99個の証明書がバンドルされていて、 証明書を1つ追加・削除したくなっても、できません。編集ができません。 1つ削除したくなったら98個の証明書を入力し、1つ追加したくなったら100個を入力する必要があります。 人間は単純作業が苦手なので機械にやらせましょう。 上記の理由から、スクリプトを組むメリットしかないです。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

はじめてのRuby on Railsの環境構築 まとめ

1. はじめに 以前はDocker上で環境構築を行いましたが今回は前回できなかった自分のPCに環境構築できたのでメモ。 2. インストールする環境 PC: MacBookAir(Early 2015) OS: BigSur 11.1 CPU:1.6 GHz デュアルコアIntel Core i5 3. Homebrewをインストール Homebrewの公式サイトにコマンドが表示されていますが、今回はこちらのコマンドを入力します。 % /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" すると以下のような警告が出ますがダウンロードが進行します。 Warning: The Ruby Homebrew installer is now deprecated and has been rewritten in Bash. Please migrate to the following command: /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" ↑こちらが最新(2021/010/09時点)のコマンド Updated 1 tap (homebrew/core). ==> Installation successful! →Homebrewのインストールが完了 4. Rubyをインストール % brew install ruby Warning: ruby 3.0.2 is already installed and up-to-date. To reinstall 3.0.2, run: brew reinstall ruby 既にインストールされてますが再インストールします。 % brew reinstall ruby ==> Caveats By default, binaries installed by gem will be placed into: /usr/local/lib/ruby/gems/3.0.0/bin デフォルトと違う場所になっているという警告 ruby-build installs a non-Homebrew OpenSSL for each Ruby version installed and these are never upgraded. rubyがHomebrewを使用せずにインストールされているのでアップグレードがされないという警告 警告文 You may want to add this to your PATH. ruby is keg-only, which means it was not symlinked into /usr/local, because macOS already provides this software and installing another version in parallel can cause all kinds of trouble. If you need to have ruby first in your PATH, run: echo 'export PATH="/usr/local/opt/ruby/bin:$PATH"' >> ~/.zshrc For compilers to find ruby you may need to set: export LDFLAGS="-L/usr/local/opt/ruby/lib" export CPPFLAGS="-I/usr/local/opt/ruby/include" For pkg-config to find ruby you may need to set: export PKG_CONFIG_PATH="/usr/local/opt/ruby/lib/pkgconfig" ruby-build installs a non-Homebrew OpenSSL for each Ruby version installed and these are never upgraded. To link Rubies to Homebrew's OpenSSL 1.1 (which is upgraded) add the following to your ~/.zshrc: export RUBY_CONFIGURE_OPTS="--with-openssl-dir=$(brew --prefix openssl@1.1)" 【対処法】 .zshrcファイルを編集 rubyをインストールした際に出ていた警告文の中にあったexport〜で始まる文を追記する % echo 'export PATH="/usr/local/opt/ruby/bin:$PATH"' >> ~/.zshrc % export LDFLAGS="-L/usr/local/opt/ruby/lib" % export CPPFLAGS="-I/usr/local/opt/ruby/include" % export PKG_CONFIG_PATH="/usr/local/opt/ruby/lib/pkgconfig" % export RUBY_CONFIGURE_OPTS="--with-openssl-dir=$(brew --prefix openssl@1.1)" または直接書き込みしてもOK 完成図 →rubyのインストールが完了 5. Railsをインストール % sudo gem install rails Successfully installed rails-6.1.4.1 →Railsのインストールが完了 6. アプリを作成 作成したい場所に移動 % cd /Users/ユーザー名/アプリの保存したい場所 % rails new RailsApp(アプリ名) エラーが発生… rails aborted! LoadError: cannot load such file -- nokogiri/nokogiri /Library/Ruby/Gems/2.6.0/gems/nokogiri-1.12.5-arm64-darwin/lib/nokogiri/extension.rb:30:in rescue in [main] /Library/Ruby/Gems/2.6.0/gems/nokogiri-1.12.5-arm64-darwin/lib/nokogiri/extension.rb:4:in [main] /Library/Ruby/Gems/2.6.0/gems/nokogiri-1.12.5-arm64-darwin/lib/nokogiri.rb:11:in [main] 対処法 nokogiriファイルが読み込めてないようなので、不要なバージョンのnokogiriファイルを削除します。 作成したrailsアプリのフォルダを開き、Gemfile.Lockファイルを開く 私は念の為以前作成したDocker+Railsのフォルダを見比べながら編集 今回は下記2つを削除 nokogiri (1.12.5-arm64-darwin) nokogiri (~> 1.6) 2021年10月10日(追記) nokogiriファイル整理後にrails serverすると以下のエラーが出ます Webpacker configuration file not found Webpackerが無いのでダウンロードします。 rails webpacker:install 参考させていただいたサイト [Tips] Rails6起動時のError対応 もう一度トライ % rails server できました!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[Ruby] AtCoder過去問 C - 100 to 105

はじめに AtCoder過去問をRubyで解いてみました。 よろしくお願いします。 問題はこちらから確認してください↓ C - 100 to 105 まずは入力を受け取ります。 その後xの十のくらいまでの二桁をx_tenに代入します。 x = gets.to_i x_ten = x % 100 僕の考え方は100の位以降の桁は一旦無視して、x_tenを5で割り、その答えをcntに代入、そして余りを4で割り、その答えをcntに足し、余りを3で割り...を1まで繰り返します。 余りを出す計算と割り算の答えをcntに追加していく計算を別にしていますが、上記のことをコードに落とし込んだのが↓です。 x = gets.to_i x_ten = x % 100 five_rem = x_ten % 5 four_rem = five_rem % 4 three_rem = four_rem % 3 two_rem = three_rem % 2 cnt = x_ten / 5 cnt += five_rem / 4 cnt += four_rem / 3 cnt += three_rem / 2 cnt += two_rem / 1 十の位までのxを5から順番に割って、割り切れなかった数字を次の数字が割って...という処理で、百のくらいは無視して、5, 4, 3, 2, 1をそれぞれ何個使ってx_tenを作れるかの最小値がcntに入っています。 実際は、5, 4, 3, 2, 1のどれかを一回使うごとに+100がついてきてます。 つまりcntを100倍すれば、下二桁をxに合わせたときの百のくらいが分かります。 xの百の位はx-x_tenで表現できます。 cntの100倍がxの百の位以下であれば1を出力できます。足りない分は100を使えばいいので下二桁に影響を与えずに百の位を合わせに行けます。 逆にcntの100倍がxの百の位を超えてしまうようなら、下二桁を合わせたときに百の位はどう頑張っても、合わせられないので0を出力します。 x = gets.to_i x_ten = x % 100 five_rem = x_ten % 5 four_rem = five_rem % 4 three_rem = four_rem % 3 two_rem = three_rem % 2 cnt = x_ten / 5 cnt += five_rem / 4 cnt += four_rem / 3 cnt += three_rem / 2 cnt += two_rem / 1 if cnt * 100 <= x-x_ten puts 1 else puts 0 end おまけ 最後のif文の条件式はcntに100を掛けなくてもcntとx/100を比べてもできましたね。 あと、僕はクソ真面目に解きましたが、xの百の位の数字に5をかけた数字がxの下二桁以上であれば、合計価格がちょうどx円で買い物ができるという法則を見つけられたなら下記のようにより明快な短いコードを書けます。 x = gets.to_i x_ten = x % 100 n = x / 100 if n * 5 >= x_ten puts 1 else puts 0 end
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

配列同士の計算

自作のECサイトでカート内商品の合計金額を算出が必要となったため、色々試してみたところ一番しっくりくる記述法があったため忘れないように記録。 total_price.rb # items = CartItem.includes(:product) //商品情報をincludesで取得 def total_price(items) quantity = items.pluck(:quantity) # :quantity(購入個数) のレコードの配列を取得 # quantity = {1, 2, 3} price = items.pluck(:price) # :price(購入金額)のレコードの配列を取得 # price = {1500, 1200, 1000} total_price = quantity.zip(price).map{|q,p| q*p}.sum # .zip(price) = {[1, 1500], [2, 1200], [3, 1000]} <----quantityとpriceの配列をzipで結合 # .map{|q,p| q*p} = {1500, 2400, 3000} <----mapで商品ごとの個数*金額を算出 # .sum <----最後にsumで合計金額を算出 total_price = add_tax(total_price) # 消費税を計算 return total_price end これで合計金額の算出完了!!以上!!!!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AWSへのデプロイ後、ブラウザー上で「We're sorry, but something went wrong.」と表示された際の対処法

はじめに AWS上にCapistranoを使用してRailsアプリをデプロイしましたが、ブラウザー上に「We're sorry, but something went wrong.」と表在されてしまうエラーに遭遇して、エラーの解決に苦戦しましたため、同様の悩みをお持ちの方のお役に立てばと思い、記載いたします。 開発環境 Mac Ruby 2.7.2 Rails 6.1.3.1 PostgreSQL 13.2 本番環境 puma nginx AWS(EC2、RDS、VPC、S3) 前提 RailsアプリをHerokuとS3を使用した環境で上手くデプロイできましたため、AWS(EC2、RDS、VPC)環境にRailsアプリをデプロイした際に発生したエラーとなります。 エラーの事象 ローカル環境のターミナルで「bundle exec cap production deploy」コマンドを実行し、表示されたIPアドレスをブラウザーに入力後、以下の画面が表示されました。本来であれば、アプリケーションのトップページが表示されるはずですが、エラー画面が表示されてしまいました。 ローカル環境のターミナルでデプロイエラーは出ていなかったため、サーバー環境のターミナルで「/var/www/アプリケーション名/shared/log/nginx.error.log」を確認したところ、以下のメッセージが表示されました。 /var/www/アプリケーション名/shared/log/nginx.error.log 2021/10/04 08:00:08 [crit] 25745#25745: *539 connect() to unix:/var/www/stop_sweets/shared/tmp/sockets/puma.sock failed (2: No such file or directory) while connecting to upstream, client: xx.xx.xx.xxx, server: localhost, request: "GET /blog/wp-includes/wlwmanifest.xml HTTP/1.1", upstream: "http://unix:/var/www/stop_sweets/shared/tmp/sockets/puma.sock:/blog/wp-includes/wlwmanifest.xml", host: "xx.xx.xx.xxx" 2021/10/04 08:00:09 [crit] 25745#25745: *539 connect() to unix:/var/www/stop_sweets/shared/tmp/sockets/puma.sock failed (2: No such file or directory) while connecting to upstream, client: xx.xx.xx.xxx, server: localhost, request: "GET /web/wp-includes/wlwmanifest.xml HTTP/1.1", upstream: "http://unix:/var/www/stop_sweets/shared/tmp/sockets/puma.sock:/web/wp-includes/wlwmanifest.xml", host: "xx.xx.xx.xxx" 「sockets/puma.sock failed (2: No such file or directory)」というメッセージでググってみたところ、pumaが起動した際にpuma.sockというファイルが作成されるとのことですので、pumaが上手く起動していないことによるエラーなのではと思い、pumaが上手く動かない原因を調べてみました。 以下のpuma起動用スクリプトからpumaを起動しているコマンドを確認しました。 /etc/systemd/system/puma_アプリ名_production.service [Unit] Description=Puma HTTP Server for stop_sweets (production) After=network.target [Service] Type=simple User=stop_sweets_user WorkingDirectory=/var/www/stop_sweets/current ExecStart=/home/stop_sweets_user/.rbenv/bin/rbenv exec bundle exec puma -C /var/www/stop_sweets/shared/puma.rb ExecReload=/bin/kill -TSTP $MAINPID StandardOutput=append:/var/www/stop_sweets/shared/log/puma_access.log StandardError=append:/var/www/stop_sweets/shared/log/puma_error.log Restart=always RestartSec=1 SyslogIdentifier=puma [Install] WantedBy=multi-user.target 上記のpuma起動用スクリプトから確認した起動コマンド「bundle exec puma -C /var/www/アプリ名/shared/puma.rb」をサーバー環境ターミナルのディレクトリ「/var/www/アプリ名/current」で実行したところ、以下のログが表示されました。 Puma starting in single mode... * Puma version: 5.2.2 (ruby 2.7.2-p137) ("Fettisdagsbulle") * Min threads: 0 * Max threads: 16 * Environment: production * PID: 13673 ! Unable to load application: ArgumentError: Missing required arguments: aws_access_key_id, aws_secret_access_key bundler: failed to load command: puma (/var/www/stop_sweets/shared/bundle/ruby/2.7.0/bin/puma) Traceback (most recent call last): 57: from /home/stop_sweets_user/.rbenv/versions/2.7.2/bin/bundle:23:in `<main>' 56: from /home/stop_sweets_user/.rbenv/versions/2.7.2/bin/bundle:23:in `load' エラーメッセージ「ArgumentError: Missing required arguments: aws_access_key_id, aws_secret_access_key」でググってみたところ、Railsアプリ内で画像投稿用のgem「CarrierWave」を使用して、投稿した画像をS3に保存するようにしておりましたが、S3を使用するためのアクセスキーとシークレットキーを設定していなかったことによるエラーであることが分かりました。そのため、railsアプリ内のコードを以下のように修正しました。 config/initializers/carrier_wave.rb if Rails.env.production? CarrierWave.configure do |config| config.fog_credentials = { provider: 'AWS', aws_access_key_id: Rails.application.credentials.dig(:aws, :access_key_id), aws_secret_access_key: Rails.application.credentials.dig(:aws, :secret_access_key), region: Rails.application.credentials.dig(:aws, :region) } config.fog_directory = Rails.application.credentials.dig(:aws, :bucket) end end config/credentials.yml.enc aws: access_key_id: 【IAMユーザーのアクセスキーID】 secret_access_key: 【IAMユーザーのシークレットアクセスキー】 region: ap-northeast-1 bucket: 【S3のバケット名】 上記の修正後、githubのmainブランチに反映し、ローカル環境のターミナルで「bundle exec cap production deploy」コマンドを実行致しました。ブラウザーからアプリへアクセスしたところ、無事にトップページが表示されるようになりました。 まとめ デプロイログやサーバログに真因に関するメッセージが出ていなかったため、 解決に手こずりましたが、エラーメッセージから地道に調査していくことが大切だと思いました。 nginxやpumaなどのサーバに関する知識も必要だと思いました。サーバに関する知識がないと原因がアプリ側なのか、インフラ側なのかの原因の切り分けが難しいと思いました。 参考資料 Capistrano自動デプロイ中の「ArgumentError: Missing required arguments: aws_access_key_id, aws_secret_access_key」エラー NginxとRails(Puma)をソケット通信で連携させる方法!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

transactionにおける例外処理の扱い方

はじめに 基本的には、以下のスライドを参考にまとめたものになります。 https://speakerdeck.com/jnchito/number-rubykansai-2018-01-13 例外とは 例外とは、それ以上プログラムを実行できない状況のこと。また、Wikipediaによると例外(exception)はシステム担当者が問題解決を行う必要がある。と書かれている。 例外処理とは 発生した例外を適切に処理すること。 Wikipediaによると、 「システムの設計で想定されておらず、ユーザー操作によって解決できない問題に対処するための処理である。例外処理の結果として問題が解決されないとシステム障害になる。」 と書かれている。 エラーとは Wikipediaによると、 「ユーザーが解決すべき問題はエラー(error)と呼ぶ」 と書かれている。 例外処理の使い所 これまでに例外とエラーの定義についてみてきた。これらの定義に則ると例外を扱う必要があるのは次のような場合である。 問題がにユーザーによって解決できない 具体的には以下のようなケースが考えられる。 プログラムのミス ネットワークエラー OSのエラー データベースのダウン などである。 逆に例外処理として扱うべきではないパターンは次のような場合である。 問題がユーザーによって解決できる 具体的には以下のようなケースが考えられる。 入力フォームによる入力ミス 認証、認可が必要な操作へのアクセス ちなみに例外とエラーについてWikipediaでは業務エラー、システムエラーと区別している。また紹介したスライドでは業務エラーをビジネス例外、システムエラーを技術的例外と呼んでいる。 transactionでの例外、エラーの扱い まず、前提知識としてRailsにおけるtransactionの動作について説明する。 Railsでは以下のようにtransactionを定義する。 ActiveRecord::Base.transaction do record.save! end このブロック内で何かしらの例外が発生した場合にrollbackが行われるようRailsが処理を行なっている。 では、以下のコードではどうなるか? ActiveRecord::Base.transaction do record.save! rescue Exception false end ここでは、自ら例外を補足しています。この場合Railsは自動でrollbackしてくれない! なので自分でrollbackさせてあげる処理を書く必要がある。 ActiveRecord::Base.transaction do record.save! rescue Exception raise ActiveRecord::Rollback end 詳しくはこちらの記事を参照しました。 トランザクション中にrescueするとロールバックしないので注意! 以上を踏まえるとRailsにおけるtransaction処理は以下のようにするのがベストプラクティスらしい def save success = true ActiveRecord::Base.transaction do # save success &= record1.save success &= record2.save unless success raise ActiveRecord::Rollback ned end success end ここでは、saveメソッドを用いてる。save!にしない理由としては、save!は、バリデーションに失敗した場合でも例外を発生させる。しかし、バリデーションに失敗する原因はほぼユーザーに起因するものである。したがって、業務エラーに区分されるため例外として扱わずただのエラーとして処理を行う。  最後に もっと一般的な例外の扱い方については以下の記事を参考にすると良い。 https://qiita.com/jnchito/items/3ef95ea144ed15df3637
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Open Weather Mapで天気予報取得 web API

初めに 今回ポートフォリオに「世界のお天気」ページを追加しました。 以下のような感じです。 APIキーの取得 以下のページからAPIキーを取得します。 私の場合は既に取得済みなので
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

.rbenv/shims/docker-sync: line 21: /usr/local/Cellar/rbenv/1.1.2/libexec/rbenv: No such file or directory

はじめに brew upgradeしたらdocker-sync だけ見つからなくなりました。 gemで入れたもの全部動かなくなった(全部は確認してないけど) 探しても対処法がぱっと見つからなかった(ちゃんと探してないだけ)のでメモがてら書きます。 結論(解決した方法) 以下を実行で解決した。 rbenv rehash rbenv rehash コマンドを実行すると、大まかには ~/.rbenv/versions/*/bin/ 以下のファイルを ~/.rbenv/shims/ 以下にコピーする。 なぜコピーする必要があるかというと、通常PATHが通っているのは ~/.rbenv/shims 以下となっているからで、ここにコピーしないと rspec とか rubocop といったGemが提供するコマンドを実行できないからである。 cf. https://mogulla3.tech/articles/2020-12-29-01 ということみたいです。 やったこと brewのupdate, upgradeがうまくいってない? brew update && brew upgrade 全て最新になってるっぽい。 brewで問題が起きている? brew doctor dockerのlinkができてないというのが出たので、link brew link docker でも、直らない。他に問題はなさそう。 rbenvの問題? brew reinstall rbenv まだ問題変わらず、、 ?? ----- ここから下を確認して実行すればOK ----- /usr/local/Cellar/rbenv/1.1.2/libexec/rbenv: No such file or director rbenv/1.1.2? rbenvのバージョン見てみる rbenv -v => rbenv 1.2.0 バージョンが違う、、 ll /usr/local/Cellar/rbenv total 0 drwxr-xr-x 10 kazmaw admin 320B 10 9 10:07 1.2.0 rbenv/1.1.2なんてないじゃないか。 brew ls --formula -lt | grep rbenv drwxr-xr-x 3 kazmaw admin 96 Oct 9 10:07 rbenv rbenvのバージョンが上がってしまったからか、、 gemも動かない事に気づいた gem uninstall docker-sync /(略)/.rbenv/shims/gem: line 21: /usr/local/Cellar/rbenv/1.1.2/libexec/rbenv: No such file or directory あー、rbenvのパス通すやつなんかあったな、、 rbenv rehash ❯ docker-sync -h [10:32:08] Commands: docker-sync --version, -v # Prints out the version of docker-sync and exits docker-sync clean # Stop and clean up all sync endpoints docker-sync help [COMMAND] # Describe available commands or one specific command docker-sync list # List all sync-points of the project configuration path docker-sync logs # Prints last 100 lines of daemon log. Only for use with docker-sync started in background. docker-sync restart # Restart docker-sync daemon docker-sync start # Start all sync configurations in this project docker-sync stop # Stop docker-sync daemon docker-sync sync # just sync - do not start a watcher though Options: -c, [--config=CONFIG] # Path of the docker_sync config -n, [--sync-name=SYNC_NAME] # If given, only this sync configuration will be references/started/synced -v, [--version], [--no-version] # prints out the version of docker-sync and exits いけたーー!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

railsのconstraintsを使って、ルーティングを制限する

おはようございます! 朝から警察の方に職務質問を受けてしまった、プレイライフの熊崎です。 そんな怪しさ全開の雰囲気が出ていた僕ですが、引き続きアウトプットを行なっていきたいと思います。 constraintsとは? :constraintsオプションを使って、動的セグメントのURLフォーマットを特定の形式に制限できます。 ref: https://railsguides.jp/routing.html#セグメントを制限する → ルーティングに制限を設定するオプション。constraintsの和訳が制約なので、そのまんま。 制限の仕方 routes.rb get '/articles/:id' , to: 'articles#show', constraints: { id: /[A-Z]\d{5}/ } # match => /articles/A11111, not_match => /articles/111 また、リクエスト内容に応じて制限を加えることができる。 ref: https://railsguides.jp/routing.html#リクエスト内容に応じて制限を加える routes.rb get '/articles/:id' , to: 'articles#show', constraints: { port: 3000 } # ポート番号が3000以外の場合、マッチしない。 また、以下のようにmatchesメソッドを使用して制限を加えることができる。 routes.rb get '/articles/:id' , to: 'articles#show', constraints: ArticleIdRestrict.new class ArticleIdRestrict def matches?(request) # URLの後ろについているidが、記事テーブルのidの中に含まれているか? Article.pluck(:id).include?(request[:id]) end end どんな時に使用するのか? → ルーティングを制限したいとき。 例: 記事を、ジャンルで絞り込みを行う際。 genresテーブル id name 1 SQL 2 Rails routes.rb get '/articles/:genre_name', to: 'articles#index', constraints: ArticleGenreRestrict.new class ArticleGenreRestrict def matches?(request) # ジャンル名がSQLかRailsの場合のみマッチする。 Genre.pluck(:name).include?(request[:genre_name]) end end メリット コントローラー側で、クエリパラメータが正しいかどうかを判断する必要がなくなる。 注意点 以下のように書くと、指定したルーティングが無効になる。 routes.rb resources :articles, only: %i[index] get '/articles/:genre_name', to: 'articles#index', constraints: ArticleGenreRestrict.new class ArticleGenreRestrict def matches?(request) # ジャンル名がSQLかRailsの場合のみマッチする。 Genre.pluck(:name).include?(request[:genre_name]) end end 理由 Railsのルーティングは、ルーティングファイルの「上からの記載順に」マッチします。このため、たとえばresources :photosというルーティングがget 'photos/poll'よりも前の行にあれば、resources行のshowアクションがget行の記述よりも優先されますので、get行のルーティングは有効になりません。これを修正するには、get行をresources行 よりも上 の行に移動してください。これにより、get行がマッチするようになります。 ref: https://railsguides.jp/routing.html#crud、動詞、アクション 参考記事 https://railsguides.jp/routing.html#セグメントを制限する https://railsguides.jp/routing.html#リクエスト内容に応じて制限を加える https://railsguides.jp/routing.html#crud、動詞、アクション 最後に ルーティング周りでこんな機能があるとは思わなかった。 まだまだ知らない機能がいっぱいあるので、1つ1つ覚えていく必要があると感じた。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[Ruby] Rubyで動くブラックジャック作ってみた

Rubyの基礎文法を勉強したときに知識を定着させるために作成したブラックジャックゲームです。 ちなみに、プログラミングを勉強して初めて作った成果物。 実行動画 実装部分 実装の前にマインドマップを作って各クラスの各メソッドが何をするのかを明確にしてから作りました。 マインドマップ Blackjackクラス blackjack.rb require "./deck.rb" require "./card.rb" require "./user.rb" require "./dealer.rb" require "./message.rb" #ゲーム進行 class Blackjack include Message def game_start start_msg deck = Deck.new user = User.new dealer = Dealer.new #手札配る、手札表示 user.user_first_draw_card(deck) dealer.dealer_first_draw(deck) #ユーザーターン #Hitならもう一枚引く、スタンドならループ抜ける while true select_msg #行動選択 select_num = gets.to_i if select_num == 1 user.draw(deck) user.show_hand if user.cal_score_user >= 22 burst_msg return end elsif select_num == 2 break else error_msg end end #ディーラーターン #17以上になるまで引く while true if dealer.cal_score_dealer <= 17 dealer.draw(deck) else break end end user.show_hand dealer.show_hand judge(user, dealer) end def judge(user, dealer) user_score = user.cal_score_user dealer_score = dealer.cal_score_dealer if user_score == dealer_score draw_msg elsif user_score == 21 blackjack_msg elsif dealer_score >= 22 dealer_burst_msg elsif dealer_score > user_score user_lose_msg else user_win_msg end end end ゲームコントローラー部分。 Userはカードを引くか引かないかの行動を選べて、Dealerは18以上になるまでカードを引き続ける処理を書いてます。 プレイヤーが21以上の点数になったら即バーストで負け、21ちょうどならブラックジャックの表記が出て勝ち。 メッセージ部分はmessage.rbに切り出してます。 Deckクラス deck.rb #山札作成、シャフル、ドロー class Deck #山札用の空の配列を用意 def initialize @cards = [] end #山札作成、シャッフル def create mark = ["ハート","クローバー","ダイヤ","スペード"] number = ["A","2","3","4","5","6","7","8","9","10","J","Q","K"] mark.each do |mark| number.each do |number| card = Card.new(mark,number) @cards << card end end @cards.shuffle! end #山札から1枚引く def draw @cards.pop end end ここではカードデッキの生成とカードを引く処理の部分です。 カードをデッキから引く処理は配列の末尾要素を削除するpopメソッドを使うことで実現しています。 Cardクラス card.rb #カード情報 class Card attr_reader :mark,:number #カードオブジェクトの値受け取り def initialize(mark,number) @mark = mark @number = number end #カード情報表示 def info return "#{@mark}の#{@number}" end #スコア計算方法 def score if @nunmber == "J" || @number == "Q" || @number == "K" @nunmber = 10 elsif @number == "A" @number = 1 else @number.to_i end end end スコア計算の部分は、JQKを10点Aは1点として扱っています。 本当のBJだとAは1点か11点のどちらか都合の良い方で扱えるけど難しくて実装断念した‥ Done is better than perfect ってことで今回はとりあえずこれで、今後時間があれば実装します 笑 Userクラス user.rb class User def initialize @user_hands = [] end #最初に引く、手札公開 def user_first_draw_card(deck) 2.times do deck.create card = deck.draw @user_hands << card end puts "====あなたの手札=======" @user_hands.each.with_index(1) do |user_hand, i| puts "#{i}枚目 : #{user_hand.info}" end puts "あなたの合計点数は#{cal_score_user}です" puts "========================" end def cal_score_user user_score = 0 @user_hands.each do |hand| user_score += hand.score end return user_score #合計のスコアスコアを返す end #1枚引く def draw(deck) deck.create card = deck.draw @user_hands << card end #手札表示 def show_hand puts "" puts "====あなたの手札=======" @user_hands.each.with_index(1) do |user_hand, i| puts "#{i}枚目 : #{user_hand.info}" end puts "あなたの合計点数は#{cal_score_user}です" puts "========================" puts "" end end Userは最初に2枚手札を配られて、Hitを選択したときに1枚ずつデッキからカードを引くっていう処理。 Dealerクラス dealer.rb class Dealer def initialize @dealer_hands = [] end #最初に引く、手札公開 def dealer_first_draw(deck) 2.times do deck.create card = deck.draw @dealer_hands << card end puts <<~TEXT ====ディーラーの手札==== 1枚目:#{@dealer_hands.first.info} 2枚目:伏せられている ======================== TEXT end #ディーラーのスコア計算 def cal_score_dealer dealer_score = 0 @dealer_hands.each do |hand| dealer_score += hand.score end return dealer_score #2枚の合計のスコア end def draw(deck) deck.create card = deck.draw @dealer_hands << card end def show_hand puts "" puts "====ディーラーの手札====" @dealer_hands.each.with_index(1) do |dealer_hand, i| puts "#{i}枚目 : #{dealer_hand.info}" end puts "あなたの合計点数は#{cal_score_dealer}です" puts "========================" puts "" end end やっていることはUserと大体同じだけどDealerの場合は2枚配られてカードを1枚伏せてる状態にしてる。 Messageモジュール message.rb module Message def start_msg puts <<~TEXT ======================= Welcome to Blackjack!!! ======================= TEXT end def select_msg puts <<~TEXT どうしますか? 1.Hit(カードを引く) 2.Stand(今の手札で勝負) TEXT end def burst_msg puts "バースト!!" puts "合計点数が21を超えたのであなたの負けです。" end def error_msg puts "1 or 2 を入力してください。" end def draw_msg puts "同点なので引き分けです。" end def blackjack_msg puts "ブラックジャック!! あなたの勝ちです!" end def dealer_burst_msg puts "ディーラーがバーストしました。あなたの勝ちです!" end def user_lose_msg puts "ディーラーの勝ちです!" end def user_win_msg puts "あなたの勝ちです!" end end Blackjacクラスの出力メッセージはメッセージモジュールとして切り出して処理のみにすることで可読性を上げています。 Main main.rb require "./blackjack.rb" blackjack = Blackjack.new blackjack.game_start 最後に 実行するmain部分。 ここでblackjack.game_startを呼び出すことでゲームが始まる。  感想 実際にコードに落とし込む作業は基礎文法を勉強しているときとは比べ物にならないくらい大変でした。 それでも作っているときの楽しさ、実際に完成して動いた時の感動は忘れられません。 次はAの処理や掛け金機能を追加して、よりゲーム性を高めていきたいと思います。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Progate Ruby on Rails5 I〜III 個人的ざっくりまとめ

Railsの立ち上げ ターミナル $ rails new アプリケーション名 例) rails new tweet_app $ rails server 上記入力後、ブラウザのurlに「localhost:3000」を入力し、「Yay!You're on Rails!」と書いてあるページが表示されていればOK ページ作成 ○ページ作成に必要なもの ・ ビュー ・ コントローラ ・ ルーティング ビュー ビューとは、ページの見た目を作るHTMLファイルのこと。 ターミナル $ rails generate controller コントローラ名 アクション名 例)rails generate controller home top または、 rails g controller home top でもOK 「rails g controller home top」でviewsフォルダの中にhomeフォルダとtop.html.erbファイルが作成される。 app/views/home/top.html.erb <h1>Home#top</h1> <p>Find me in app/views/home/top.html.erb</p> コントローラ ページを表示するとき、railsではコントローラを経由して、ブラウザに返している。 先ほど、「rails g controller home top」を実行したとき、同時にコントローラも作成されており、コントローラファイルの場所は、「app/controllers/home_controller.rb」である。 また、rails g controllerでtopアクションも指定しているため、home_controller.rbの中身は以下のようになっている。 app/controllers/home_controller.rb class HomeController < ApplicationController def top #アクション end end コントローラ内のアクションは、コントローラと同じ名前のビューフォルダから、アクションと同じ名前のHTMLファイルを探して、ブラウザに返す役割を担っている ルーティング ページを表示するときコントローラを経由していたが、ブラウザとコントローラを結ぶ役割がルーティングである。 ルーティングは対応表にして考えるとわかりやすい URL コントローラ アクション home/top home top ルーティングが定義されている場所は、「config/routes.rb」で、中身は以下のようになっている config/routes.rb Rails.application.routes.draw do #get "URL" => "コントローラ名#アクション名" get "home/top" => "home#top" #localhost:3000/home/top #URLの部分を「top」に変えると、localhost:3000/topでアクセスできるようになる get "top" => "home#top" #localhost:3000/top #トップページの場合は、URLの部分を"/"にする get "/" => "home#top" end CSSファイルや画像を保存するファイルの場所 ○CSSファイル 「app/assets/stylesheets/コントローラ名.scss」 ○画像を保存するファイル 「public/画像名」 <% %>と<%= %> <% %>は中身が表示されないので、変数の定義などに使われる。 <%= %>は中身が表示される。 <% language = "Ruby" %> <%= language %>を学ぼう Rubyを学ぼう <% language %>を学ぼう を学ぼう @変数 通常、アクションで定義した変数をビューでそのまま使用することはできない。 そこで、「@変数」とすることで、ビューでも使えるようにする。 posts_controller.rb class PostsController < ApplicationController def index @post1 = "hogehoge" post2 = "fugafuga" end end posts/index.html.erb <%= @post1 %> hogehoge <%= post2 %> ※エラー発生 テーブル作成(モデルとマイグレーション) ターミナル $ rails g model モデル名 カラム名:データ型 例) rails g model Post content:text 上記をターミナルに入力し実行すると、「モデルが定義されたファイル」と「マイグレーションファイル」の2つファイルが生成される。 モデルが定義されたファイルの場所は、「app/models/ファイル名.rb」(ファイル名は単数形) models/post.rb class Post < ApplicationRecord end マイグレーションファイルの場所は、「db/migrate/マイグレーション名.rb」 db/migrate/20170228021417_create_posts.rb class CreatePosts < ActiveRecord::Migration[5.0] def change create_table :posts do |t| t.text :content t.timestamps end end end マイグレーションファイルを使って、データベースに変更を反映するにはターミナルに以下を実行する ターミナル $ rails db:migrate rails console rails consoleはRubyのコードを手軽に実行できる。「quit」でやめることができる。 ターミナル $ rails console Loading Development environment (Rails 5.0.1) [1]pry(main) > 1 + 1 => 2 [2]pry(main) > text = "Hello" => "Hello" [3]pry(main) > text + "World" => "HelloWorld" [3]pry(main) > quit saveメソッド saveメソッドはデータベースに保存するメソッド。 例えば、作成したPostインスタンスをpostsテーブルに保存するとき。(このとき、saveメソッドが使えるのは、PostモデルがApplicationRecordを継承しているから) ターミナル $ rails console > post = Post.new(content: "Hello World") > post.save firstメソッド firstメソッドはテーブルの最初のデータを取得できる。 postsテーブル id content 1 hogehoge 2 fugafuga ターミナル > post = Post.first > post.content => "hogehoge" allメソッド allメソッドはテーブルの全てのデータを取得できる。 index番号を指定することで特定の箇所のデータを取得することもできる。 postsテーブル id content 1 hogehoge 2 fugafuga ターミナル > post = Post.all[1].content => "fugafuga" link_toメソッド link_toメソッドは「第一引数に表示する文字」、「第二引数にURL」 application.html.erb <%= link_to("News", "/news") %> ↓ 以下のように変換される application.html <a href="/news">News</a> find_byメソッド find_byメソッドは、特定のidの投稿を取得できる。(allメソッドのindex番号指定でも同じことができる) postsテーブル id content 1 hogehoge 2 fugafuga ターミナル > post = Post.find_by(id: 1) > post.content => "hogehoge" 変数Params 変数Paramsは、ルーティングで設定したURLの「:id」の値を取得できる。 コントローラのアクション内で使う。 例)ルーティングを「localhost:3000/posts/1」に設定した場合 get "post/:id" => "post#show" posts_controller.rb def show @id = params[:id] end posts/show.html.erb <%= @id %> 結果は「1」と出る ルーティングでデータベースに変更を加えるアクションの場合は「get」ではなく「post」 routes.rb post "posts/create" => "posts#create" form_tagメソッド form_tagメソッドは、フォームに入力されたデータを送信することができる。 「form_tag(送信先のURL) do」のように送信先のURLを指定し、そこにデータを送信する。 posts/new.html.erb <%= form_tag("/posts/create") do %> <textarea name="content"></textarea> <input type="submit" value="投稿"> <% end %> name属性を指定したフォームに入力されたデータは、コントローラのアクション内で受け取ることができる。 フォームのデータは変数paramsで受け取る。 paramsはname属性に設定した文字列をキーとしたハッシュになっている。 posts_controller.rb def create params[:content] end #textareaでhogehogeと打って投稿ボタンを押すと、params[:content]にはhogehogeというデータが入ってくる redirect_toメソッド redirect_toメソッドは、他のURLに転送することができる。 「redirect_to("URL")」とすることで、そのページに転送することができる。 posts_controller.rb def create redirect_to("/posts/index") end
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Rails】【JS】GoogleMapで固定した場所にピンを刺したい!【Geocoder】

はじめに この記事では, RailsアプリでGoogle Mapを利用する際に、固定した場所を表示する方法を書き記しています。 特徴は以下です。 Google MapのAPIを利用 指定した緯度軽度の場所にピンを刺す ピンの情報ウィンドウをクリックすると指定したページに遷移する 遷移したページの指定した場所に移動できる(sectionタグを用いる) ページ遷移をなくすこともできます!! この記事をもとに、GoogleMapの表示ができていることが前提とします。 1. Viewを編集する posts/index.html.erb <div id='map'></div> <style> #map { height: 600px; width: 100%; } </style> <script> function initMap() { //初期表示位置:東京駅 let latlng = new google.maps.LatLng(35.68114292160832, 139.76699220422807); //デザイン let styles = [ { stylers: [ { "saturation": 0 }, { "lightness": 0 } ] } ]; let map = new google.maps.Map(document.getElementById('map'), { zoom: 5.3,  //倍率を決める styles: styles, center: latlng }); let transitLayer = new google.maps.TransitLayer(); transitLayer.setMap(map); //複数マーカー ここから ( function() { let markerLatLng = new google.maps.LatLng({lat: 35.170662, lng: 136.923430}); // 名古屋の位置情報を表示 let marker = new google.maps.Marker({ position: markerLatLng, map: map });    //マーカーをクリックしたとき、詳細情報を表示 let infowindow = new google.maps.InfoWindow({ position: markerLatLng, content: "<nav><a href='<%= tweets_url %>#first-block' target='_blank'>名古屋</a></nav>" }); //飛びたいページのURL、タグを入力 marker.addListener('click', function() { infowindow.open(map, marker); }); })(); ( function() { let markerLatLng = new google.maps.LatLng({lat: 34.397521, lng: 132.459266}); // 広島の位置情報を表示 let marker = new google.maps.Marker({ position: markerLatLng, map: map });    //マーカーをクリックしたとき、詳細情報を表示 let infowindow = new google.maps.InfoWindow({ position: markerLatLng, content: "<nav><a href='<%= tweets_url %>#second-block' target='_blank'>広島</a></nav>" }); //飛びたいページのURL、タグを入力 marker.addListener('click', function() { infowindow.open(map, marker); }); })(); ( function() { let markerLatLng = new google.maps.LatLng({lat: 38.260021, lng: 140.882344}); // 仙台の位置情報を表示 let marker = new google.maps.Marker({ position: markerLatLng, map: map });    //マーカーをクリックしたとき、詳細情報を表示 let infowindow = new google.maps.InfoWindow({ position: markerLatLng, content: "<nav><a href='<%= tweets_url %>#third-block' target='_blank'>仙台</a></nav>" }); //飛びたいページのURL、タグを入力 marker.addListener('click', function() { infowindow.open(map, marker); }); })(); //複数マーカー ここまで } </script> <script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyBbOOQW7X6GRBDQbvKGXhHsw3R8j2Fe-XA&callback=initMap" async defer></script>  指定する地図のピンの位置について //複数マーカー ここから ( function() { let markerLatLng = new google.maps.LatLng({lat: 35.17101, lng: 136.88149}); // 名古屋の位置情報を表示 let marker = new google.maps.Marker({ position: markerLatLng, map: map }); {lat: 35.170662, lng: 136.923430}に、緯度軽度を入力します。 Google Mapで入れたい場所を検索し、ピンの位置を右クリックすると緯度と軽度が表示されます。 飛ばしたい遷移先のURLについて content: "<nav><a href='<%= tweets_url %>#third-block' target='_blank'>   名古屋</a></nav>"}); //飛びたいページのURL、タグを入力 続いて、遷移先のページ指定についてです。 Rubyを使っている場合は、 $ rails routes をするとpathが表示されると思いますが、pathのかわりにurlといれます。 また、そのページの遷移場所を指定するときは、 タグを用いて、遷移先のページを書き、その後 <%= tweets_url %> の後ろに #third-block のように入力します。 sectionタグの使い方に関してはこのような記事を参考にしてください。 リファレンス idについて ページ内遷移について 2-5. 自己紹介サイトを作ろう! 終わりに これでGoogle Mapを利用する際に、固定した場所を表示することができました! Railsで書いているけどMapに関してはJSを用いなければならず、よくわからない!という人をよく見受けます。 確かによくわからない部分もありますが、どこがどんな風に対応しているかを考えれば糸口は見つかりますのでご自身の必要に応じて変更してみてください!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む