20220115のRailsに関する記事は13件です。

【個人開発】海とサーフィンが好きすぎて、海のように見え方が変わるサーフィン日記共有サービスを作ってみた。

はじめに 天気が雪の日は雪が降ります。 サーフィンをしたことがありますか? 一度きりの人生、自然と一体になれるこんな素晴らしいスポーツをやってみる事もしないなんて勿体ない事です。 私は海とサーフィンを愛しています。 自身の大好きなものを題材に作品を作って誰かの心に届くものにしたい!そんな想いがあります。 初めまして。りゅうじと申します。 【Twitter】 https://twitter.com/otokomigakimasu 【今回作ったサービス】 https://www.namikki.jp 私はエンジニアの方は全員海の近くに住んでサーフィンをした方がいいと思っています。 メリット 都会で家賃が高い→海の側なら家賃が安い ジムで筋トレ→サーフィンで筋トレ 日頃PCから電磁波を浴びている→サーフィン(素足で浜辺を歩くことでアーシングする) 散歩して日光を浴びてセロトニンを出したい→サーフィンは太陽光を浴びられます サウナと水風呂で整いたい→サーフィンは本当に整います ダイエット→サーフィンすれば痩せて引き締まります メンタルが不安定→サーフィンすると気持ちが明るくなります アンチエイジング→サーフィンしてる方は皆さん若々しいです これら表面的なものは付加価値です。 実際にやってみると本質はここではありません。 自然に発生する波と一体になる感覚は筆舌に尽くし難いものです。 サーフィンの道具を買うといった初期投資も、家賃の差額とジムに通っている方ならジムの会員費1年分あれば十分元が取れてしまうでしょう。 正直きっかけはなんだっていいのです。 さあ、サーフィンしましょう! Namikki(なみっき) https://www.namikki.jp/ サービス概要 愛知県田原市の伊良湖エリアのサーファーがサーフィン日記を共有できるSNSサービスです。 エリアを限定して始動しましたが、これから私が様々な地域でサーフィンする中で拡張していく予定です。 1. 田原市の3時間ごとの天気予報5日間分を表示 2. 投稿機能 (無限スクロールにしました) サーファーはスマートフォンからSNSに投稿される方が多いので、スマホファーストの実装しています。 そのため、無限スクロールを採用しました。 3. いいね・コメントがあった場合に通知機能をつけました。 自身の投稿・自身がコメントした投稿したコメントに反応があると右上のベルに赤いマークがついて通知がきたとわかるようにしました。 このサービスが交流のきっかけになってもらえたらと思い実装しました。 通知ページ 使用技術 Ruby 2.7.2 Rails 6.1.4.1 JavaScript 主なGem better_errors bullet sorcery carrier_wave rails_admin factory-bot capybara pry-byebug rubocop テスト RSpec フロントライブラリ JQuery ストレージサービス Amazon S3 ER図 こだわったポイント 海はその日の天気によって見え方が変わるので Namikkiも同様にするために…。 取得した天気予報に応じて背景画像を変化させました 雨の日 雷雨の日 雪の日 今後実装したい事 今後、自身が実際にサーフィンしたエリアも追加します 返信相手を指定してその人にのみ通知がいくようにする(現状は投稿にコメントした人全員に通知がいきます) 終わりに 最後まで読んでいただきありがとうございました。 これからサーフィンを始める方にとっては、初めてサーフィンをした日記からつけていただき感じた事を記録しておくと財産になります。 今回リリース時では私の地元の海、伊良湖エリアを限定にしたサービスにしました。 実際にこれから、様々な海でサーフィンしていき、その都度このサービスを拡張させていきたいと考えています。 自分の作った作品と共に成長したい!と考えています。 【Twitter】 https://twitter.com/otokomigakimasu 【今回作ったサービス】 https://www.namikki.jp
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

railsチュートリアル第十四章 [Follow]のWebインターフェイス 統計と[Follow]フォーム

