- 投稿日:2020-11-20T23:36:29+09:00
AWS Railsの再起動手順
この度Railsで開発中のアプリをAWSへ開発中アプリをデプロイしましたが、
今後本番環境のサーバー再起動を行う頻度は高いだろうと思い
備忘録としてUnicornの再起動手順をまとめていきたいと思います。EC2インスタンスにログインしている前提で進めていきます。
まずは ps aux | grep unicorn コマンドでプロセスIDを確認します。
ターミナル[ec2-user@ip-172-31-33-238 <対象リポジトリ>]$ ps aux | grep unicorn ec2-user 26995 17.4 10.7 475732 108272 ? Sl 13:55 0:01 unicorn_rails master -c config/unicorn.rb -E production -D ec2-user 26999 0.0 10.0 476748 101508 ? Sl 13:55 0:00 unicorn_rails worker[0] -c config/unicorn.rb -E production -D ec2-user 27002 0.0 0.0 119436 908 pts/0 S+ 13:55 0:00 grep --color=auto unicornこの時 unicorn_rails master と表示されているプロセスが Unicorn のプロセスとなっているので、今回の場合は 26995 がPIDとなります。
PIDが確認できたら killコマンドを使ってプロセスを止めます。
ターミナル[ec2-user@ip-172-31-33-238 <対象リポジトリ>]$ kill 26995ps aux | grep unicornコマンドで実際に止まっているのか確認します。
ターミナル[ec2-user@ip-172-31-33-238 <対象リポジトリ>]$ ps aux | grep unicorn ec2-user 27345 0.0 0.0 119436 964 pts/0 S+ 14:27 0:00 grep --color=auto unicorn上記のような表示になっていればプロセスは止まっています。
確認が取れたら下記コマンドを入力しUnicornを起動させます。
ターミナル[ec2-user@ip-172-31-23-189 <対象リポジトリ>]$ RAILS_SERVE_STATIC_FILES=1 unicorn_rails -c config/unicorn.rb -E production -D以上で再起動は完了しました。
EC2インスタンスに紐付けたElasticIPを使ってブラウザにアクセスすると、正常に表示されているか確認ができます。
- 投稿日:2020-11-20T22:29:48+09:00
Rails新規アプリケーションの作り方
GitHubでリポジトリつくる
localにcloneしてくる
$ git clone https://github.com/k-tetsuhiro/rails_docker_sample_3.git & cd rails_docker_sample_3bundleを初期化する
$ bundle init Writing new Gemfile to /Users/kakuno/sandbox/rails_docker_sample_3/GemfileGemfileができているので編集する
$ vi GemfileGemfile# frozen_string_literal: true source "https://rubygems.org" git_source(:github) {|repo_name| "https://github.com/#{repo_name}" } gem "rails"→ # gem "rails" のコメントアウトをはずす
bundle installして必要なものをインストールする
$ bundle install --path vendor/bundle [DEPRECATED] The `--path` flag is deprecated because it relies on being remembered across bundler invocations, which bundler will no longer do in future versions. Instead please use `bundle config set path 'vendor/bundle'`, and stop using this flag Fetching gem metadata from https://rubygems.org/............. Fetching gem metadata from https://rubygems.org/. Resolving dependencies... --- 必要なgemがはいっていく... ---Railsアプリケーションを作成する
$ bundle exec rails new . -B -d mysql --skip-turbolinks --skip-test exist create README.md create Rakefile create .ruby-version create config.ru create .gitignore conflict Gemfile Overwrite /Users/kakuno/sandbox/rails_docker_sample_3/Gemfile? (enter "h" for help) [Ynaqdhm] --- ここで上書きしていいか聞かれるのでYを押して許可する ---→最後になにかエラーメッセージが出てたらもう一度bundle installする
$ bundle install --path vendor/bundlewebpackerをinstallする
$ rails webpacker:install create config/webpacker.yml Copying webpack core config create config/webpack create config/webpack/development.js --- 必要なものが入っていく ---Railsサーバーを起動してみる
$ bundle exec rails s→ようやくRails起動!!
http://localhost:3000/
でアクセスできる(ただしまだMySQLなどの設定をしてないのでエラー画面になるはず)gitで管理しないものを設定する
$ vi .gitignore→無視するファイルを設定
.gitignore# Created by https://www.toptal.com/developers/gitignore/api/rails # Edit at https://www.toptal.com/developers/gitignore?templates=rails ### Rails ### *.rbc capybara-*.html .rspec /db/*.sqlite3 /db/*.sqlite3-journal /db/*.sqlite3-[0-9]* /public/system /coverage/ /spec/tmp *.orig rerun.txt pickle-email-*.html # Ignore all logfiles and tempfiles. /log/* /tmp/* !/log/.keep !/tmp/.keep # TODO Comment out this rule if you are OK with secrets being uploaded to the repo config/initializers/secret_token.rb config/master.key # Only include if you have production secrets in this file, which is no longer a Rails default # config/secrets.yml # dotenv, dotenv-rails # TODO Comment out these rules if environment variables can be committed .env .env.* ## Environment normalization: /.bundle /vendor/bundle # these should all be checked in to normalize the environment: # Gemfile.lock, .ruby-version, .ruby-gemset # unless supporting rvm < 1.11.0 or doing something fancy, ignore this: .rvmrc # if using bower-rails ignore default bower_components path bower.json files /vendor/assets/bower_components *.bowerrc bower.json # Ignore pow environment settings .powenv # Ignore Byebug command history file. .byebug_history # Ignore node_modules node_modules/ # Ignore precompiled javascript packs /public/packs /public/packs-test /public/assets # Ignore yarn files /yarn-error.log yarn-debug.log* .yarn-integrity # Ignore uploaded files in development /storage/* !/storage/.keep # End of https://www.toptal.com/developers/gitignore/api/railsコミットとプッシュ
$ git add * $ git commit -m "first commit" $ git push→これでGitHubに更新される
番外編
rbenvを最新にする
https://qiita.com/_kanacan_/items/c1499f6c13b1c41da982
railsを最新にする
- 投稿日:2020-11-20T22:28:39+09:00
Railsを使ったToDoリストの作成(5.CRUDのCreate機能)
概要
本記事は、初学者がRailsを使ってToDoリストを作成する過程を記したものです。
私と同じく初学者の方で、Railsのアウトプット段階でつまづいている方に向けて基礎の基礎を押さえた解説をしております。
抜け漏れや説明不足など多々あるとは思いますが、読んでくださった方にとって少しでも役に立つ記事であれば幸いです。環境
Homebrew: 2.5.10
-> MacOSのパッケージ管理ツールruby: 2.6.5p114
-> RubyRails: 6.0.3.4
-> Railsnode: 14.3.0
-> Node.jsyarn: 1.22.10
-> JSのパッケージ管理ツールBundler: 2.1.4
-> gemのバージョン管理ツールiTerm$ brew -v => Homebrew 2.5.10 $ ruby -v => ruby 2.6.5p114 $ rails -v => Rails 6.0.3.4 $ npm version => node: '14.3.0' $ yarn -v => 1.22.10 $ Bundler -v => Bundler version 2.1.4第5章 CRUDのCreate(new/create)
第5章では、以下の機能を実装していきます。
- 新規登録画面(newアクション)
- 新規登録画面で入力された情報をデータベースに保存する機能(createアクション)
では、詳しく見ていきましょう。
1 newアクション
まずは、newアクションを使って新規登録画面を実装していきます。
1 コントローラ
まず、コントローラで新規登録された情報を保存するための空のインスタンスを作ります。ActiveRecordのnewメソッドを使っていきます。
app/controllers/boards_controller.rbdef new @board = Board.new end
(name: ' ', description: ' ')
のような空の箱がインスタンス変数に代入されているイメージです。2 ビュー
次に、投稿フォームを作成していきます。
new.html.haml.container %h2.form_title New Board = form_with(model: @board, local: 'true') do |f| %div = f.label :title, 'Name' %div = f.text_field :name, class: 'text' %div = f.label :description, 'Description' %div = f.text_area :description, class: 'text' %div = f.submit :Submit, class: 'btn-primary'フォーム作成のポイントは2つあります。
- form_withメソッドを使ってフォームを作成しています。form_withメソッドの引数は
model: [モデルクラスのインスタンス], local: 'true'
を指定します。local: 'true'
を指定しない場合はAjaxによる送信になります。- フォームヘルパーを使って、ラベル・1行入力欄、複数行入力欄を作成しています。フォームヘルパーは以下のように指定します。
=f.[メソッド名] :[column名], class: 'class名'フォームヘルパーの種類について知りたい場合は以下の記事が参考になります。
* フォームヘルパーの種類と例
* Action View フォームヘルパー3 一覧表示画面にリンクを貼る
最後に、一覧表示ページから新規登録ページに遷移できるようにリンクを貼っていきましょう。pathはrails infoの'boards#new'を参照してください。
app/views/boards/index.html.haml= link_to new_board_path do .add_card %p + Add new board以上で、新規登録画面の実装は完了です。
2 createアクション
では、次にcreateアクションを使って新規登録画面で入力された情報をデータベースに保存し、保存が成功したら詳細表示ページに遷移する機能を実装していきます。
1 コントローラ
コントローラで以下のように記述します。詳しい説明は後述します。
app/controllers/boards_controller.rbdef create @board = Board.new(board_params) if @board.save redirect_to board_path(@board), notice: 'Save successful' else flash.now[:error] = 'Could not save' render :new end end private def board_params params.require(:board).permit(:name, :description) endBoard.newでインスタンスを作成し、インスタンス変数に代入します。引数にはStrong Parameter(後述)を渡します。
ActiveRecordのsaveメソッドを実行し、作成したインスタンスをデータベースに保存します。Q. newアクションで新しいインスタンスを作成していたのに、なぜcretaeアクションで再度作成しなければいけないのか?
A. Webアプリケーションでは、ブラウザからのリクエストのたびに新しくプロジェクトが実行されるため、newアクション(GETリクエスト)で作成した変数は利用することができません。そのため、今回はパラメータを渡して再度インスタンスを作成することが必要となってきます。
'render'と'redirect to'
render
はアクションに続けてビューを表示させる場合に使用します。
redirect_to
はアクションを実行した直後にビューを表示せず、別のURLに遷移したい場合に使用します。
今回のケースではif文を使用して、インスタンスが保存された場合は詳細表示ページ(boards#show)に遷移するようにして、保存が失敗した場合は、現在の画面のビュー(boards#new)を表示するようにしています。
redirect_to
の引数に@boardを指定しているのは、idを渡すためです。id: @board.id
だと思ってください。Strong Parameter
Strong ParameterはRailsのセキュリティに関する概念の一つです。board_paramsメソッドに記載している内容が該当します。
[更新する対象のモデル名_params]
と命名する必要があります。
また、Strong ParameterはBoardsControllerクラスの外で使用することはないのでprivateメソッドを使用します。
表記 意味 params リクエストパラメータとして送られてきた情報が格納されているオブジェクト .require(:board) オブジェクトの中にboardというキーが入っている必要があります .permit(:name, :description) boardの中で、nameとdescriptionを保存する対象として許可します ちなみに今回のparamsの状況は以下のようになっています。
これを見ると、paramsはハッシュのようになっていてboardというキーとnameやdescriptionなどのデータが入ったバリューを持っていることがわかります。Flashメッセージ
Flashは、リダイレクトやレンダーする際に、次のリクエストに対してちょっとしたデータを伝えるために用意された仕組みです。
Flashにはハッシュでデータを格納することができます。
redirect_to
の場合は、第2引数にnotice: '[表示したいメッセージ]'
を指定し、renderの場合はflash.now[:error] = '[表示したいメッセージ]'
を指定することで設定することができます。
今回の場合は以下のようなハッシュが格納されています。flash = { notice: 'Save successful', error: 'Could not save' }ビューで以下のように設定することで画面に表示することができます。
- if flash.present? .flash - flash.each do |key, value| %div.key= valueこれは何をやっているかというと、まず、present?メソッドを使ってflashにデータが入っているかどうかを確認します。if文を使ってtrueの場合は3行目と4行目を実行します。
2 モデル
モデルではvalidationの設定を行います。
validationとは、データの内容が正しいかどうかをチェックする仕組みのことを指します。モデルのvalidationは、モデルに対応するオブジェクトをデータベースに登録・更新する前に検証を行い、エラーがあれば登録・更新処理をせずに差し戻しを行うという仕組みになっています。
今回のケースではsaveメソッドを実行しデータベースの登録を行う前に自動的に検証を行い、エラーがあればfalseが返ってきます。検証エラーの詳細はerrorsメソッドを使うことで確認することができます。app/models/board.rbclass Board < ApplicationRecord validates :name, presence: true validates :description, presence: true end今回は、Railsがデフォルトで用意してくれている検証用のヘルパーを利用し必須のデータが入っていなければエラーが出るようにしています。
記述方法は以下の通りです。validates :[column名], presence: true3 ビュー
ビューではvalidationの検証エラーのエラー文を取得して表示できるように設定していきたいと思います。
具体的には、まずerrorsメソッドを使って検証エラーの詳細が入ったオブジェクトを取得します。このオブジェクトにfull_messagesメソッドを使ってエラー文の全てを配列で取得します。さらにこれをeach文で表現することにより、各エラーがリストで表示されるようにします。app/views/new.html/haml%ul - @board.errors.full_messages.each do |message| %li= messageコンソールで確認すると以下のようになっています。
errorsメソッドで検証エラーの詳細がわかります。
また、full_messagesメソッドでエラー文の全てが配列で取得できていることがわかります。
これをeach文を使ってリスト化しているため、検証に引っかかった文章を表示することができます。以上で、新規登録機能の実装は完了です。
- 投稿日:2020-11-20T21:46:34+09:00
RailsのDocker化 〜その2〜
とりあえず、Railsアプリケーションを動かしてみる
まずは、どういうところに環境依存があるのか、また何がめんどくさかったのか思い出すために、
Railsアプリケーションをcloneしてlocal環境で動かすところまでやってみましょう。■sample project
https://github.com/k-tetsuhiro/rails_docker_sample
こちらは
ruby 2.7.2
とRails 6.0.3.4
で作成されたsampleアプリです。
これを好きなところにgit cloneしてみてください。
これをbundle exec rails s
で動かせるところまで持っていってみてください!
動かすまでに様々な問題点が出てくると思います。出てくる問題点
まずはlocalのRubyのバージョンに2.7.2が入っているでしょうか?
rbenvを使用してる場合rbenv versions
で確認できます。$ rbenv versions system 2.3.8 2.6.3 2.6.5 2.6.6 2.7.0 2.7.1 * 2.7.2 (set by /Users/kakuno/.rbenv/version)どうでしょうか?
2.7.2が入ってない場合、まずlocal環境にruby2.7.2のインストールが必要になります。さっそく環境依存が出てきてしまいました!!
この先も同じような環境依存が出てくる
起動するまでにlocalのこのような環境依存にこまるかと思います
・rubyのversion
・Railsのversion
・MySQLのversion
・yarnのversion
etc...その環境依存 dockerで解決しよう!
誰かが環境を整えたRailsアプリケーション
それをimageとして保存しちゃおう!!すべての環境(Ruby, Rails, MySQL, etc...)を込み込みでimageにしてしまえば、そもそも環境依存はおきないよね!
というイメージです!更に利点として、local環境がMacだろうがWindowsだろうが、実際にRubyやRailsが入っているのはdockerのimageなので、どのマシンでも関係なく動きます!
dockerで動かしてみる
dockerで動かすことにすごいメリットを感じますね!
では次回はどうしたら今のRailsアプリケーションをdockerで動かすことができるのか?
ここを説明していきます。
- 投稿日:2020-11-20T21:07:42+09:00
form_withについての周辺知識
はじめに
脱初心者にむけてアウトプットをしていこうと思って記事を書いております。
間違ったことがありましたら、ぜひコメントいただけると幸いです。form_withとは何か
form_withとはブラウザにデータのリソースの入力や
編集を行うフォームを生成するために使用される。
(Railsで何かしらに情報を送信したい時に使うメソッド)という理解で大丈夫だと思います。<%= form_with(モデル or URLベース,[スコープ],[オプション]) do |f| %> フォームの内容 <% end %>form_forとform_tagについて
これらのヘルパーメソッドはRails5.1で導入されたform_withが導入されたことによって非推奨となりました。
(form_withはこれらの機能をまとめたもの)という理解で大丈夫です。
form_withを理解するためにはこれらのヘルパーメソッドを理解するにはこれらを知ることでさらに理解を深めることができます。form_for
<%= form_for(モデル,[オプション]) do |f| %> フォームの内容 <% end %>form_forは入力されたデータをモデルなどに保存する時に使われていた
form_tag
<%= form_tag(URL,[オプション]) do |f| %> フォームの内容 <% end %>form_tagは入力されたデータを保存する必要がない時に使用されていた
form_withはこれらの機能を併せ持ったヘルパーメソッドだと覚えておきましょう。
form_withには様々なオプションがあり、今まで、分けられていた機能がまとまったメソッドなので、少しわかりづらいこともありますが、なれるととても便利な機能(らしい)なので、どんどん使って慣れていこうと思います。
- 投稿日:2020-11-20T18:05:33+09:00
syntax error, unexpected end-of-input, expecting end について
はじめに
初学者のアウトプットです。
訂正、追記等あればご教示いただけると幸いです。エラー文章
エラー文章が発生しては、長くて読む気が無くなりそうですが、
大抵の内容は、エラーが発生しているアドレスを示してくれており、
SyntaxError: /アドレス/.../: エラー内容
みたいな感じになっています。
結局、アドレスのエラー内容を修正すればエラーは解決するので、
現段階では、学習の為にもエラー内容部分を翻訳してエラー修正にするのが一番だなと感じています。syntax error, unexpected end-of-input, expecting end
表題のようなエラーが出ました。
翻訳 → 構文が誤っています、予期していない終わり方です、endを追加すると良いと思われます。
見直してみると構文に
end
が足りていませんでした。
end
を追加してエラー解消です。まとめ
複雑になればなるほど発生しそうなエラーです。
こんなのは体で覚えてしまってすぐ対処出来るようになりたいです。
- 投稿日:2020-11-20T18:03:25+09:00
【Rails5】check_boxで任意の文字列を渡す方法(ガチ初学者向け)
初投稿です。
初学者のため、参考程度に見ていただければ幸いです。至らない点、わかりにくい点などあればコメントで教えていただければ幸いです。
version
Ruby 2.5.7
Rails 5.2.4.4How to
まずチェックボックスフォーム機能を実装する際に、デファルトだとか機能ようなコードになると思います。(form_withを使う場合)
<%= form_with model: 変数, url:遷移先のパス do |f| %> <%= f.check_box :カラム名,{オプション(クラス名など} %> ←チェックボックスを表示 <%= f.submit %> <% end %>このようにするとデフォルトで
"1"か"0"
が送られます。<%= form_with model: 変数, url:遷移先のパス do |f| %> <%= f.check_box :カラム名, {オプション(クラス名など}, "true","fales" %> ←チェックボックスを表示 <%= f.submit %> <% end %>このように記述すれば
true,fales
を渡すことができます。<%= form_with model: 変数, url:遷移先のパス do |f| %> <%= f.check_box :カラム名, {オプション(クラス名など}, "attende","absence" %> ←チェックボックスを表示 <%= f.submit %> <% end %>同様に
true,fales
の部分を書き換えれば、任意の値を渡すことができます。ポイントは、オプションの後ろに記述することです。
渡したい文字列の後ろにクラス名などのオプションを指定するとエラーが出ます。簡単なようで意外と車学者がつまずくポイントかなと思い記事にさせていただきました。
誰かの参考になれば・・・
- 投稿日:2020-11-20T17:14:57+09:00
[Rails]selfについての理解を深めたい[初心者]
はじめに
プログラミングの超初心者です。
self
への理解が全然できていないと感じたので、アウトプットも兼ねて、学んだことをまとめます!
それではいきましょう!!selfって何のこと?
オブジェクトそのものを指す特殊な変数
です。と、説明だけでは非常に分かりにくいですよね。
一緒に、どのように使用されているのか、確認していきましょう。使用例
book.rbclass Book < ActiveRecord::Base def hoge #インスタントメソッド end def self.hoge #クラスメソッド end def author #インスタントメソッド self.hoge #インスタンスメソッドのhogeが呼ばれる hoge #インスタンスメソッドのhogeが呼ばれる self.class.hoge end def self.author #クラスメソッド self.hoge #クラスメソッドのhogeが呼ばれる hoge #クラスメソッドのhogeが呼ばれる end endクラスメソッド(特異メソッド)とは?
さて、
クラスメソッド
とは一体、何を指しているのでしょうか?
ざっくりの認識では、クラス全体の中から何かを取り出す
際に使用するものです。
一つ一つのインスタンスには紐づいておらず、クラスに対して働きかけるメソッド、とも言い換えられるでしょう。
後述する特異クラス
と分ける形で、特異メソッド
と呼ばれます。メソッドの呼び出しには、必ずレシーバが必要になります。
クラスメソッドには、あらかじめレシーバとしてself(自分自身のオブジェクト)が指定されているので、クラスから直接呼び出せる仕掛けになっています。インスタントメソッドとは?
では、
インスタントメソッド
とは何ぞや、となるでしょう。
簡単に説明すると、特定のインスタンスから、何かを取り出す
際に使用されるもの、という認識でOKです。
逆に言うと、メソッド名にself
を付けないと、指定したオブジェクト(レシーバ)に対してしか、そのメソッドを使用することが出来ないということです。特異クラスとは?
クラスメソッドの中で、別名
特異メソッド
と紹介していたのを覚えていますか。
実際は、クラスメソッドで毎回self
と記載すれば大丈夫なのですが、クラスメソッドが複数に渡る場合は、いちいちself
と打っていくのが面倒ですよね。
そこで使えるのが、特異クラス
です。
使い方は、以下の通りです。book.rbclass Book < ActiveRecord::Base class << Book def say_thanx puts "#{self}, thanx" end end end↑に、
book = 'book'
という条件を与えた上で、book.say_thanx
を打ち込むと、book, thanx
と出力されます。
全体の流れは、クラスメソッドと似通っていますが、<< Book
により、bookオブジェクトの特異クラスを呼び出しているため、あくまでもオブジェクトに対しての特異メソッド、という定義です。おわりに
自分でこの記事を書いていて、
なんて初心者にはとっつきにくい概念なんだろう
と思っています。
記事の中では、あくまで概念にしか触れていませんので、実際にアプリ制作で使用する際は、もっと実地に即した形での運用になると思います。
「なぜこの記載をしているのか」を大切にして、ただの丸暗記に終始することの無いよう、自戒を込めて執筆しました。
- 投稿日:2020-11-20T16:55:58+09:00
enumを使用して投稿の公開設定をする(二択式)
はじめに
やりたいこと
- 投稿機能に公開ステータスを持たせる
- デフォルトは非公開にする
- 公開設定をセレクトボタンで選択させる
やってみて
enum自体は非常に奥が深いモジュールだと感じましたが、私がやりたいことは簡単に実装できました。
ですので、この投稿は初心者でもすぐに実践できる内容になっていると思います。参考
Rails公式リファレンス
Pikawaka <【Rails】enumチュートリアル手順
DB設計
db/migrate/create_item.rbclass CreateItems < ActiveRecord::Migration[6.0] def change create_table :items do |t| t.string :title, null: false t.string :tagbody t.string :url t.text :body, null: false # statusカラム、integer型、deroult: 0 を指定 t.integer :status, null: false, default: 0 t.integer :category_id, null: false t.references :user, foreign_key: true t.timestamps end end endboolean型で作成することもできますが、2個以上の定数と紐付けたい場合はinteger型を選択。
Model
models/item.rbenum status: { closed: 0, open: 1 }デフォルトを非公開にするので「closed」という定数を「0」に設定しました。
Controller
通常通りストロングパラメーターとcreateアクションを定義します。
controllers/items_controller.rbclass ItemsController < ApplicationController def create @item = Item.new(item_params) if @item.save redirect_to root_path else render :new end end private def item_params params.require(:item).permit(:title, :tagbody, :body, :url, :status, :category_id).merge(user_id: current_user.id) end endView
formの書き方
views/items/new.html.erb<%= form_with model:@item, url: '/items', local: true do |f| %> <%= f.select :status, Item.statuses.keys.to_a, {}, { class:'item-open' } %> <% end %>解説
f.selectの使い方
<%= f.select 属性, 選択肢の集合, {オプション}, {HTMLオプション} %>Item.statuses.keys.to_a について
enumで指定した定数はハッシュの形で配列になっています。
したがってstatuses(複数形).keys.to_a(配列を返すメソッド)の形で呼び出します。実装例
投稿画面
DB
数字で保存される
呼び出し方
公開記事だけをインスタンス変数に含める
controllers/item_controller.rbclass ItemsController < ApplicationController def index @items = Item.open.order('created_at DESC') end endおわりに
今回はenumを使用して二択のセレクトボックスからDBに保存する形を実践しました。
今後はより多くの選択肢を与えたり、enumを使用して検索・確認・更新などの機能を実装してみたいなと思います。✔︎
- 投稿日:2020-11-20T14:43:12+09:00
【Rails】ジャンル&商品名の検索機能実装
前提
ジャンルの一覧表示の中で検索したいジャンルをクリック or 検索フォームに商品名を打ち込んで「検索」ボタンをクリックすることで、searchアクションを実行します。ジャンルor商品名の検索結果を遷移後のsearch.html.erbで表示するような機能を実装していきます。検索結果画面には、該当する商品のレコード内容(商品写真や商品名など)をeach文で表示する形になります。モデル同士のアソシエーションなどの部分は省いていきます。
通常の検索機能の実装がしたい方はこちらを参考にしてください(gemなし複数モデル対象の検索機能)実装の条件、太文字は必須のカラムです(カラム名は違くても問題ありません、デフォルトでつくidカラムは一応記述しました)
・genresテーブル(PK:id、ジャンル名:name、ジャンル有効or無効:is_active(boolean))
・itemsテーブル(PK:id、ジャンルのid(FK):genre_id、商品名:name、その他、商品写真や商品説明など)実装環境
ruby '2.6.3'
gem 'rails', '~> 5.2.4', '>= 5.2.4.3'
gem 'bootstrap-sass', '~> 3.3.6' (無くても可)
gem 'devise'(無くても可)
・bootstrapはtableタグや、class指定でレイアウトを整えています。
・deviseはヘルパーメソッドを時々使用していますが、記述しなくても検索機能への影響はありません。実装後のイメージ
商品の一覧画面でジャンル検索枠内のジャンル名をクリックすると、写真の検索結果一覧画面に結果が表示されます。
商品の一覧画面で検索フォームに商品名(例:ケーキ)、検索方法を指定後「検索」を押すと写真の検索結果一覧画面に結果が表示されます。
検索結画面の写真にジャンル名を載せてないのでわかりずらいですが、「ケーキ」ジャンル(genre_id:1)で検索をした結果、itemsテーブルのgenre_idカラムが1の商品だけ表示されている状態です。
※筆者は検索結果画面(写真)にも検索フォームとジャンル検索のサイドバーを表示させています。実装していきます!
1⃣コントローラー新規作成
$ rails g controller Search search
2⃣Viewに検索フォーム & searchアクションへのlink_toを記述
・@genresはviewページのコントローラーで
@genres = Genre.all
で定義してください。
・検索に必要な情報であるvalue(検索ワード)とhow(検索方法)をコントローラーへ送信できるようにそれぞれ定義しています。
・form_with内では、フォームに打ち込まれた文字列をvalue、プルダウンメニューで選択された「検索方法」をhowとして送信できるように定義しています。
・ジャンル検索では、genre.nameをリンクにしてsearchアクションを実行するようにしてます。search_pathの第一、第二引数にvalueとhowを定義してコントローラーで必要な情報を受け取れるようにしています。valueにgenre.idを指定してる理由ですが、itemsテーブル内にgenre_idカラムが存在するからです。genre_idカラムが一致する商品だけ探し出す処理をコントローラーで定義します。items/index.html.erb<div class="name-search"> <% if customer_signed_in? %> #deviseのヘルパーメソッドです、省いても問題ありません。 <h5>商品名検索</h5> <%= form_with url: search_path, method: :get, local: true do |f| %> <%= f.text_field 'search[value]', size: "26x4" %><br> <span class="search-button col-xs-12 text-right"> <%= f.select 'search[how]', options_for_select({ "部分一致" => "partical", "前方一致" => "forward", "後方一致" => "backward", "完全一致" => "match" }) %> <%= f.submit :"検索" %> </span> <% end %> <% end %> </div> <table class="table table-bordered genre-table"> <thead> <tr> <th>ジャンル検索</th> </tr> </thead> <tbody> <% @genres.each do |genre| %> <tr> <td> <%= link_to genre.name, search_path('search[value]': genre.id, 'search[how]': "match") %> </td> </tr> <% end %> </tbody> </table>3⃣コントローラー作成
筆者は商品名検索機能を実装してからジャンル検索をどのように実装しようか悩み、初めはsearchアクションとは別のアクションとViewページを作成する必要があるかなぁ、、と悩みましたがitemsテーブルにgenre_idを持たせていることと、itemのnameは文字列(string)なのに対してgenre_idは整数型(integer)なので下記にある.orのwhereで取得できるのではないかと考えました。(商品名が1とかだとどうなってしまうのかは試してませんが、、)
search_controller.erbclass Customer::SearchController < ApplicationController def search @value = params["search"]["value"] #データを代入 @how = params["search"]["how"] #データを代入 @datas = search_for(@how, @value) #def search_forを実行(引数に検索ワードと検索方法) end private def match(value) #.orを使用することで、valueに一致するカラムのデータをnameカラムとgenre_idカラムから探してきます。 Item.where(name: value).or(Item.where(genre_id: value)) end def forward(value) #forward以降は商品名検索の定義しかしてません。 Item.where("name LIKE ?", "#{value}%") end def backward(value) Item.where("name LIKE ?", "%#{value}") end def partical(value) Item.where("name LIKE ?", "%#{value}%") end def search_for(how, value) case how #引数のhowと一致する処理に進むように定義しています。 when 'match' #ジャンル検索の場合はmatchで固定してるので、必ず'match'の処理に進みます。 match(value) when 'forward' forward(value) when 'backward' backward(value) when 'partical' partical(value) end end end検索結果表示(search.html.erb)
後は検索結果を表示するだけです。@datasをeachで該当商品の数だけ繰り返し処理します。[ブロック変数data.カラム名]でitemsテーブルの情報を表示しています。
search.html.erb<% if @datas.empty? %> <h2>該当する商品はありません</h2> <% end %> <% @datas.each do |data| %> <div> <%= link_to item_path(data.id) do %> #写真を商品詳細へのリンクにしていますが、必要なければ省略してください。 <%= attachment_image_tag data, :image, size: "190x150", class: "img_hover" %><br> <% end %> <p><%= data.name %></p><br> <p>¥<%= data.price_without_tax %></p> </div> <% end %>以上で実装できたかと思います。ジャンル検索、商品名検索セットでの記述なので参考にならなかった方はすいません。
おまけ
筆者はwhere分の.orを思いつく前までは、
def match(value)
の部分でif文を使ってvalue == integerならgenre_idを探しに行かせようと定義してみたりしましたが結果的に色々失敗して(他に何種類か試しましたが)、上記の処理に行きつきました。なにかもっと効率的な処理があればコメントお願いします。
- 投稿日:2020-11-20T14:37:23+09:00
【Ruby】バイナリーサーチを用いた配列内の要素検索
配列内に任意の値が存在するかを確認するプログラムを作成します。
任意の値が配列内に存在しない場合は、「値は配列内に存在しません」と表示し、存在する場合は、配列の何番目にあるかを表示します。今回のプログラムではバイナリーサーチという、配列を2分割した検索方法を用います。
例えば以下のような配列がある場合、中央値である「3」から左右と比較して検索する手法です。
これにより検索したい値が「1」であった場合、「4,5」は比較を行わないため処理速度の向上につながります。rubyarray = [1, 2, 3, 4, 5]回答例
rubydef binary_search(array, number_of_elements, target) left = 0 //配列の先頭の番号 right = number_of_elements - 1 //配列の末尾の番号 while left <= right //配列番号が逆転するまで繰り返し center = (left + right) / 2 //中央値の配列番号の決定 if array[center] == target //配列の中央値が検索したい値であった場合 return center elsif array[center] < target //配列の中央値<検索した値であった場合 left = center + 1 //arrayの「1,3,5,6,9」を対象外とする設定 else right = center - 1 //それ以外の場合、arrayの「9,10,13,20,26,31」を対象外とする設定 end end return -1 //何も当てはまらなかった(配列に存在しなかった場合の返り値) end array=[1,3,5,6,9,10,13,20,26,31] puts "検索したい数字を入力してください" target = gets.to_i number_of_elements = array.length result = binary_search(array, number_of_elements, target) if result == -1 puts "#{target}は配列内に存在しません" else puts "#{target}は配列の#{result}番目に存在します " end解説
まずはメソッド外。
1. 配列「array」の準備
2. 任意の文字「target」の準備
3. 配列の要素数「number_of_elements」の準備
これら3つの変数を実引数に設定し「binary_serach」メソッドを実行しています。続いてメソッド内。
1. 配列の先頭及び末尾の配列番号
を「left」「right」に代入。
2. while文にて、この「left」「right」の値が逆転するまで繰り返しを行う設定。
3. 以下の記述で中央値の配列番号を取得しています。今回の配列の要素は偶数個であるため、「(0+9) / 2 = 4.5」となります。配列番号4.5は存在しませんが、rubyにおける計算式の小数点は切り捨てられるため、今回の配列における中央値は「array[4] = 9
」となります。ruby「center = (left + right) / 2」if文による条件分岐を行い、左右のどちらに値が存在するかを繰り返し判定します。
最終的に配列内に任意の値が存在しなかった場合は「return -1」という返り値を渡してメソッドを終了します。最後に再びメソッド外。
1. 任意の値が存在しなかった場合は「-1」が戻ってくるので、存在しない旨のメッセージを出力。
2. 任意の値が存在した場合は正しい値が戻ってくるので、存在する箇所を出力。バイナリーサーチ知らないと思いつかない方法だと思いますので、しっかり覚えておきたいです。
ご意見等ございましたらコメントをいただけますと幸いです。
- 投稿日:2020-11-20T09:26:23+09:00
自走力に必要なもの?
私の結論は楽しみながら学習することです。
なぜなら、嫌々でプログラミングをしても挫折してしまうからです。スクール2週間目に突入して…
スクールのカリキュラムを2週間終え感じたことは、「事前に勉強していて良かった...」
スクールでの受講を悩んでいる方や、これから受講するって方は”未経験からエンジニアへ”という謳い文句を勘違いして知識ゼロで臨むとなかなか苦労すると思いました。実際に自分の所属している6人のグループではProgateで事前学習していたのは自分だけでした。私の場合は、ブラインドタッチがあまり出来ず、苦労したのでタイピング練習をもっとすべきだったなと反省をしています。また、カリキュラムの進行はスピーディで、合間にある中間試験など理解度を高めながら、スピード感を持ってカリキュラムを進めるのに、不安と焦りを感じながら学習を続けています。
転職活動の心構え
一度でも内容に触れたことがあれば記憶の定着もしやすいですし、理解度も増します。そして、気持ちにも余裕が生まれます。
この点は、転職活動においても言えます。内定をもらって終わり!ではなく、やっとスタート地点に立てただけなので、入社前にどれだけ内定先で必要となるプログラミング言語、SQLや基本情報試験を事前学習できるかで職場での貢献度を大きく左右すると言えます。
スクール受講前(2ヶ月間)
・エンジニア界隈のリサーチ
(親戚の自社開発企業を訪問)
・キタミ式基本情報技術者
・Progate2周(HTML,CSS,Ruby,Rails)
・Youtube(自社開発、受託開発、SESの違い)8月からProgateで独学し、スクールの無料カウンセリングを受けて受講する覚悟が決まったのが9月上旬。スクール受講開始が10月上旬。その間に23年間お世話になったWindowsからスタバで作業しているとかっこいいと言われるMacへシフト
https://twitter.com/by_miwa30/status/1301541645859434496エンジニア界隈のリサーチ
私は、高校生の時に情報ビジネス科でJavaとC言語を学んでいたこともあり、進路先にエンジニアを考えていました。ただ、求人が1件しかないこと、エンジニアとして働くイメージが湧かず断念。その当時、進路相談でお世話になったのが親戚の自社開発企業です。そして、今回2度目のエンジニア現場で1時間半、話を伺いました。「基本情報技術者資格を取得するつもりがなくても、学習しておいたほうが良い!クラウドインフラではAWSが主流だよ。」などネットだけでは知り得ない現場の声を伺えました。とても貴重なご意見ありがとうございました。
キタミ式基本情報技術者
上記にある通り、現役のエンジニアのご意見から基本情報技術者を早速購入。人から言われたことは、すぐに一度調べて必要なら実践してみる考えがモットーな私。このスピード感と素直さを強みとして有益な情報かどうかを取捨選択できる収集心と分析力を磨き上げ自走力を最大化させていければと思います。本の内容は、試験対策のためだけの資格本ではない!と思いました。なぜなら、イラストやマンガを取り入れながら暗記ではなく、楽しく理解することを大切にしている印象を持ったからです。プログラミングも暗記するつもりで学習しては行けないと言われます。いくら知識があっても、その知識を応用できる柔軟性が必要で知識を繰り返し学習することで記憶に定着されます。その為には、学習したことをアウトプットすること、復習することが欠かせません。この考えを改めて痛感させられただけでも、購入した甲斐があって良かったです。
Progate
カリキュラムが分かりやすいこと、書いたコードの動きも確認できる。環境構築が不要で自分が書いたコードを体感でき楽しくゲーム感覚で進めることが出来ました。高校の時のような講義形式で学ぶよりも、自分のペースで進められ、わからない点すぐにカリキュラムを見返すことが出来るのが嬉しかったです。
https://twitter.com/by_miwa30/status/1291192741280399360Youtube
Web系エンジニアとは何か?IT業界とは?等に特化して学びました。現役の方や元々やっていた方の話を視聴して、自分のこれから進んで行く道をじっくり考える時間となりました。自社開発、受託開発、SESそれぞれのメリットデメリットを学べたので今後の転職活動にとても参考になりました。振り返り・感想
今思うと、Progateのコードの中身はめちゃくちゃだと思います。DRYの原則を意識すれば、もっとスッキリさせられるはず。でも、何事も初めから完璧にできる人はいません。
冒頭で「事前に勉強していて良かった‥.」と言いましたが、1日10時間、10週間を終えた時に後悔することがないようにしたいです。その為には、愚直に毎日インプットしてはアウトプットを繰り返すこれに尽きると思います。この考えを持つきっかけをくれたプログラミング。本当に出会えて良かったなと思いました。
- 投稿日:2020-11-20T01:59:06+09:00
個人アプリ開発日記 #3
まずはuserリソースから
ユーザー登録機能
ログイン機能
ユーザー詳細表示機能
ユーザー編集機能
ユーザー削除機能を実装していきます!
users_controller の実装
class UsersController < ApplicationController include SessionsHelper before_action :set_user, only: [:show,:edit,:update,:correct_user] before_action :logged_in_user, only: [:index,:edit,:update] before_action :correct_user, only: [:edit, :update] def index @users = User.all end def new @user = User.new end def create @user = User.new(user_params) if @user.save log_in(@user) redirect_to @user else render 'new' end end def show end def edit end def update if @user.update(user_params) redirect_to @user else render end end def destroy user = User.find(params[:id]) user.destroy end private def user_params params.require(:user).permit(:nickname,:email,:password,:password_confirmation) end def set_user @user = User.find(params[:id]) end def logged_in_user unless logged_in? store_location # ユーザーがいきたがってたページを記憶 flash[:danger] = "Please log in" redirect_to login_url end end def correct_user redirect_to(root_url) unless current_user?(@user) end end長いので、注目ポイントは フレンドリーフォワーディングを実装したlogged_in_userメソッドと、correct_userメソッドです
store_locationメソッドと、current_user?(@User
は sessions_helperメソッドに定義されてるので見ていきましょうsessions_helper
module SessionsHelper # 渡されたユーザーでログインする def log_in(user) session[:user_id] = user.id # このコードを実行すると、ユーザーのブラウザ内 # の一時cokkiesに暗号化済みのユーザーidが自動で # 作成されます # この後のページでsession[:user_id]を使って # 元通りにIDを取り出すことができる end def log_out session.delete(:user_id) @current_user = nil end # ユーザーのセッションを永続的にする def remember(user) user.remember # rememberメソッド呼び出し # つまりハッシュ化したトークンをDBに保存 cookies.permanent.signed[:user_id] = user.id # 永続的に保存できるクッキーの保存期限示すため # permanentを書く(本当は20年) # 生のuser_idができるとだめなので # signedで暗号化 cookies.permanent[:remember_token] = user.remember_token # 期限はOK # ランダムな文字列のトークンをクッキーに保存 end # 永続セッションを破棄する def forget(user) user.forget #DBのremember_digestからデータ破棄 cookies.delete(:user_id) cookies.delete(:remember_token) # クッキーからもユーザーの情報削除 end # 現在ログインしているユーザーの情報を取得 def current_user # DBの問い合わせの数を可能な限り小さくしたい # logged_in?メソッドでも使われてるし、、、 if user_id = session[:user_id] # セッションがある場合 # すなわちログインしてる時のみ # sessionにアクセスした結果を変数に # 入れておいてあとで使いまわした方が # 早くなる @current_user ||= User.find_by(id: user_id) # find_byでデータベースにクエリを投げる # ブラウザのセッションにあるuser_idをもとにUser定義 # find_byの実行結果をインスタンス変数に保存する # ことで、1リクエスト内におけるデータベースへの # 問い合わせは最初の一回だけになり、 # 以後の呼び出しではインスタンス変数の結果を # 再利用する # すでに@current_userが存在する場合って何? # 一回current_userを実行したら、 # @current_userがあるのでそれを使ってね # sessionのuser_idがあるということは # 既にログインしてるといてDBにユーザーの情報があるはず。 # だからsessionのuser_idをDBでfind_byかければいい elsif (user_id = cookies.signed[:user_id]) # sessionが張られてなかったらcookiesにあるかも user = User.find_by(id: user_id) if user && user.authenticated?(cookies[:remember_token]) # nilガード # クッキーのuser_idとremember_tokenが一致してる log_in user @current_user = user end end end def current_user?(user) user && user == current_user # nilガード end # ユーザーがログインしていればtrueを返す、 # その他ならfalse def logged_in? !current_user.nil? # nilじゃなかったら # すなわちログインしてたらfalseが # 返ってくるけど、それだとif文とか # 使う時にややこしいので、! # で返り値の真偽値を逆にして # trueを返すようにしてる end # 現在のユーザーをログアウトする def log_out forget(current_user) # カレントユーザーのremember_digestを破棄 # トークン、user_idを破棄 session.delete(:user_id) # セッションも破棄 @current_user = nil # インスタンス変数の値を更新 end # フレンドリーフォワーディングの処理 # 記憶したURL(もしくはデフォルト値にリダイレクト) def redirect_back_or(default) # これはいい命名!! redirect_to(session[:forwarding_url] || default) # store_locationでsession[:forwarding_url]を定義 session.delete(:forwarding_url) # redirectできたらforwarding_urlって情報はいらないので # 破棄しましょう # セッション情報を保持したままにしておくと、次のログインの # 時もこれを読み込んでおかしくなる end # アクセスしようとしたURLを覚えとく def store_location session[:forwarding_url] = request.original_url if request.get? # request.original_url はリクエストされたurl # それをセッションに保存 # if request.getでなぜGETリクエストだけ対応してるかと # いうと、before_actionのlogged_in_userで # updateに制限かかってるけど,PATCH users/:idを # 保存する意味はない # なぜならユーザーが元々いきたいのはeditとかだから end end僕の下手くそなコメントだけじゃ意味わからないと思うので、rails tutorialやってみてください、、、笑
本当に色々勉強になりました、、、sessions_controller
class SessionsController < ApplicationController include SessionsHelper def new end def create user = User.find_by(email: params[:session][:email].downcase) # 受け取ったemailからfind_byでデータベースに # 問い合わせてユーザー取得 if user && user.authenticate(params[:session][:password]) # まずそのユーザーがいるかnilガード # いたらpasswordとauthenticateかける log_in user params[:session][:remember_me] == '1' ? remember(user) : forget(user) # check boxがonの時は1になるので1の時は # ? 以降がtrueの処理 # : 以降がfalseの処理 redirect_back_or user # redirect_back_or メソッド呼び出し # 引数にuser_url(user)を渡す else flash.now[:danger] = 'invalid email/password combination' render 'new' end end def destroy log_out if logged_in? # 二つのブラウザで同時ログアウトとかされたらバグが起こるので # ログイン redirect_to root_url end end注目ポイントはnilガードです
nilガードとは、例えば
user = User.find_by(email: params[:session][:email].downcase)
とかでユーザーを取得できない場合にif user && user.authenticate(params[:session][:password])
まずuserで本当にuserがいたのか確かめます
コンピューターは Aor B と条件式があったら左(A)から実行するので、
その特性を生かしたプログラミングです。面白いですね。user.rb
class User < ApplicationRecord attr_accessor :remember_token # remember_tokenというメソッドを作成 # password,password_comfirmationみたいな # 変数のように扱える # u.remember_token的なことができる has_many :drinks before_save { self.email = email.downcase } has_secure_password validates :nickname, presence: true, length: { maximum: 50 } VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i validates :email, presence: true, length: { maximum: 255 }, format: { with: VALID_EMAIL_REGEX }, uniqueness: { case_sensitive: false } validates :password, presence: true, length: { minimum: 6 },allow_nil: true # ユーザー更新時に空のパスワードでも大丈夫 # has_secure_passwordの方でpasswordの存在性を検証するから大丈夫 # 渡された文字列のハッシュ値を返す def User.digest(string) cost = ActiveModel::SecurePassword.min_cost ? BCrypt::Engine::MIN_COST : BCrypt::Engine.cost BCrypt::Password.create(string, cost: cost) end # ランダムなトークンを返す def User.new_token SecureRandom.urlsafe_base64 end # 永続的にログインするためにトークンをDBに保存 def remember self.remember_token = User.new_token # 何のトークンか分かりやすいから # remember_tokenって名前を作った update_attribute(:remember_digest,User.digest(remember_token)) # ハッシュ化したトークンをremember_digestに保存 end # 渡されたトークンがダイジェストと一致したらtrue # を返す def authenticated?(remember_token) return false if remember_digest.nil? # 二種類のブラウザを使用してログアウトした場合 # cookiesのremember_tokenはあるけど、 # サーバー側でremember_digestをnilにしてるから # nilに対して.is_password?とかやるとfor nil classエラーが起きちゃう # remember_digestがnilの場合はfalseを返して、処理を止める # 後置if文に当てはまる条件があれば処理を止めて! # って場合はreturnとかで明示的に書くとif ~ else ~ end # とか書かなくて済む BCrypt::Password.new(remember_digest).is_password?(remember_token) end # ユーザーのログイン情報を破棄する def forget update_attribute(:remember_digest,nil) end endこれでユーザー機構に必要であろうメソッドが揃いました、、、!
どのメソッドをどのコントローラーや、ヘルパーに配置すべきかまだイマイチよく分かってないので、これから学んでいきたいですね
本当にこれでしっかり動くのか不安なので実際にビューを動かして次回試してみたいと思います、、、!
- 投稿日:2020-11-20T01:27:58+09:00
個人アプリ開発日記 #2
基本的なテーブル構造
users テーブル
Column Type Options nickname string null: false string null: false, unique: true password_digest string null: false remember_digest string reset_digest string activation_digest string null: false activated boolean default: false activated_ad datetime null: false Association
- has_many :drinks
- has_many :comments
- has_many :trades
drinks テーブル
coffeeは不可算名刺なので初心者が扱うのが怖かった、、
Column Type Options name string null: false price integer null: false explain text null: false user_id integer null: false,foreign_key: true Association
- belongs_to :user
- has_many :comments
- has_many :tags,
- has_many :tags,through: :coffee_tags
- has_one :trade
tags テーブル
Column Type Options name string null: false
- has_many :drinks
- has_many :tags,through: :coffee_tags
coffee_tags テーブル
Column Type Options drink_id integer null: false,foreign_key: true tag_id integer null: false,foreign_key: true
- belongs_to :drink
- belongs_to :tag
comments テーブル
Column Type Options content text null: false user_id integer null: false,foreign_key: true drink_id integer null: false,foreign_key: true Association
- belongs_to :user
- belongs_to :drink
addresses テーブル
Column Type Options postal_code string null: false prefecture_id integer null: false city string null: false house_num string null: false building_name string phone_num string null:false,unique: true trade_id integer null:false,foreign_key: true Association
- belongs_to :trade
trades テーブル
Column Type Options user_id integer null: false,foreign_key: true drink_id integer null: false,foreign_key: true Association
- belongs_to :user
- belongs_to :drink
- has_one :address
次回は実際のコードに触れていきます
- 投稿日:2020-11-20T01:27:02+09:00
初心者はDeviseをカスタマイズするなという話
Deviseを実装したら迷走した
Deviseのことをよくわかっておらず、Contorollerやviewから全部作って設定しようとしてたので、戒めとして記事を書きます。
ControllerとViewは最初からある
Ruby初心者の私はこんなことも直感的に分からなかったんですね。
https://qiita.com/hakatatech/items/f991d54ff527edb844d9
この辺りの記事をみて「はえ〜コマンドでコントローラー作るんだなあ」とコピペで実装していきましたが、最初からあるのでこういうのは実装しなくてOKです。
それでも最初はコマンドを打たねばならない
まあgemファイル追加して必要なものは設定しないといけないので、こちらの記事を参考に実装してみてください。
実際に3日悩んだ結果、ここが一番簡潔で明快でした。
https://qiita.com/salvage0707/items/d3ddc889458ac186e62e
もう初心者はここの「Deviseの使い方」だけやってればいいと思いました。
email認証じゃなくしたいんですけど?
そういう方へは、なんとDeviseの公式記事がございます。
英語ですが、email認証からusername認証にするための方法が全部書かれいてるのでDeepLで翻訳して読んでください。
終わりに
プログラミングの鉄則に「複数のタスクを同時に解決しようとするんじゃない、一個ずつやりなさい」というものがあるみたいですが、今回で身に沁みて分かりました。
あまりにもタスクが多いと「分からないことが分からない」みたいな状況に陥りがちなので、エラー画面から読み取って一つひとつ解決していきます。
- 投稿日:2020-11-20T01:00:29+09:00
個人アプリ開発日記 #1
初めましてHarasouです。これから個人アプリを開発するのでその進捗を更新指定いきたいと思います、、!◎ポートフォリオ概要
■何を作るか
コーヒーの感想をみんなとシェアできて、コーヒーを購入できるアプリ■なぜ作ろうと思ったか
コーヒーが大好きで、みんなのおすすめのコーヒーを
知りたかったけど、日本にコーヒー専用アプリみたいなのはなかったスタバはみんな知ってるのに,スタバのサービスのコーヒーパスポートはみんな知らない
スタバには「コーヒーパスポート」と言う、コーヒーの記録を取れる手帳が実はあるんです、、、!
お洒落でございますね、、、(字が汚い,,)
こんな風に記録を取ることができます、、、!!
■必要な機能
コーヒー購入機能(提携した企業によって商品ラインナップが変わる)
投稿機能
ユーザー登録機能
ログイン機能
ユーザー詳細表示機能
ユーザー編集機能
ユーザー削除機能
投稿一覧表示機能
投稿に画像
投稿詳細表示機能
(ユーザー表示押したらそのユーザーの投稿表示)
投稿削除機能
フォロー機能
(いいね機能)
(レイティング機能)
コーヒータグ付け機能
検索機能
スタンプ機能
ページネーション
フレンドリーフォワーディング
動的なタイトル変更
メール認証
ゲストログイン
ハンバーガーメニュー
レスポンシブ化次回細かな実装に入りたいと思います