[Follow]のWebインターフェイス この節では、モックアップで示したようにフォロー/フォロー解除の基本的なインターフェイスを実装します。 フォローしているユーザーと、フォロワーにそれぞれ表示用のページを作成します。 ユーザーのステータスフィードを追加して、サンプルアプリケーションを完成させます。 フォローのサンプルデータ サンプルデータにfollowing/followerの関係性を追加する db/seeds.rb . . . # 以下のリレーションシップを作成する users = User.all # 全ユーザー user = users.first # 最初のユーザー following = users[2..50] # 全体の3(2+1)番目から51(50+1)番目まで呼び出す followers = users[3..40] # この場合 4番目から41番目まで呼び出す following.each { |followed| user.follow(followed) } # 「each」メソッドは配列や範囲オブジェクトなどで用意されているメソッドであり、オブジェクトに含まれている要素を順に取り出します。 # 配列から一つずつ取り出し、自分にフォローさせる。 followers.each { |follower| follower.follow(user) } # それぞれのユーザーに自分をフォローさせる 演習 1. コンソールを開き、User.first.followers.countの結果がリスト 14.14で期待している結果と合致していることを確認してみましょう。 > User.first.followers.count User Load (0.1ms) SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ? [["LIMIT", 1]] (1.0ms) SELECT COUNT(*) FROM "users" INNER JOIN "relationships" ON "users"."id" = "relationships"."follower_id" WHERE "relationships"."followed_id" = ? [["followed_id", 1]] => 38 >> User.first.following.count User Load (0.2ms) SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ? [["LIMIT", 1]] (0.8ms) SELECT COUNT(*) FROM "users" INNER JOIN "relationships" ON "users"."id" = "relationships"."followed_id" WHERE "relationships"."follower_id" = ? [["follower_id", 1]] => 49 2. 先ほどの演習と同様に、User.first.following.countの結果も合致していることを確認してみましょう。 1問目で解決 統計と[Follow]フォーム プロフィールページとHomeページを更新して、これを反映しましょう。 プロフィールページとHomeページに、フォローしているユーザーとフォロワーの統計情報を表示するためのパーシャルを作成します。 フォロー用とフォロー解除用のフォームを作成します。 フォローしているユーザーの一覧("following")とフォロワーの一覧("followers")を表示する専用のページを作成 Usersコントローラにfollowingアクションとfollowersアクションを追加する config/routes.rb Rails.application.routes.draw do . . . member do # member メンバールーティング(デフォルトで作成されるRESTfullなルーティング)を追加 get :following, :followers # URLで指定したファイルの送信を要求するためのもの。コントローラやアクションを呼び出すこともある。 # :controller, :action コントローラとアクションを指定。必ずセットで指定 end end . . . end フォロワーの統計情報を表示するパーシャル app/views/shared/_stats.html.erb <% @user ||= current_user %> <!--<%...%> 埋め込みruby @userにどちらかが返される--> <div class="stats"> <!--クラス名--> <a href="<%= following_user_path(@user) %>"> <!--<a href="リンク先のURL">アンカーテキスト</a>--> <strong id="following" class="stat"> <!--<strong>~</strong>で囲んだテキストを強調--> <%= @user.following.count %> <!--フォローの数(強調された文字) これがアンカーテキストになる--> </strong> following <!--これもアンカーテキスト    この場合フォロー数とfollwingがアンカーテキストとなる--> </a> <a href="<%= followers_user_path(@user) %>"> <strong id="followers" class="stat"> <%= @user.followers.count %> </strong> followers </a> </div> Homeページにフォロワーの統計情報を追加する app/views/static_pages/home.html.erb <div class="row"> <aside class="col-md-4"> <section class="user_info"> <%= render 'shared/user_info' %> <!--user_infoアクションに移動する--> </section> <section class="stats"> <%= render 'shared/stats' %> </section> <section class="micropost_form"> <%= render 'shared/micropost_form' %> </section> </aside> <div class="col-md-8"> <h3>Micropost Feed</h3> <%= render 'shared/feed' %> </div> </div> フォロワーの統計情報を表示するパーシャル app/views/shared/_stats.html.erb <% @user ||= current_user %> <!--<%...%> 埋め込みruby @userにどちらかが返される--> <div class="stats"> <!--クラス名--> <a href="<%= following_user_path(@user) %>"> <!--<a href="リンク先のURL">アンカーテキスト</a>--> <strong id="following" class="stat"> <!--<strong>~</strong>で囲んだテキストを強調--> <%= @user.following.count %> <!--フォローの数(強調された文字) これがアンカーテキストになる--> </strong> following <!--これもアンカーテキスト    この場合フォロー数とfollwingがアンカーテキストとなる--> </a> <a href="<%= followers_user_path(@user) %>"> <strong id="followers" class="stat"> <%= @user.followers.count %> </strong> followers </a> </div> Homeページにフォロワーの統計情報を追加する app/views/static_pages/home.html.erb <% if logged_in? %> <%= render 'static_pages/user_logged_in' %> <% else %> <%= render 'static_pages/user_not_logged_in' %> <% end %> Homeページのサイドバー用のSCSS app/assets/stylesheets/custom.scss .stats { overflow: auto; margin-top: 0; padding: 0; a { float: left; padding: 0 10px; border-left: 1px solid $gray-lighter; color: gray; &:first-child { padding-left: 0; border: 0; } &:hover { text-decoration: none; color: blue; } } strong { display: block; } } .user_avatars { overflow: auto; margin-top: 10px; .gravatar { margin: 1px 1px; } a { padding: 0; } } .users.follow { padding: 0; } /* forms */ . . . フォロー/フォロー解除フォームのパーシャル app/views/users/_follow_form.html.erb <% unless current_user?(@user) %> <!--ログインしてなないか?--> <div id="follow_form"> <% if current_user.following?(@user) %> <!--ログインされたユーザーは@userをフォローしているか?--> <%= render 'unfollow' %> <!--unfollowのパーシャルに移動--> <% else %> <%= render 'follow' %> <% end %> </div> <% end %> Relationshipリソース用のルーティングを追加する config/routes.rb Rails.application.routes.draw do get 'password_resets/new' get 'password_resets/edit' get 'sessions/new' root 'static_pages#home' # 何の意味がわからん # ホーム画面がhomeページなるらしい get '/help', to: 'static_pages#help' # static_pagesコントローラからhomeアクションに紐付けされる # getでアクセルすることでページを取得することができる get '/about', to: 'static_pages#about' # 何を書いているかはわからない get '/contact', to: 'static_pages#contact' # aboutアクションにGETリクエストを送る get '/signup', to: 'users#new' # urlに/signupと書くとuserコントローラのnewアクションを起こす get '/login', to: 'sessions#new' # データを取得 post '/login', to: 'sessions#create' # データを投稿 delete '/logout', to: 'sessions#destroy' # 削除 resources :users do # usersコントローラ member do # member メンバールーティング(デフォルトで作成されるRESTfullなルーティング)を追加 get :following, :followers # URLで指定したファイルの送信を要求するためのもの。コントローラやアクションを呼び出すこともある。 # :controller, :action コントローラとアクションを指定。必ずセットで指定 end end resources :users # /users/1の有効にするため resources :account_activations, only: [:edit] # editアクションへの名前付きルートが必要になるため # ルーティングのアカウント有効化 resources :password_resets, only: [:new, :create, :edit, :update] # 新しいパスワードを再設定するためのフォームと、Userモデル内のパスワードを変更するため resources :microposts, only: [:create, :destroy] # マイクロポストにはcreate,destroyあれば十分 # RESTfulなルーティングのサブセットになります。 # サブセットとは、一部分、部分集合、下位集合などの意味を持つ英単語 resources :relationships, only: [:create, :destroy] # ??? end ユーザーをフォローするフォーム app/views/users/_follow.html.erb <%= form_with(model: current_user.active_relationships.build, local: true) do |f| %> <div><%= hidden_field_tag :followed_id, @user.id %></div> <%= f.submit "Follow", class: "btn btn-primary" %> <% end %> ユーザーをフォロー解除するフォーム app/views/users/_unfollow.html.erb <%= form_with(model: current_user.active_relationships.find_by(followed_id: @user.id), html: { method: :delete }, local: true) do |f| %> <%= f.submit "Unfollow", class: "btn btn-default" %> <% end %> プロフィールページにフォロー用フォームとフォロワーの統計情報を追加する app/views/users/show.html.erb <% provide(:title, @user.name) %> <div class="row"> <!--サイドバーを表示させる--> <aside class="col-md-4"> <!--サイドバーを表示させる--> <section class="user_info"> <h1> <%= gravatar_for @user %> <%= @user.name %> </h1> </section> <section class="stats"> <%= render 'shared/stats' %> <!--???--> </section> </aside> <div class="col-md-8"> <%= render 'follow_form' if logged_in? %> <!--フォローされているかを調べる--> <% if @user.microposts.any? %> . . . </div> 演習 1. ブラウザから /users/2 にアクセスし、フォローボタンが表示されていることを確認してみましょう。同様に、/users/5 では[Unfollow]ボタンが表示されているはずです。さて、/users/1 にアクセスすると、どのような結果が表示されるでしょうか? フォロー、アンフォローのボタンが無かった。 2. ブラウザからHomeページとプロフィールページを表示してみて、統計情報が正しく表示されているか確認してみましょう。 確認 3. Homeページに表示されている統計情報に対してテストを書いてみましょう。同様にして、プロフィールページにもテストを追加してみましょう。ヒント: リスト 13.28で示したテストに追加してみてください。 しなかった。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

railsチュートリアル第十四章 ステータスフィールド サブセレクト

ステータスフィールド 現在のユーザーにフォローされているユーザーのマイクロポストの配列を作成し、現在のユーザー自身のマイクロポストと合わせて表示します。 このセクションを通して、複雑さを増したフィードの実装に進んでいきます。 これを実現するためには、RailsとRubyの高度な機能の他に、SQLプログラミングの技術も必要です。 動機と計画 ステータスフィードのテスト test/models/user_test.rb require 'test_helper' . . . test "feed should have the right posts" do michael = users(:michael) archer = users(:archer) lana = users(:lana) # テストユーザー # フォローしているユーザーの投稿を確認 lana.microposts.each do |post_following| # フィードを作成する assert michael.feed.include?(post_following) # マイケルのフィードにフォローが投稿されてるのが含まれているか? end # 自分自身の投稿を確認 michael.microposts.each do |post_self| assert michael.feed.include?(post_self) # マイケルのフィードに自分自身も含まれているか? end # フォローしていないユーザーの投稿を確認 archer.microposts.each do |post_unfollowed| assert_not michael.feed.include?(post_unfollowed) # フォローしていないものは含まれていないか? end end end テスト ubuntu:~/environment/sample_app (following-users) $ rails t Running via Spring preloader in process 5728 Started with run options --seed 13331 FAIL["test_feed_should_have_the_right_posts", #<Minitest::Reporters::Suite:0x000056391fee5aa8 @name="UserTest">, 3.5545889589998296] test_feed_should_have_the_right_posts#UserTest (3.56s) Expected false to be truthy. test/models/user_test.rb:131:in `block (2 levels) in <class:UserTest>' test/models/user_test.rb:129:in `block in <class:UserTest>' 74/74: [===========================] 100% Time: 00:00:04, Time: 00:00:04 Finished in 4.55511s 74 tests, 341 assertions, 1 failures, 0 errors, 0 skips Expected false to be truthy. とりあえず動くフィードの実装 app/models/user.rb テスト ubuntu:~/environment/sample_app (following-users) $ rails t Running via Spring preloader in process 7499 Started with run options --seed 53450 74/74: [===========================] 100% Time: 00:00:04, Time: 00:00:04 Finished in 4.11729s 74 tests, 378 assertions, 0 failures, 0 errors, 0 skips 演習 1. リスト 14.44において、現在のユーザー自身の投稿を含めないようにするにはどうすれば良いでしょうか? また、そのような変更を加えると、リスト 14.42のどのテストが失敗するでしょうか? 2. リスト 14.44において、フォローしているユーザーの投稿を含めないようにするにはどうすれば良いでしょうか? また、そのような変更を加えると、リスト 14.42のどのテストが失敗するでしょうか? 3. リスト 14.44において、フォローしていないユーザーの投稿を含めるためにはどうすれば良いでしょうか? また、そのような変更を加えると、リスト 14.42のどのテストが失敗するでしょうか? ヒント: 自分自身とフォローしているユーザー、そしてそれ以外という集合は、いったいどういった集合を表すのか考えてみてください。 サブセレクト whereメソッド内の変数に、キーと値のペアを使う app/models/user.rb class User < ApplicationRecord . . . # 試作feedの定義 # 完全な実装は次章の「ユーザーをフォローする」を参照 def feed # すべてのユーザーがフィードを持つので、feedメソッドはUserモデルで作るのが自然です Micropost.where("user_id IN (:following_ids) OR user_id = :user_id", following_ids: following_ids, user_id: id) # following_ids フォローのユーザーidを取得 # id 要素 # whereメソッド テーブル内の条件に一致したレコードを配列の形で取得することができるメソッド # user_idを条件として取得することができる。 # 上の疑問符があることで、SQLクエリに代入する前にidがエスケープされるため # 、SQLインジェクションと呼ばれる深刻なセキュリティホールを避けることができます。 # SQL文に変数を代入する場合は常にエスケープする習慣をぜひ身につけてください。 end . . . end フィードの最終的な実装 app/models/user.rb class User < ApplicationRecord . . . # 試作feedの定義 # 完全な実装は次章の「ユーザーをフォローする」を参照 def feed # すべてのユーザーがフィードを持つので、feedメソッドはUserモデルで作るのが自然です following_ids = "SELECT followed_id FROM relationships WHERE follower_id = :user_id" Micropost.where("user_id IN (#{following_ids}) OR user_id = :user_id", user_id: id) # following_ids フォローのユーザーidを取得 # id 要素 # whereメソッド テーブル内の条件に一致したレコードを配列の形で取得することができるメソッド # user_idを条件として取得することができる。 # 上の疑問符があることで、SQLクエリに代入する前にidがエスケープされるため # 、SQLインジェクションと呼ばれる深刻なセキュリティホールを避けることができます。 # SQL文に変数を代入する場合は常にエスケープする習慣をぜひ身につけてください。 end . . . end テスト ubuntu:~/environment/sample_app (following-users) $ rails t Running via Spring preloader in process 10510 Started with run options --seed 15480 74/74: [===========================] 100% Time: 00:00:04, Time: 00:00:04 Finished in 4.25870s 74 tests, 378 assertions, 0 failures, 0 errors, 0 skips
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Rails】kaminariとboostrap4を使ってページネーションをする

ページネーションとは? ページネーションとは画像の通り、検索した時などの下に出てくる、今は何ページ目…と表記してくれるもの。 railsでこのページネーションを導入する際にはkaminariと言うgemを使っていく。 手順 ①kaminariのインストール ②ページネーションデザインのデフォルトの設定ファイルを作成/編集 ③コントローラーの編集 ④viewの実装 ①kaminariのインストール 今回はboostrap4を一緒に使っていくので、Gemfileにkaminariとbootstrap4-kaminari-viewsを記入し、bundle installする。 Gemfile. gem 'kaminari' gem 'bootstrap4-kaminari-views' → bundle install ②ページネーションデザインのデフォルトの設定ファイルを作成/編集 ターミナルにて、設定ファイルの作成コマンドを実施。 ターミナル. rails g kaminari:config config/initializers/kaminari_config.rbを開くと、下記がデフォルトで入っている。 基本的にコメントアウトされているので設定したいもののコメントアウトを外していく。それぞれの意味は下記に記載していく。 kaminari_config.rb # frozen_string_literal: true Kaminari.configure do |config| # config.default_per_page = 25         1ページあたりの表示件数(デフォルトは25レコード) # config.max_per_page = nil         1ページあたりの最大表示件数(デフォルトはnil。つまり無限) # config.window = 4        現在のページから、左右何ページ分のリンクを表示させるか(デフォルトは4件) # config.outer_window = 0        最初(First)と最後(Last)のページから、左右何ページ分のリンクを表示させるか(デフォルトは0件) # config.left = 0        最初(First)のページから、何ページ分のリンクを表示させるか(デフォルトは0件) # config.right = 0        最終(Last)ページから、何ページ分のリンクを表示させるか(デフォルトは0件) # config.page_method_name = :page        モデルに追加されるページ番号を指定するスコープの名前:page by default # config.param_name = :page        ページ番号を渡すために使用するパラメータ名(デフォルトは:page)        ↑Board.page(params[:page])のようにparamsメソッドで取得できる。 # config.max_pages = nil        最大ページ数(デフォルトはnil) # config.params_on_first_page = false        最初のページでparamsを無視しない end ③コントローラーの編集 ページネーションを表示させたいところに.page(params[:page])を追加。 例えばBoardにページネーションをつけたい場合、以下のように記載。 boards_controller.rb def index @boards = Board.all.includes(:user).order(created_at: :desc).page(params[:page]) end ここの表記に.per(20)を付け足たら以下のようになる↓ @boards = Board.all.includes(:user).order(created_at: :desc).page(params[:page]).per(20) ただし、1ページにこの場合だと最大20件と設定できるが、毎回ページネーションを新たに追加するごとに同じように記入しなければならないので、出来ればコントローラーに記載した方が、DRYな記法になる。 ④viewの実装 あとはページネーションさせたいviewに下記を追記するだけで出来る。 index.html.rb <%= paginate @boards %> ページネーションのデザイン変更 先程のだけだと少しシンプルすぎるので、先程のviewに以下を書き足す。 index.html.rb <%= paginate @boards, theme: 'twitter-bootstrap-4' %> 結果きれいに装飾され見やすくかつボタンが押しやすくなった。 またこれとは別に、cssを編集してさらに自分好みのデザインに変更することも可能。 ラベルを日本語に変更 ラベルとは、ページ番号の前後についているFirstやPrveのこと。 デフォルトでは英語表記なので、こちらを日本語に変更したい場合はrailsアプリのデフォルト言語を日本語に変更したあと、ja.ymlにてそれぞれ編集する必要がある。 ▶︎デフォルトの言語を日本語に設定 config/localesに日本語変換用のja.ymlを作成。下記のは一例。 config/locales/ja.yml ja: views: pagination: first: "&laquo; 最初" last: "最後 &raquo;" previous: "&lsaquo; 前" next: "次 &rsaquo;" truncate: "..." ラベルのアイコン化 ラベルをアイコンのみにすることで、よりシンプルなページネーションを作ることができる。 Font Awesome使った例を記載。 はじめに、Font Awesomeを読み込むために, app/views/layouts/application.html.erbに以下のコードを追加して、アプリ全体にFont Awesomeを適用。 app/views/layouts/application.html.rb #コード追加 Font Awesome読み込みコード <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.8.2/css/all.css" integrity="sha384-oS3vJWv+0UjzBfQzYUhtDYW+Pj2yciDJxpsK1OYPAYjqT085Qq/1cq5FLXAZQ7Ay" crossorigin="anonymous"> あとは先程出てきたja.ymlファイルに使用したいアイコンのコードに書き換えるのみでOK。 << < 1 2 3 .....9 10 > >>のようになる。 config/locales/ja.yml ja: views: pagination: first: <i class="fas fa-angle-double-left"></i> last: <i class="fas fa-angle-double-right"></i> previous: <i class="fas fa-angle-left"></i> next: <i class="fas fa-angle-right"></i> truncate: "..." 参考記事 【Rails】kaminariの使い方をざっくりまとめてみた 【Rails初心者】ページネーションを実装して自分好みにデザインを変える Kaminariの使い方 まとめ
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【共同開発】欲しいものを買う優先度をランキング形式で提示するサービス「HoshiMe」をリリースしました!

はじめに 早速ですが質問です。衝動買いをして後悔した経験はありませんか? 私はよく後悔しています。。 ずっと欲しかったものがあったにも関わらず、違うものを衝動買いしてお金を使ってしまい、本当に欲しかったものを買うためのお金がなくなってしまったことがありました。 そんな悩みを解決するために開発したのが、欲しいものを買う優先度をランキング形式で提示するサービス 『HoshiMe』(ほしみぃ) です。 使用技術 バックエンド - Ruby 2.6.6 - Rails 6.1.4 フロントエンド - TailwindCSS - JavaScript(jQuery) - Chart.js 主なサービス内容 欲しいもの登録ページ ユーザ登録なしで欲しいもの3つ登録できるように実装しました。 ランキングページ 欲しいものを登録すると、以下のランキング形式で買う優先度が表示されます。また、ランキング上位3つ分の計算データをレーダーチャートを使って差が分かるように表示しています。 こだわったポイント ゲストユーザ機能 HoshiMeでは、できる限りたくさんのユーザの方々に、まず触って頂きたいという思いから、「はじめる」を押した時点でゲストユーザとしてログインされる仕様になっています。 TRANSACTION (0.1ms) BEGIN User Load (4.9ms) SELECT "users".* FROM "users" ORDER BY "users"."id" DESC LIMIT $1 [["LIMIT", 1]] => #<User:0x00007fe3bd20af00 id: 108, name: "ae2b4e", email: "guest_ae2b4e@example.com", crypted_password: "$2a$10$/3SasIg85bnveT0IK/VIIOvEoAQ09QBK7XjrO5mvIs.BozatxJpp2", salt: "b9E3njyFrvUAkHuXmzvW", uuid: "448fb42e-51df-4a35-bf8f-45c28cbe0a08", created_at: Sat, 15 Jan 2022 14:46:11.513789000 JST +09:00, updated_at: Sat, 15 Jan 2022 14:46:11.513789000 JST +09:00, is_valid: true, role: "guest", reset_password_token: nil, reset_password_token_expires_at: nil, reset_password_email_sent_at: nil, access_count_to_reset_password_page: 0> また、ユーザ新規登録したときにゲスト時に作成したデータをユーザ新規登録時にそのまま引き継ぐ仕様になっています。 アイテム一括投稿フォームの実装 入力フォームを複数用意し、submitボタンが押されたらフォームの内容をまとめて保存できるように実装しました。Form Objectで定義しているitemsでフォームヘルパーのfields_forを使ってアイテムの情報を下記のようなハッシュ形式で受け取ります。 "form_item_collection"=>{"items_attributes"=>{ "0"=>{"name"=>"Apple Watch", "degree"=>"60", "start_date"=>"180", "finish_date"=>"180", "price"=>"50000"}, "1"=>{"name"=>"リング", "degree"=>"30", "start_date"=>"30", "finish_date"=>"360", "price"=>"31000"}, "2"=>{"name"=>"キーボード", "degree"=>"70", "start_date"=>"360", "finish_date"=>"10", "price"=>"21000"}}} そしてこの送信された一つずつのアイテムのuser_idにcurrent_user.idを付与して一括で保存する仕組みを作成しました。 jRangeを使った範囲選択フォーム フォームヘルパーを使用して、レンジ入力をしたいときは下記のようにrange_fieldを使います。 <%= f.range_field :degree, min:"0", max:"100" %> しかしこのままでは目盛りがないので、どれくらいの範囲を選択しているのか分かりづらいです。 目盛りをつけるためにjRangeというjQueryというライブラリを導入しました。 ランキング機能 欲しいものを保存すると同時に保存した値を使ってランキングに必要な計算をしています。 その部分について簡単に説明します。 素直に入力された各パラメータ(欲しい度、いつから欲しい?、いつまでに欲しい?、値段)を合算してランキングにすると、値段の値(0~100,000)が大きすぎて値段のランキングみたいになってしまうので、各パラメータを変換します。 以下は「欲しい度」を計算するコードです。 # data にはユーザが入力した値が入る def calculate_degree(data) case data when 0..20 degree_value = 2 # 欲しい度が 0~20 なら2に変換 when 21..40 degree_value = 4 # 同様に 21 ~ 40 なら4に変換 when 41..60 degree_value = 6 when 61..80 degree_value = 8 when 81..100 degree_value = 10 end degree_value * 0.4 end このように各パラメータを5分割にし2、4、6、8、10に変換します。 計算の最後に出てくる×0.4の係数ですが、これはそのパラメータの重要度によって値を変えています。 重要度が高いものから順に、 いつまでに欲しい? : 0.8 いつから欲しい? : 0.6 欲しい度 : 0.4 値段 : 0.2 欲しいものを登録する際の「いつまでに欲しい?」が一番ランキングに影響度が高く、「値段」は一番影響度が小さいことになります。 このように各パラメータを換算して係数をかけたものを合計し降順にしたものがランキングとなります。 共同開発の目的 私たちが共同開発をやった目的は大きく分けて次の3つです。 実務に入る前に共同で開発する時の流れや、雰囲気を知ること メンバー間でコミュニケーションを取りながら協力してひとつのものを作るという経験をすること GitやGitHubなどをより使えるようになること 今回3人で開発したのですが、難しい技術を使って実装するとか、大きなアプリを作るとかではなく、みんなで協力しながら楽しくやることを念頭に置いて取り組みました。 最後に Twitter : sayo https://twitter.com/sayo_saru 今回のチーム開発を通して、誰がみても理解できるPRを書くこと、チームメンバーのPRを丁寧にレビューすることの大切さを痛感しました。毎週行っていたチーム開発会議で、本音で自分の考えていることを言い合えるメンバーだったので、とても楽しく開発ができました。 ありがとうございました。 Twitter : ワタル https://twitter.com/wataru_pgm コンフリを起こした時の対処法、プルリクの書き方、チームが上げたプルリクをレビューするため、チェック用のブランチを作成して、挙動を実際に確かめるなど、たくさん繰り返し、多くのことを学ぶことができました。 新年の年明けと同時にHoshiMeをリリースすることができ、チームHoshiMeと使っていただいたユーザの方々に感謝です! Twitter : たけむー https://twitter.com/takemuu_pote 今回初めて共同開発をやってみて、楽しかったというのが率直な感想です。 アイディア出しから始まり、画面遷移図とER図作成、実装してリリースまで3人で議論を重ねながら一緒にやり切ることができたのはとても良い経験になりました。 上記で述べた目的も達成でき、目標としていたあけおめリリースもできたので満足しています。 今回この3人で一緒にやれて本当に良かったと思います。 また機会があればやろうと思います。 最後まで読んでいただきありがとうございました。 今回作ったアプリ あけおめリリースツイート
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

DockerでRails 6 + postgresの開発環境構築

DockerでRails6の開発環境を構築するときにやったこと。 対象 dockerについてなんとなく知っていて、これからrails,postgreでwebアプリの開発環境を用意しようとしている方向けです。 自分の備忘録も兼ねて書いてみました。 環境 ホスト環境 macOS Caterina 10.15.5 Docker version 20.10.2 構築しようとする環境 ruby 2.7 postgresql 10.7 rails 6.1.1 rails用のDockerfileの作成 Dockerfileの作成します。DockerfileとはDockerイメージを実行する際に実行するコマンドをまとめたものです。 $ touch Dockerfile 上記で作成したDockerfileに以下のコマンドをお好きななエディタで記述していきます。 まずはベースとなるイメージを設定します。ベースはruby2.7のイメージを使用し、nodeのイメージは後ほど使用します。 また、環境変数LANGを設定します。 Dockerfile FROM node:14.10 AS node FROM ruby:2.7 ENV LANG "C.UTF-8" mysqlを削除して、postgresqlをインストールします。 Dockerfile RUN apt-get update -qq && \ apt-get remove -y --purge mysql\* && \ apt-get install -y build-essential libpq-dev postgresql-client && \ rm -rf /var/lib/apt/lists/* コンテナの起動順を制御するために、dockerizeをインストールします。 Dockerfile ENV DOCKERIZE_VERSION v0.6.1 RUN wget https://github.com/jwilder/dockerize/releases/download/$DOCKERIZE_VERSION/dockerize-linux-amd64-$DOCKERIZE_VERSION.tar.gz \ && tar -C /usr/local/bin -xzvf dockerize-linux-amd64-$DOCKERIZE_VERSION.tar.gz \ && rm dockerize-linux-amd64-$DOCKERIZE_VERSION.tar.gz コンテナ起動時に実行するコマンドを指定するためにentrykitをインストールします。 Dockerfile ENV ENTRYKIT_VERSION 0.4.0 RUN wget https://github.com/progrium/entrykit/releases/download/v${ENTRYKIT_VERSION}/entrykit_${ENTRYKIT_VERSION}_Linux_x86_64.tgz \ && tar -xvzf entrykit_${ENTRYKIT_VERSION}_Linux_x86_64.tgz \ && rm entrykit_${ENTRYKIT_VERSION}_Linux_x86_64.tgz \ && mv entrykit /bin/entrykit \ && chmod +x /bin/entrykit \ && entrykit --symlink 日本語フォントのインストールをします。 Dockerfile RUN cd /tmp && \ mkdir noto && \ curl -O -L https://noto-website-2.storage.googleapis.com/pkgs/NotoSansCJKjp-hinted.zip && \ unzip NotoSansCJKjp-hinted.zip -d ./noto && \ mkdir -p /usr/share/fonts/noto && \ cp ./noto/*.otf /usr/share/fonts/noto/ && \ chmod 644 /usr/share/fonts/noto/*.otf && \ fc-cache -fv && \ rm -rf NotoSansCJKjp-hinted.zip ./noto yarnとnodeをnodeイメージからコピーし、シンボリックリンクの設定を行います。 Dockerfile ENV YARN_VERSION 1.22.5 COPY --from=node /opt/yarn-v$YARN_VERSION /opt/yarn COPY --from=node /usr/local/bin/node /usr/local/bin/ RUN ln -s /opt/yarn/bin/yarn /usr/local/bin/yarn \ && ln -s /opt/yarn/bin/yarnpkg /usr/local/bin/yarnpkg ワークディレクトリを作成します。 Dockerfile ENV APP_ROOT "/hoge_app" RUN mkdir $APP_ROOT WORKDIR $APP_ROOT 上記でインストールしたentrykitのprehookという機能を使用し、コンテナ起動前に時刻したいコマンドを設定します。 Dockerfile ENTRYPOINT [ \ "prehook", "ruby -v", "--", \ "prehook", "dockerize -timeout 60s -wait tcp://hoge_postgresql:5432", "--", \ "prehook", "bundle install -j4 --quiet", "--", \ "prehook", "yarn install --ignore-optional", "--" ] postgresql用のDockerfileの作成 Dockerfileの作成を行います。 $ mkdir docker $ mkdir docker/db $ touch docker/db/Dockerfile postgresqlのイメージをベースとして使用します。さらに言語の設定をします。 docker/db/Dockerfile FROM postgres:10.7 RUN localedef -i ja_JP -c -f UTF-8 -A /usr/share/locale/locale.alias ja_JP.UTF-8 ENV LANG ja_JP.utf8 docker-compose.ymlの作成 docker-compose.ymlを作成します。 Docker composeとはDockerのビルドや複数のコンテナの起動を簡単なコマンドで行えるようしたものです。docker-compose.ymlにdockerイメージをビルドするために使用するDockerfileの情報や起動するコンテナの情報などを記述します。 $ touch docker-compose.yml 上記で作成したdocker-compose.ymlに以下の内容を記述していきます。 railsが動くコンテナの設定をします。ここではDockerfileのパス(build)や、実行するコマンド(command)、環境変数(environment)、永続化するディレクトリ(volumes)、ポート番号(ports)を設定します。depends_onは起動順を指定します。このコンテナはpostgresqlコンテナの後に起動します。コンテナの外から入出力できるようにするためにstdin_openとttyをtrueに設定します。 ちなみにvolumesで設定した永続化するディレクトリはローカル環境をマウントすることによって実現されています。ここでcashedというオプションを使用している部分がありますが、これはMacでdockerを動かし開発する際に、ボリュームをマウントする際に動作が非常に遅くなるという問題を解決するために使用しています。ここで注意しなければいけないのは、cashedを使用したボリュームはホストからの見え方は信頼できますが、コンテナからの見え方は遅延が発生します。 docker-compose.yml version: '3' services: rails: &app_base build: . container_name: hoge_rails command: ["rails", "s", "-p", "3000", "-b", "0.0.0.0"] environment: RAILS_ENV_NAME: development DATABASE_HOST: hoge_postgresql WEBPACKER_DEV_SERVER_HOST: webpack WEBPACKER_DEV_SERVER_PUBLIC: webpack:3035 depends_on: - postgresql ports: - "127.0.0.1:3000:3000" stdin_open: true tty: true volumes: - .:/hoge_app:cached - node_modules:/hoge_app/node_modules - bundle:/usr/local/bundle - vendor - tmp - log - .git webpackerが動くコンテナを設定します。Dockerfileはrailsコンテナと同じものを使用しています。 docker-compose.yml webpack: <<: *app_base container_name: hoge_webpack command: "bin/webpack-dev-server" environment: NODE_ENV: development WEBPACKER_DEV_SERVER_HOST: 0.0.0.0 ports: - '127.0.0.1:3035:3035' depends_on: - rails tty: false stdin_open: false postgresqlが動くコンテナを設定します。 docker-compose.yml postgresql: build: context: docker/db container_name: hoge_postgresql ports: - 5432:5432 volumes: - ./docker/db/volumes:/var/lib/postgresql/data:cached environment: POSTGRES_USER: root POSTGRES_PASSWORD: root hostname: postgres restart: always user: root ビルドしてコンテナを立ち上げる 作成したdocker-compose.ymlを使用してビルドを行います。 $ docker-compose build rails環境を構築 Gemfileを作成し以下を記述します。 $ touch Gemfile Gemfile source 'https://rubygems.org' gem 'rails', '~>6' rails newをします。途中、Gemfileを上書きするか聞かれるのでyと入力します。 $ docker-compose run rails rails new . --database=postgresql config/database.ymlを書き換えます。 config/datebase.yml default: &default adapter: postgresql charset: UTF8 encoding: UTF8 pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> username: <%= ENV.fetch('DATABASE_USERNAME', 'root') %> password: <%= ENV.fetch('DATABASE_PASSWORD', 'root') %> host: <%= ENV.fetch('DATABASE_HOST', 'hoge_postgresql') %> database: <%= ENV['DATABASE_NAME'] %> development: <<: *default database: hoge_app_development test: <<: *default database: hoge_app_test production: <<: *default database: hoge_app_production username: hoge_app password: <%= ENV['HOGE_APP_DATABASE_PASSWORD'] %> DBを作成します。 $ docker-compose run rails rails db:create コンテナを立ち上げます。 $ docker-compose up -d ブラウザでlocalhost:3000を開きます。 「Yay! You’re on Rails!」が表示されれば成功です。 参考にしたサイト https://qiita.com/minamijoyo/items/711704e85b45ff5d6405 http://www.tohoho-web.com/docker/dockerfile.html https://laptrinhx.com/rails6nodocker-compose-huan-jingwowebpackermade-hanmete-gou-zhusuru-2906065143/ https://www.pressmantech.com/tech/6522 https://hfuji.hatenablog.jp/entry/2019/06/01/102617
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Rails】rails routesの見方

rails routesの見方 現在のルーティングを確認する際にroutes.rbフォルダを見に行く方法もありますが、以下のコマンドでも確認できます。 $ rails routes 上記コードを入力すると下のような画面がターミナル上で表示されます。 Prefix:URLのニックネームです。(routes.rb内で「as:ニックネーム」で設定したものがここに表示されます) Verb:HTTPメソッドです。 URI:URL(例 /books) ※(.:format)というのは、/books.htmlとしてもいいよという意味です。htmlがフォーマットです。 Controller#Action:コントローラーとアクションを意味しています。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Rails+Reactで何か作る(パート1:Rails準備編)

はじめに rails と react で何か作ろうと思います。 やったことをメモ&共有します。 railsとreactは別プロジェクトとして作成します。 最終的に rails app は herokuへデプロイ react app は firebase hostingへデプロイ の予定です。 今回は、RailsAppを作成してテスト用のAPIを作成するところまでを行います。 環境 ツール バージョン ruby 3.0.2p107 sqlite3 3.36.0 node v17.3.0 yarn 1.22.17 rails 7.0.0 git 2.26.2 Railsの準備 Railsをnewする APIモードでrails アプリを作成する $ rails new quiz_rails --api とりあえず、git で first commit しておく $ cd quiz_rails $ git status On branch main No commits yet Untracked files: (use "git add <file>..." to include in what will be committed) .gitattributes .gitignore .ruby-version Gemfile Gemfile.lock README.md Rakefile app/ bin/ config.ru config/ db/ lib/ log/ public/ storage/ test/ tmp/ vendor/ $ git add . $ git commit -m "rails new quiz_rails --api" とりえあず、起動してみる $ rails server => Booting Puma => Rails 7.0.1 application starting in development => Run `bin/rails server --help` for more startup options Puma starting in single mode... * Puma version: 5.5.2 (ruby 3.0.2-p107) ("Zawgyi") * Min threads: 5 * Max threads: 5 * Environment: development * PID: 9149 * Listening on http://127.0.0.1:3000 * Listening on http://[::1]:3000 Use Ctrl-C to stop http://localhost:3000 をブラウザで表示 テストAPIを作成 モデルを作成 $ rails g model Chat content:string invoke active_record create db/migrate/20220115021134_create_chats.rb create app/models/chat.rb invoke test_unit create test/models/chat_test.rb create test/fixtures/chats.yml db/migrate/20220115021134_create_chats.rb class CreateChats < ActiveRecord::Migration[7.0] def change create_table :chats do |t| t.string :content t.timestamps end end end マイグレートしておく $ rails db:migrate == 20220115021134 CreateChats: migrating ====================================== -- create_table(:chats) -> 0.0028s == 20220115021134 CreateChats: migrated (0.0029s) ============================= テスト用のデータを作る db/seeds.rb Chat.create(content: "Hello, world!") Chat.create(content: "これはSeedで作ったメッセージです") $ rails db:seed コントローラーを作る $ rails g controller api/v1/chats create app/controllers/api/v1/chats_controller.rb invoke test_unit create test/controllers/api/v1/chats_controller_test.rb app/controllers/api/v1/chats_controller.rb class Api::V1::ChatsController < ApplicationController before_action :set_chat, only: %i[show destroy update] def index chats = Chat.all.order(:id) render json: chats end def show render json: @chat end def create chat = Chat.new(chats_params) if chat.save render json: chat else render json: chat.errors end end def update if @chat.update(chats_params) render json: @chat else render json: @chat.errors end end def destroy if @chat.destroy render json: @chat else render json: @chat.errors end end private def set_chat @chat = Chat.find(params[:id]) end def chats_params params.require(:chat).permit(:content) end end curl コマンドで確認 $ curl http://localhost:3000/api/v1/chats [{"id":1,"content":"Hello, world!","created_at":"2022-01-15T02:27:46.274Z","updated_at":"2022-01-15T02:27:46.274Z"},{"id":2,"content":"これはSeedで作ったメッセージです","created_at":"2022-01-15T02:27:46.279Z","updated_at":"2022-01-15T02:27:46.279Z"}] git にコミット $ git status On branch main Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git restore <file>..." to discard changes in working directory) modified: config/routes.rb modified: db/seeds.rb Untracked files: (use "git add <file>..." to include in what will be committed) app/controllers/api/ app/models/chat.rb db/migrate/ db/schema.rb test/controllers/api/ test/fixtures/chats.yml test/models/chat_test.rb no changes added to commit (use "git add" and/or "git commit -a") $ git add . $ git commit -m "add test api" おわりに。 久々にrails触りましたが、基本的なことは昔(3年前)くらいと変わってなさそうですね ControllerとModelを別々に rails g しましたが、 そういえば、一発で作るとか出来たような、そっちでやればよかったかなとも思っています。 今度やってみます。 おわり。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

present?メソッドとnil?メソッドの使い方

はじめに  今回はpresent?メソッドとnil?メソッドについてまとめます。どちらも条件分岐の時に便利なメソッドです。条件分岐どうしようと悩んだ時に、このメソッドで解決できたのでまとめます。 この記事は学習備忘録です。 present?メソッドとnil?メソッドの違い  present?メソッドとnil?メソッドは、オブジェクトに対してtrueとfalseを返すメソッドです。 使用例としては present?メソッド→@testsに値が入っている時trueが返される qiitq.rb @tests.present? #実行結果 => true nil?メソッド→@testsに値が入っていない時trueが返される qiitq.rb @tests.nil? #実行結果 => true このメソッドを利用して条件分岐を作る事ができます present?メソッドとnil?メソッドで条件分岐を作る  present?メソッドとnil?メソッドを使って、 以下のようにインスタンス変数に中身がある場合は商品を表示させて、中身がない場合は代わりの画像を表示させる実装があります。 qiita.rb <% if @tests.present?%> <% @tests.each do |test| %> <%= test.title %> <% end %> <% else %> 値なし <% end %> 上記はpresent?メソッドを使っているので、 実行すると@testsの中身がある場合は値が表示され、中身がない場合は「値なし」と表示されます。 (代わりに、nil?メソッドを使う方法でも条件分岐を作れます。) まとめ  今回はpresent?メソッドとnil?メソッドについてまとめました。どちらも簡単に条件分岐を行う事ができる便利なメソッドなので、使い方をマスターしたいと思います。 この記事が少しでも誰かのお役に立てれば幸いです。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Rails】RSpecの導入手順(メモ)

はじめに チーム開発でテストツールとしてRSpecを導入することになったので調べたことを記録したいと思います。 環境 Ruby 3.0.3 Rails 6.1.4 rspec-rails 5.0.2 spring-commands-rspec 1.0.4 1. 必要モジュールのインストール RSpecをRailsアプリで使用するためにはrspec-railsというgemが必要です。 また必須ではありませんが、RSpecのテストをより高速に実行するためにspring-commands-rspecもインストールしておきます。 インストールグループとしてtestだけでなくdevelopmentも追加することでテストファイルを作成するgeneratorを使用することができます。 Gemfile group :development, :test do gem 'rspec-rails' gem 'spring-commands-rspec' end bundle installでGemfileに記載したgemをインストールします $ bundle install 2. spring-commands-rspecの設定 以下を実行してbin/railsが使用できるように設定します $ bundle exec spring binstub rspec 3. RSpecの設定 3-1. 以下のコマンドを実行して必要ファイルを生成します。 $ rails g rspec:install # 以下のファイルが生成される create .rspec create spec create spec/spec_helper.rb create spec/rails_helper.rb 生成されたディレクトリ、ファイルの役割は以下の通りです。 .rspec 基本設定ファイル spec specディレクトリ配下にあるテストファイルがテストとして実行される spec/spec_helper.rb Rspecの全体的な設定を記述するファイル spec/rails_helper.rb Rails特有の設定を記述するファイル 3-2. .rspecの編集 .rspec --require spec_helper --format documentation # 追加 --require spec_helper デフォルトで記述されており、これから作成するspecファイルで毎回require '--spec_helper'と記述する必要がなくなる --format documentation 記述することで、テストコードの実行結果をターミナル上に可視化してくれる 他にもテスト結果を色付けしてくれる--colorなど様々なオプションが用意してある 3-3. 動作確認 今回は簡易的にPostというモデルのオブジェクトを生成したとき中身がnilにならないことをテストしたいと思います. spec/models/post_spec.rb require 'rails_helper' # 設定ファイルrails_helper.rbを読み込むコードが全テストにあります RSpec.describe Post, type: :model do it "Postモデルをnewしたとき, nilでないこと" do expect(Post.new).not_to eq(nil) end end テストを実行します $ bin/rails spec しっかりとテストできていることが確認できます。 その他 $ rails g [command] ~と$ rails g rspec:[command] ~の違い $ rails g [command] ~ RSpecをインストールした時点でrails g model Postを実行すると以下のようにマイグレーションファイルやモデルファイルに加えてRSpec用のテストファイルを生成してくれる デフォルトで生成されていたminitest用のテストファイルは生成されなくなる $ rails g model post invoke active_record create db/migrate/20220110190849_create_posts.rb create app/models/post.rb invoke rspec create spec/models/post_spec.rb # <- モデルのspecファイルが生成される $ rails g rspec:[command] ~ rails g rspec:model Postを実行するとマイグレーションファイルやモデルファイルは生成されず、RSpec用のテストファイルのみ生成される 開発の途中でRSpecを導入したりする際など、すでにモデルが存在する場合に使うとよい $ rails g rspec:model post create spec/models/post_spec.rb 参考
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【devise_token_auth】認証トークンの保存先について

はじめに  本記事は、プログラミング初学者が、学習を進めていて疑問に思った点について調べた結果を備忘録も兼ねてまとめたものです。  そのため、記事の内容に誤りが含まれている可能性があります。ご容赦ください。  間違いを見つけた方は、お手数ですが、ご指摘いただけますと幸いです。 今回の疑問点  今回の疑問点は、   認証トークンの保存先について    です。  devise-token-authを用い、認証機能を実装していた際に保存先について疑問を抱き、それぞれのメリット・デメリットについて調べました。 認証トークン保存先のメリット・デメリット local storage メリット 実装が簡単 デメリット XSS脆弱性があった場合、トークンを簡単に盗むことができる Cookie メリット HttpOnly属性をtrueにすることでJavaScriptからのCookie操作を無効にできる デメリット 実装が手間 HttpOnly属性をtrueにしても完全に安全というわけではない In-Memory メリット 攻撃が困難 デメリット 利便性が低い リロードするとログアウトされる タブ間でログイン状態が継続されない 認証プラットフォーム(Auth0) メリット 安全性が高い 利便性も損なわれない デメリット ユーザーが一定数を超えるとお金がかかる まとめ 認証トークンの保存先について検索するとCookieへの保存を紹介しているページが多いように感じましたが、どの方法にもメリット・デメリットがあるため、よく吟味して決定する必要があると感じました。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Railsチュートリアル(6版)の13章で_form.html.erbを使っていた場合の戸惑い解消

はじめに プログラミング初学者の@kat_logと申します。 Railsチュートリアル(Rails6版)の13章「13.3.2マイクロポストを作成する」の「リスト 13.43、13.44」で戸惑った部分について共有です。 戸惑ったポイント 10章の「10.1.1編集フォーム」の演習2をやった場合、new.html.erbとedit.html.erbの一部を_form.html.erbとしてパーシャルにするため、テキストと違いが出て、どの部分をf.objectにするか戸惑いました。 結論 new.html.erbとedit.html.erbは書き換え不要で、_form.html.erbを1箇所変えるとOKです。 _form.html.erb <%= form_with(model: @user, local: true) do |f| %> <%= render 'shared/error_messages', object: f.object %> <%= f.label :name %> <%= f.text_field :name, class: 'form-control' %> <%= f.label :email %> <%= f.email_field :email, class: 'form-control' %> <%= f.label :password %> <%= f.password_field :password, class: 'form-control' %> <%= f.label :password_confirmation %> <%= f.password_field :password_confirmation, class: 'form-control' %> <%= f.submit yield(:button_text), class: "btn btn-primary" %> <% end %> おわりに お読みいただきありがとうございました。 自分と同じくrailsチュートリアル学習中の方の参考になれば嬉しいです。 一緒にプログラミング学習頑張っていきましょう〜?
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Ruby 中級者になるために絶対に理解しておかなければならない知識

こんにちは!石田佳介です! 今回の記事では、RoR初心者が中級者になるために絶対に抑えておかなければならないことを記事にします。 それは、オブジェクト、インスタンス、インスタンス変数、クラス この4つを人に説明できるようになるくらい理解していないと絶対に更なる高みにはいけません。 それはなぜか?理由は、めちゃくちゃ大事な基礎であり、RoRの根幹になるものだからです。いくら多くのメソッドをおぼえても、上の4つを完璧に理解していなければ、実務に入ってもいつか頭打ちがきます。 こんな言っている僕ですが、ぼくも最近理解したので、心配しないでくださいね(笑) 今回使用する言語はrubyを使うので、ご了承ください それでは本題に入りましょう そもそもオブジェクトって? この言葉よく聞くとおもいますが、そんな難しいことを言っているわけではありません。よく「モノ」と表現されます。現実世界でイメージしてみるとよく分かると思いますが、世の中には、モノであるあふれてますよね。スマホ、パソコン、本、等々あげたらキリがありません。 それはわかったけど、プログラミングの話をしてくれよ!っていうツッコミが出てくるとおもうので、もう少しプログラミングチックな話にしていきましょう 実際にターミナルに打って確かめる rubyをインストールしている方は、コマンドで irb と入力すると、コンソールが開きます。 まずは、簡単なオブジェクトからいきましょう。その一つが文字列です。文字列とは簡単にいうと、人間が普通にしゃべっている言葉のことです。 コマンドで、山田太郎と入力すると "山田太郎" => "山田太郎" と出力されます。ここで、僕らと、コマンドの間でどういう会話が生まれたかというと、 僕ら:山田太郎というオブジェクトを作って、ここに置いておくね!ターミナル:山田太郎というオブジェクトを作って、ここに置いておくのね!おっけ! というような会話が生まれています。この会話によって、「山田太郎」というモノが作られたわけです。*(誤解を招かないようにいうと、ターミナルじゃないと、オブジェクトが作られないわけじゃないです。) 要は何を言いたいかというと、rubyはあらゆる文字や数字がモノ、つまりオブジェクトとして扱われるよ!ということなんです。このようにあらゆるものがオブジェクトとして扱われ、使われることをオブジェクト指向といいます。でも、皆さんのなかには、「石田よ、言ってることは分かった。でも、あらゆるものがオブジェクトになると何がいいの?」って思う人が多いとおもいます。ここで理解しなければいけないのが、インスタンス変数というものです。変数というものは、プログラミング勉強していたら分かるとおもいますが、インスタンスというものは中々理解されないところだとおもいます。そして、インスタンスというものを理解するためには、クラスというものを理解しなければいけません。 クラスとインスタンス まず、クラスとは設計書とよくいわれれます。現実世界でイメージしてみましょう。たとえば、家を作るための設計書があるとします この設計書をもとに、あらゆる家を作っていきます。たとえば、洋風な家、和風な家、お城みたいな家などなどできるわけです。このように洋風な家、和風な家、お城みたいな家それぞれをインスタンスと呼ぶわけです。洋風な家もインスタンス、和風な家もインスタンス、お城みたいな家もインスタンスになるんです。インスタンスを和訳すると、「実物」となるので和訳もぴったりですね。 では、プログラミングの話で考えてみましょう。Userというクラスがあるとします。そこでこんなようなコードを打ってみましょう User.create(name: “John”, email: “John@example.com”) (モデルにこのカラムがあると仮定しています)このようにすると、Userというクラス(設計書)から、 nameがJohnでemailがJohn@example.comという具体的なモノ、つまりインスタンスができるわけです 長くなりましたが、インスタンスとはこのようの具体的なモノなんですでは話は戻ってインスタンス変数とは何か。ここまでついてこれた方は何となくわかるとおもいます今まで見てきたような具体的なモノ、つまりインスタンスが格納されている変数、それがインスタンス変数なんです。そしてインスタンス変数はそのインスタンス固有の変数です オブジェクト指向とは? オブジェクト指向の話に戻ります。これまでの話を総括すれば、オブジェクト指向のメリットは分かるとおもいます。これまでの話で、クラス、インスタンス、そしてインスタンス変数を説明しました。そしてこれらって、どこでも使いまわせるんですね。クラスでいえば、継承(これも非常に重要な概念なので、また記事にします。)、インスタンスであれば、具体的なものを変数に渡すインスタンス変数。 オブジェクト指向の最大のメリットはこれですね。(ほかにもメリットはありますが。) 逆に使いまわしができないとどれくらいめんどくさいかっていうと、思い浮かべてほしいのが、ターミナルですね あれって、全く使いまわしができないじゃないですか。100回前にかいたあの長い記述を呼び出したい時に、それをまた書かなきゃいけない。マジだるいですね それを楽にしてくれるのがオブジェクト指向っていうものなんです。 なんとなくわかってくれましたかね?この記事を読んで、少しでもオブジェクト指向を分かってくれた人がいたらうれしいです!ありがとうございました!ここ間違っているよ!とかあったら、遠慮なくコメントしてくださいね!この記事では、プログラミングに関すること、技術系をメインに発信しています。Twitterフォローもお願いします!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む