- 投稿日:2020-05-19T23:54:40+09:00
[rails]deviseのヘルパーメソッドbefore_action :authenticate_user!の使い方
before_action :authenticate_user!について
deviseを簡単に説明すると、ログイン系をやってくれるgemです。
そのdeviseのヘルパーメソッドauthenticate_user!メソッドは、コントローラーにbefore_actionで記載することで、そのコントローラーで行われる処理はログインユーザーのみ実行可能とすることができるメソッドです。
before_action :authenticate_user!の使い方
authenticate_user!メソッドはコントローラーに記載します。
例class PostsController < ApplicationController before_action :authenticate_user! def index end endこのように記載するとposts_controllerでの処理をすることができるのはログインユーザーのみとなります。
一部の処理を未ログインユーザーでも行えるようにする
例
class PostsController < ApplicationController before_action :authenticate_user!, only: [:show] def index end def show end endこのように記載することで、showアクションのみを未ログインユーザーが使用できないようにできます。
間違いなどがありましたらご指摘いただければ幸いです。
最後までご覧いただきありがとうございました。
- 投稿日:2020-05-19T23:13:43+09:00
Railsでグループ機能(掲示板)を作ってみた
Railsでグループ機能(掲示板風)の作成
<開発環境>
1. ruby 2.6.3
2. Rails 5.1.6
3. AWS Cloud9
4. GitHub
6. sqlite3(develop環境)設計構想
ユーザーは自由にグループを作成でき、また他のユーザーが作成したグループに所属することもできます。
また、グループに参加したメンバーはグループ内で自由に発言することも可能になります。この仕組みをテーブルに落とし込むと、
ユーザーとグループは多対多の関係になるので中間テーブルを用いることとします。
そして、ユーザーとグループ内での投稿も多対多の関係となる為、こちらも中間テーブルを用います。
ER図はこんな感じになりました。(手書きですいません・・・)
モデル
先ほどのER図は以下のようなアソシエーションとなりました。
group.rbclass Group < ApplicationRecord validates :name, presence: true, uniqueness: true has_many :group_users has_many :users, through: :group_users has_many :groupposts accepts_nested_attributes_for :group_users endgroup_user.rbclass GroupUser < ApplicationRecord belongs_to :group belongs_to :user endgrouppost.rbclass Grouppost < ApplicationRecord belongs_to :group belongs_to :user endコントローラー
groups_controller.rbclass GroupsController < ApplicationController def new @group = Group.new @group.users << current_user end def create if Group.create(group_params) redirect_to groups_path, notice: 'グループを作成しました' else render :new end end def index @groups = Group.all.order(updated_at: :desc) end def show @group = Group.find_by(id: params[:id]) if !@group.users.include?(current_user) @group.users << current_user end @groupposts = Grouppost.where(group_id: @group.id).all end private def group_params params.require(:group).permit(:name, :user_id []) end def grouppost_params params.require(:grouppost).permit(:content) end end基本的な設計はユーザー周りと同じです。
def show . . if !@group.users.include?(current_user) @group.users << current_user end endこのようにグループのリンクを踏んだ人がそのグループに所属できるようにしています。
grouppost_controller.rbclass GrouppostsController < ApplicationController def new @grouppost = current_user.groupposts.new @group = Group.find_by(id: params[:group_id]) end def create @group = Group.find_by(id: params[:group_id]) @grouppost = current_user.groupposts.new(grouppost_params) @grouppost.group_id = params[:group_id] if @grouppost.save redirect_to group_path(@group.id) end end private def grouppost_params params.require(:grouppost).permit(:content) end endこちらも以前作成した投稿機能と同じ形にしています。
以上で2chちっくなグループ機能(掲示板風)が完成しました。
今後の課題としては、グループ作成時に鍵をかけることができ、招待制のグループを作ることができるようにしたいと考えています。
- 投稿日:2020-05-19T22:56:58+09:00
devise導入からフラッシュ実装②
最初に行うコマンド
deviseをインストールする
rails g devise:installuserモデルを作る。ユーザー管理に必要なため
rails g devise userいつもの
$ rails db:migrateヘッダーをいじります。新規登録とログインとログアウトのリンクを作る
= link_to 'ログアウト', destroy_user_session_path, method: :delete, class: 'header__top__userMenu--logout' - else = link_to '新規登録', new_user_registration_path, class: 'header__top__userMenu--logout' = link_to 'ログイン', new_user_session_path, class: 'header__top__userMenu--logout'未ログインのアクセス制限
before_action :move_to_index, except: [:index] private def move_to_index redirect_to action: :index unless user_signed_in? enddeviseのコマンドでビューを作る
rails g devise:viewsサインアップ時にニックネームを登録
userテーブルにカラムを追加
rails g migration AddNicknameToUsers nickname:string最大文字数のために
<div class="field"> <%= f.label :nickname %> <em>(6 characters maximum)</em><br /> <%= f.text_field :nickname, autofocus: true, maxlength: "6" %> </div>を追加
ニックネームカラムを送れるようにする
devise_parameter_sanitizerはrequireみたいな意味らしいapplication_controller.rb before_action :configure_permitted_parameters, if: :devise_controller? protected def configure_permitted_parameters devise_parameter_sanitizer.permit(:sign_up, keys: [:nickname]) endtweetsカラムにuser_idを追加する
rails g migration AddUserIdToTweets user_id:integerツイート投稿時にユーザーidを追加
.merge(user_id: current_user.id)アソシエーションの定義
1,モデルクラスにhas_many ~~sやbelongs_to ~~(単数形)で関係が定義されてる
2,所属する側のテーブルに「所属するモデル名_id(例)tweet_id」というカラムがあるhas_many :tweets belongs_to :userマイページの作成
1.マイページのルーティングを記述しよう
2.マイページへのリンクを作成しよう
3.コントローラーとアクションを作成しよう
4.マイページ用のビューファイルを作成しよう
resources :users, only: :show
= link_to current_user.nickname, user_path(current_user.id)
Usersコントローラーを作成rails g controller users def show @nickname = current_user.nickname @tweets = current_user.tweets endツイート一覧画面にニックネームを表示
1.投稿者名を表示するようにビューを変更しよう
2.ツイートからユーザー情報を先読みしよう
3.投稿画面のビューを変更しよう
4.投稿時のコントローラーでの処理を変更しよう
includes(:user)を使ってincludesを解消ログインユーザーのみ編集削除が可能にする
orderメソッドで。@tweets = Tweet.includes(:user).order('updated_at desc')ページネーションの実装
kaminariをbundle install
?pageメソッド
paramsの中にpageキーが追加される。引数はparams[:page]
?parメソッド
1ページあたりに表示する件数を指定
?paginateメソッド
ページネーションのリンクを表示するメソッド@tweets = Tweet.includes(:user).order('updated_atdesc').page(params[:page]).per(5) <%= paginate(@tweets) %>コメント機能
$ rails g model commentマイグレーションファイルを編集してrails db:migrate
アソシエーションとroutesの設定$ rails g controller comments def create Comment.create(comment_params) end private def comment_params params.require(:comment).permit(:text).merge(user_id: current_user.id, tweet_id: params[:tweet_id]) end詳細ビューにコメント投稿フォームと一覧を変更
<%= form_with(model: [@tweet, @comment], local: true) do |form| %> <%= form.text_area :text, placeholder: "コメントする", rows: "2" %> <%= form.submit "SEND" %>showアクションにコメントを追加(超大事、comment定義してなくて1時間こけた)
def show @comment = Comment.new @comments = @tweet.comments.includes(:user) end検索機能の実装(2種類あり)
①collectionを使う
tweetにネストしてルーティングの設定
collection do get 'search' endform_withで検索するフォームを作る
tweetモデルに検索するメソッドを作成
def self.search(search) if search Tweet.where('text LIKE(?)', "%#{search}%") else Tweet.all end endtweetsコントローラにsearchアクションを定義
def search @tweets = Tweet.search(params[:keyword]) end検索結果のビューを表示
<% @tweets.each do |tweet| %> <%= render partial: "tweet", locals: { tweet: tweet } %> <% end %>②namespaceを利用した方式(⑦つのアクションのみ使用)
searchesコントローラーを作成$ rails g controller tweets::searchesnamespaceのルートを追加する
resouece :tweetsより上に書くこと。
ルートの順番の問題。tweetsのルートが先に読まれておかしくなるからnamespace :tweets do resources :searches, only: :index end検索フォームを追加する
<%= form_with(url: tweets_searches_path, local: true, method: :get, class: "search-form") do |form| %> <%= form.text_field :keyword, placeholder: "投稿を検索する", class: "search-input" %> <%= form.submit "検索", class: "search-btn" %>searchコントローラーにindexアクションを追加する
def index @tweets = Tweet.search(params[:keyword]) endtweetモデルに検索するメソッドを作成
def self.search(search) if search Tweet.where('text LIKE(?)', "%#{search}%") else Tweet.all end end検索結果フォームを追加
<% @tweets.each do |tweet| %> <%= render partial: "tweets/tweet", locals: { tweet: tweet } %> <% end %>フラッシュメッセージの実装
①フラッシュメッセージが表示されるようにする
②フラッシュメッセージのスタイリングを行う
③フラッシュメッセージを日本語化するapp/views/layouts/_notifications.html.haml
.notification - flash.each do |key, value| = content_tag :div, value, class: key
- 投稿日:2020-05-19T21:42:08+09:00
【Railsチュートリアル】第1章にあるGitのこと
はじめに
この記事ではRails チュートリアルの第1章
で使用されているGitの使い方について
まとめた記事です。
ベストプラクティスや間違いがあれば
チュートリアルをやりながら書き直していく予定です。Git
言わずと知れたVersion管理ツール
ちなみにGit HubとGitは別物
よく勘違いされているのであらかじめ書いておきます。Git : 技術の名前、コマンド
Git Hub : Gitを使ったサービスザックリいうとそんな感じです。
チュートリアル 第1章
チュートリアル上で使われてるAmazonのクラウドIDE
Cloud9もそうですが、まぁ日頃使っていないので
使い方を忘れるんですよね。。。
それと同じようにGitも業務に取り入れていない状態で
案の定忘れていました。今後、職場に導入することも考えて
自分なりのリファレンスをどこかで作りたいな。。。今回はそんな忘れっぽい私のような人に贈る内容です。
設定コマンド
インストールをするときに欠かせない設定コマンド
社内のそれも外の世界とつながっていない場合でも
これは入れるのだろうか。。。git config --global user.name [username] git config --global [mailaddress]最低限知っておきたい Gitコマンド
$ git init $ git add -a $ git status $ git commit -am "命令系のコメント"git addの-aオプションは
作業ツリーのファイルをすべてステージするという意味
チュートリアルでは注意して使うように書いてある。
「変更する必要のないファイルも
一緒にステージングしてしまうから」という意味で書いてるのかなといっても中途半端にあらゆるファイルに変更を加えるのにはリスクがある。
そう思うのは一人で開発しているからかな。ちなみに初めて知りましたがGitのコメントは命令形
(チュートリアルでは体言止めと表記)が良いみたいです。筆者は日頃から体言止めで書いているので
ここは当たり前のようにcommitしてました。Git初心者から脱却したいなら
リポジトリやバックアップについて勉強しよう。
Gitではブランチを使うことで
変更履歴を複数持たせることができる。文字通どおり枝分かれさせることができるので
オリジナルファイルを複数持つことなく
変更履歴A 変更履歴B といった感じに
変更履歴のみを管理することができる。何がすごいってオリジナルファイルを
2コ3コと持たなくてよいということよくファイル名で
ファイル名_YYYYMMDD-0.txtやファイル名_YYYYMMDD-1.txtといった
ファイルを目にすることだろう。どれが新しいのかわからない
そういった面倒な版数管理をする必要がないのだ。また、どうしても
2重管理したいということであれば
別のサーバ上にリポジトリを作成することができる。これを
「リモートリポジトリを作成する」
という。
リモートリポジトリは
まず、リモートにリポジトリを
登録することから始まり
プッシュすることで終わる。厳密にはSSHの鍵が必要だとかどうとかあるけど今回は脱線するので
もっと知りたい人は調べてください。' 現在、スイッチしているブランチ名を参照する $ git checkout 'リモートリポジトリの操作(ここではmasterブランチにプッシュ) $ git remote add origin リポジトリURL $ git push origin master ' 枝分かれtestの作成 $ git checkout -b test ' 枝分かれtestとmasterの結合(masterにスイッチ後) $ git merge test ' 全ての枝分かれを表示 $ git branch ' コミットログの表示(変更履歴が多い場合はこのまま打つのは得策ではないかも) $ git log '任意の変更箇所まで戻る(もしかすると、ベストプラクティスがあるかも) $git reset ハッシュ値出力メッセージの英語翻訳
あと、チュートリアルの最中に気になった文言
単語 日本語 On branch master 親ブランチを参照しています No commits yet まだコミットされていません Changes to be committed コミットされる変更 Changes not staged for commit 変更がステージングされていません nothing to commit, working tree clean 作業ツリーにコミットするものは何もありません discard changes in working directory 作業ディレクトリの変更を無視する おわり
- 投稿日:2020-05-19T21:03:23+09:00
Rails テスト
前提
本日学んだことを書いていきます。
本題
単体テスト
RSpecをインストール
#省略 group :development, :test do # Call 'byebug' anywhere in the code to stop execution and get a debugger console gem 'byebug', platforms: [:mri, :mingw, :x64_mingw] gem 'rspec-rails', '~> 3.8' #追記 gem 'factory_bot_rails', '~> 5.0' #追記 end # 省略$ bundle installRspec・FactoryBotがインストールされているか確認
$ bundle exec rspec --version $ bundle exec gem list | grep factory_bot_railsアプリのプロジェクトにRSpecを導入
$ rails g rspec:installテスト用のDBを最新の構成にする
$ rails db:migrate:reset RAILS_ENV=testテスト用のDBとは自動テストを実行するときに利用する専用のDB
例えば自動テストで「全データが消えること」を確認するとき、開発中に利用しているデータが消えてしまっては困る
開発中のデータと自動テスト用のデータを分離して考えることで、双方が干渉しないようになるモデルのテストコードを追加
$ rails g rspec:model モデル名テスト実行コマンド
$ bundle exec rspecRSpecでテストケースを識別するための3つのキーワード
・describe
正常系の機能
大分類のようなイメージで何についてテストをするかを記述する・context
回答する
中分類のようなイメージで状況を記述する・it
正しく登録できること
個々のテストケースを表し、期待する振る舞いを記述するenquete = FoodEnquete.new( name: '田中 太郎', mail: 'taro.tanaka@example.com', age: 25, food_id: 2, score: 3, request: 'おいしかったです。', present_id: 1 ) # バリデーションが通ること(バリデーションエラーが無いこと)を検証 expect(enquete).to be_valid※Rails 5.2以降のRSpecではテストコードの実行が終了すると、DBの状態を元に戻してくれる
$ bundle exec rspec spec/models/〜.rb . Finished in 0.03355 seconds (files took 2.24 seconds to load) 1 example, 0 failures実行結果の1行目に記号やアルファベットで結果が表示される
.
成功 テストコードの想定通りに動作した
F
失敗 テストコードの想定通りに操作しなかった# true/falseのような真偽値を検証する時、be_truthy/be_falseyをマッチャーとする expect(new_enquete.save).to be_falsey_enquetes.rbFactoryBot.define do factory :food_enquete do name { '田中 太郎' } mail { 'taro.tanaka@example.com' } age { 25 } food_id { 2 } score { 3 } request { 'おいしかったです。' } present_id { 1 } end end_enquete_spec.rb# FactoryBot.build(クラス名) enquete = FactoryBot.build(:food_enquete)FactoryBot.create(クラス名)を呼出すと「田中 太郎」のテストデータが作成、さらにテストデータがDBへ保存される
つまり、.saveが不要になるFactoryBot.create(:food_enquete)FactoryBot.build(クラス名, 上書きしたい項目: XX)を呼出すと「田中 太郎」のテストデータが作成される
ここでは「お召し上がりになった料理」「満足度」「希望するプレゼント」「ご意見・ご要望」を上書きしているre_enquete_tanaka = FactoryBot.build(:food_enquete, food_id: 0, score: 1, present_id: 0, request: "スープがぬるかった")_enquete_spec.rb# このテストコードでは、各テストケースの前処理として「田中 太郎」のテストデータを作成する before do FactoryBot.create(:food_enquete_tanaka) end_enquete_spec.rb# インスタンスを共通化してテストデータを作成 let(:new_enquete) { FoodEnquete.new }共通メソッドのテストコードのファイルを認識させる
モデルのテストコードを書くためのファイルはrails g rspec:model
で準備したが、共通メソッドは手動で用意する
RSpecが手動で作成するテストコードのファイルを認識するように設定を修正する
以下のテストコードのモデルのインスタンスを共通化
まずは修正前のテストコードを確認spec/rails_helper.rb# 省略 # コメントアウトを解除する # Dir[Rails.root.join('spec', 'support', '**', '*.rb')].each { |f| require f } Dir[Rails.root.join('spec', 'support', '**', '*.rb')].each { |f| require f } # 省略共通メソッドのテストコードのファイルを追加
spec/support/concerns/common_modules.rb
にテストコードを追加共通のテストコードを定義するときは
shared_examples
を利用し、その中にテストコードを書く_enquete_spec.rb# 共通のテストコードを呼出すときはit_behaves_likeを利用 it_behaves_like '価格の表示'統合テスト
capybara
統合テスト(E2E)のフレームワーク
Rspecと連携してWEBブラウザの自動操作を支援するselenium-webdriver
capybaraを通じてWEBブラウザを自動で操作するwebdrivers
GoogleChromeを操作するドライバGemfile.group :test do gem 'capybara', '~> 3.28' gem 'selenium-webdriver', '~> 3.142' gem 'webdrivers', '~> 4.1' endterminal.$ bundle installインストールされているか確認
$ bundle exec gem list | grep -e capybara -e selenium-webdriver -e webdrivers capybara (3.32.2) selenium-webdriver (3.142.7) webdrivers (4.3.0)
spec_helper.rb
の修正spec_helper.rb# 省略 require 'capybara/rspec' #追記 RSpec.configure do |config| # ブラウザにChromeを指定(以下追記) config.before(:each, type: :system) do driven_by :selenium, using: :chrome, screen_size: [1280, 960] end # 省略 end※Chromeを1280px × 960pxのウィンドウサイズで開いて操作
追記
--skip-test
デフォルトのテストフレームワークを作成しない
--skip-coffee
CoffeeSprictを使用しない
- 投稿日:2020-05-19T20:43:13+09:00
Dockerでの環境構築(Rails)超入門3 ~MySQLを立ち上げる~
これまで
Dockerでの環境構築(Rails)超入門1
Dockerでの環境構築(Rails)超入門2 ~Dockerfileの設定~やること
前々回立ち上げたRailsは初期設定で「sqlite3」に接続している
今回はMySQLサーバーを立ち上げ、複数コンテナを動作させる手順
- MySQLサーバーを立ち上げる
- Railsのプロジェクトを書き換える
実践
- MySQLサーバーを立ち上げる
1) docker-compose.yamlの編集
docker-compose.yamlversion: '3' services: mysql: image: mysql:8.0.20 command: --default-authentication-plugin=mysql_native_password volumes: - "./mysql-data:/var/lib/mysql" environment: MYSQL_ROOT_PASSWORD: root app: build: . volumes: - ".:/app" ports: - "3000:3000" tty: true depends_on: - mysql2)「mysql-data」フォルダをappと同じ階層に作成
3) Dockerfileに以下を追加
DockerfileFROM ruby:2.6.6-stretch RUN gem rails install RUN apt-get update && \ apt-get install -y node.js *mysql-client* COPY Gemfile/Gemfile COPY Gemfile.lock/Gemfile.lock RUN bundle install4) Mysqlに接続する
$ docker-compose up --build $ docker exec -it practice_app_1 /bin/bash /# mysql -u root -proot -h mysql > show databases; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | sys | +--------------------+2 . Railsのプロジェクトを書き換える
・Gemfileを以下に編集Gemfile(省略) gem 'sqlite3'→ gem *'mysql2' (省略)・config/database.yamlを編集
config/database.yamldefault: &default adapter: mysql2 enconding: utf8 username: root password: root host: mysql pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> timeout: 5000 development: <<: *default database: practice_development # Warning: The database defined as "test" will be erased and # re-generated from your development database when you run "rake". # Do not set this db to the same as development or production. test: <<: *default database: practice_test production: <<: *default database: practice_production・app/#に移動して
rake db:create
でデータベースを作成・再度Mysqlに接続してデータベースが作成されていることを確認
+----------------------+ | Database | +----------------------+ | information_schema | | mysql | | performance_schema | | practice_development | | practice_test | | sys | +----------------------+最後に
rails s -b 0.0.0.0
でローカルに接続すれば開発環境の構築はOK!補足
- 別のコマンドでコンテナに入る
今まで
$ docker exec -it pracitce /bin/bash
でコンテナに入っていたが、「docker-compose.yaml」が入っているファイルがあれば、$ docker-compose exec コンテナ名(app)/bin/bash2 . コンテナに入ったあと、自動的にappに移動したい
1) docker-compose.yamlの編集docker-compose.yamlversion: '3' services: mysql: image: mysql:8.0.20 command: --default-authentication-plugin=mysql_native_password volumes: - "./mysql-data:/var/lib/mysql" environment: MYSQL_ROOT_PASSWORD: root app: build: . volumes: - ".:/app" ports: - "3000:3000" tty: true depends_on: - mysql #以下を追加 *working_dir: "/app"*これで
docker exec compose app /bin/bash
の後、自動的にapp/#に移動している
- 投稿日:2020-05-19T18:52:44+09:00
Day17 #Railsデバッグ方法
デバッグのツールについて
- binding.pryを追記することで、エラー内容のヒントになる。
app/controllers/posts_controller.rbdef create binding.pry Post.create(post_params) redirect_to root_path end[2] pry(#<PostsController>)> post_params Unpermitted parameter: :titles User Load (0.6ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 2 ORDER BY `users`.`id` ASC LIMIT 1 ↳ app/controllers/posts_controller.rb:38 => <ActionController::Parameters {"content"=>"牙通牙", "user_id"=>2} permitted: true> #unpermittedの内容を教えてくれる。
- 投稿日:2020-05-19T17:59:24+09:00
atomのerbでrailsのコードが上手く反応してくれない
ruby on railsを勉強している初心者です。progateのruby on rails のすべて終了後、自分でコードを書いているのですが、index.html.erbに<% >を追加したところ、以下のhtmlコードはすべて反応しなくなりました。このような時はどのような対応をすればよいでしょうか。atomでコードを書いています。
- 投稿日:2020-05-19T17:25:22+09:00
大学生Railsエンジニアが、1人でWebとアプリをリリースするまでの3ヶ月間の話
Qiita初投稿なのでお手柔らかに。
自分は大学生ながら都内のスタートアップでエンジニアをしています。
普段はRailsでのWebサービス開発がメインで、SwiftもKotlinも触ったことすらありませんでした。
経験ゼロのReact NativeとExpoでリリースまでに得た知見を残していきます。
開発したサービス
SportsLab | スポーツをより深く楽しめる新しいメディアコメントと共にスポーツのニュースを読めるサービスです。
Webとアプリの両方を1人で開発・運用しています。スタートアップあるあるですね笑。
使用技術
ざっくり使用している技術を紹介します。
Web: Rails 5.0, jQuery
アプリ: React Native, Expo, (TypeScript)
インフラ: ElasticBeanstalk(AWS)
認証: Firebase Auth
CI: Circle CI
スタートアップではよくある感じの技術構成だと思います。
Railsのエコシステムや周辺ライブラリの豊富さには助けられました。
アプリについては僕がSwiftやKotlinをかけないため泣く泣くReact Nativeを採用しました。
開発スケジュールを振り返る
開発の時間軸としては
12/24
記念すべきfirst commit
1/1
年明けにEC2にデプロイ
1/2
ドメインを取得してWeb版をローンチ
1/4
アプリを開発開始
2/1
Appleに初めて申請
2/13
朝起きたらアプリが公開されてました!
2/20
安定版がストアで公開される一人で開発して良かった事
今までのJSの経験を生かす事が出来た
React Native & Expoを採用した事でSwift, Kotlinを勉強する事なく純粋にJavaScript(TypeScript)を書くだけでモバイルアプリを開発できた、というのが一番ですね。
OTAアップデートで簡単に更新できる
また、ExpoにはOTAアップデート機能があるのでそちらを使えばストアに申請する事なくユーザのアプリを強制的にアップデートできるのも魅力の1つです。
デザインについても Native Base や React Native Elements といったUIライブラリが揃っているのでCSSをほとんど書く事なく開発を進められたのも大きかったです。
一人で開発して辛かった事
気軽にストア申請できない
ユーザによって使うアプリのバージョンがまちまちになってしまうので、API側でルーティングの変更などの仕様を変えられないのが辛いです。
TypeScript難しい?
React Nativeは完全に独学で、今も付け焼き刃の状態でコードを書いているのでアプリの挙動が不安定なのがネックでした。
少しでもバグを減らすためにTypeScriptを導入しましたが、動的型付けであるRubyしか書いてこなかったので、そもそも型ってなんですか?というレベルで、TypeScriptの恩恵を十分に受けられてないです。
これから勉強していきます!
ファイルの肥大化
useEffectで通信処理をViewにベタガキしてるのでファイルが巨大化してカオスofカオス。
Reduxや, Redux-sageなどのミドルウェアの学習と導入が待たれる。。。(そう言えば、つい最近FaceBookが新しい状態管理ライブラリを出してきましたね!)
申請が通らない!!!
最初App Storeの申請で数週間悩まされました。理由はこいつでした。
4.2 minimum functionality We found that the usefulness of your app is limited by the minimal features it includes.どうも調べたところ
お前の作ったアプリは⚪️ミだからアウト!
っていう意味らしいです。Push通知実装したり、記事の検索機能つけたりいろいろしたのですがダメでした。
ではどうやって通したかというと・・・
ウォークスルーを実装しました!!!
それだけです。
正直なんで通ったのか分からないです。
どうやら
アプリでないと得られないUX
を訴求したのが良かったっぽいです。同じ理由でリジェクトされてる人が一人でも多く救われますように。
ExpoをアップグレードしたらFacebookでログインできなくなった
ふと朝起きると同僚からSlackで同僚からメンションが来ていました。
Facebookでログインしようとするとアプリがクラッシュするんだけど
報告を受けた瞬間、顔面蒼白になりました。
急いで調査を開始するも、全く原因を特定できませんでした。
焦りを加速させたのはSentry経由でSlackにエラー通知も流れてこないという事でした。
つまり具体的にどこのコードでクラッシュしてるのか検討がつかない。
公式ドキュメント通りに実装してるし、どこが悪いのか悩む日々。
分からなさすぎてExpoにIssueまで立てちゃう始末。
Problem login with Facebook and Firebase
そのあともう一度Expo37のchangelogを調べていくと・・・ありました!!!
https://github.com/expo/expo/pull/7931/files
読んでいくと、途中にこんな記述が。
- In the Expo Client, all of your Facebook API calls will be made with Expo's Facebook App ID. This means you will not see any related ad info in your Facebook developer page while running your project in the Expo Client. - To use your app's own Facebook App ID (and thus see any related ad info in your Facebook developer page), you'll need to [build a standalone app](../../distribution/building-standalone-apps/).どうやら開発環境ではFacebookログインはできなくなったようです。
なのでビルドして動作確認する必要があるようでした。
ちなみに僕はこれに気付かず
Possible Unhandled Promise Rejection (id: 0): [Error: Unsuccessful debug_token response from Facebook: {"error":{"message":"(#100) The App_id in the input_token did not match the Viewing App","type":"OAuthException","code":100,"fbtrace_id":"********"}}]というエラーを3日間眺める羽目になりました。。。
1人でRailsでAPIを作った感想
JSONの整形にはActive Model Serializerが神
デフォルトでインストールされてるjbuilderは評判悪そうなのでActive Model Serializerを採用しました。
スター数も多いし大丈夫そうって思ってた矢先、更新が止まるという。。。
しばらくはこれで行く予定です。
Netflixが出してるfast_jsonapiっていうのが来てるらしいのですが学習コストが高そうなので断念しました。
Active Moel SerializerはActive Recordベースでかけるため直感的ですがSerializer側に値を渡す時のやり方が分からなくて最初苦労しました。
検索してもヒットするのが古いバージョンの記事ばかりで諦めかけていた、そのとき!
ActiveModelSerializers(0.10系)のインスタンス生成時に引数を渡してSerializerクラス内で使う方法
こちらの記事を発見しました。これに全て書いてあります。神!!!
重い腰を上げてFat Controllerを解決
あと初心者Railsエンジニアあるあるですね。
これどうしようかつい最近まで悩んでいたのですが
こちらを参考にさせて頂きました。
POROでサービスクラス(上記の記事ではWorkflows)を作ってそこに切り出そうというアプローチです。
あとControllerを分けてCRUDしかメソッドが作成されないようにする。
試してみましたがいい感じです。自分の書き方が合ってるか自信ありませんが。。。
突然のDockerの導入
実はWeb版のCSSは弊社のCEOが自ら書いています。
で、そのCEOのPCで環境構築しようとしたらなぜか環境構築で詰まりまして。。。
試行錯誤した結果、初めてDockerなるものを導入しました。
と言っても、開発環境でDockerfile書いただけです。
本番環境でのECSやFargateを使ったDockerの運用はリリース後のお楽しみという事で・・・。
Docker for Mac予想以上に重かった!
PCは高いやつを買おうと心に決めました。
こんな感じです!
最後に
今も一人でアプリ、バックエンド、インフラまで面倒見てます!
一緒にコードかきたい方は僕のTwitterアカウントまでDMどうぞ!!!
https://twitter.com/Katsukiniwa
- 投稿日:2020-05-19T15:15:48+09:00
【Rails】gem devise インストール時の流れ
はじめに
Qiita初投稿です。
拙い文章で恐縮ですが、ご一読いただけますと幸いです。
よろしくお願いします。ユーザー管理機能のためのgem deviseをインストール
1. Gemfileの最終行に以下のように追記
Gemfile# 省略 gem 'devise' # 最終行に追記してください2. ターミナルで
bundle install
を実行ターミナル$ bundle install3. Gemfile.lockで
devise
がインストールされたか確認Gemfile.lock# 省略 devisedeviseの適用
インストールが完了したら、devise専用のコマンドを利用して設定ファイルを作成
4. ターミナルで
rails g devise:install
を実行ターミナル# deviseの設定ファイルを作成 $ rails g devise:install新規作成されるファイル
- config/initializers/devise.rb
- config/locales/devise.en.yml
5. ターミナルで
rails g devise user
を実行ターミナル# deviseコマンドでモデルを作成 $ rails g devise user新規作成されるファイル
- app/models/user.rb
- db/migrate/20XXXXXXXXXXXX_devise_create_users.rb
- test/fixtures/users.yml
- test/models/user_test.rb
また、config/routes.rbに
devise_for :users
の記述が自動的に追記されます。config/routes.rbRails.application.routes.draw do devise_for :users # 省略6. ターミナルで
rails db:migrate
を実行ターミナル# 作成されたマイグレーションファイルを実行 $ rails db:migrate7. ターミナルで
rails g devise:views
を実行ターミナル# devise用のビューを作成 $ rails g devise:views新規作成されるファイル
- app/views/devise/shared
- app/views/devise/shared/_error_messages.html.erb
- app/views/devise/shared/_links.html.erb
- app/views/devise/confirmations
- app/views/devise/confirmations/new.html.erb
- app/views/devise/passwords
- app/views/devise/passwords/edit.html.erb
- app/views/devise/passwords/new.html.erb
- app/views/devise/registrations
- app/views/devise/registrations/edit.html.erb
- app/views/devise/registrations/new.html.erb
- app/views/devise/sessions
- app/views/devise/sessions/new.html.erb
- app/views/devise/unlocks
- app/views/devise/unlocks/new.html.erb
- app/views/devise/mailer
- app/views/devise/mailer/confirmation_instructions.html.erb
- app/views/devise/mailer/email_changed.html.erb
- app/views/devise/mailer/password_change.html.erb
- app/views/devise/mailer/reset_password_instructions.html.erb
- app/views/devise/mailer/unlock_instructions.html.erb
以上、
gem devise
のインストール時の流れを説明させて頂きました。
少しでも多くの方の参考になれば幸いです。
- 投稿日:2020-05-19T14:19:02+09:00
wicked pdfは、windowsでは動きません!
wicked pdfをリファレンス通りに実行し、
ネットの記事を英語を含め読みまくっても、全く動かず、
エラーを吐きまくっていた。なんでやねんと、検索してあたった記事がこれ。
https://github.com/mileszs/wicked_pdf/issues/693以前はwindowsも対応していたらしいが、今はしていないらしい。
このコメントによって、公式のread meからwindows対応の文字が消された模様。
要するに、
wicked pdfは、windowsでは動きません!(2020.05.19時点)local環境だけでよければ可能なもよう。
windowsのc:にダウンロードして、
rails アプリのpathの先を、wicket PDFのインストール先に設定すると
動くみたい。だが、某は本番アプリで使いたいので、意味がなし!!!
ってなことで、windowsユーザーのプログラマーさんは、
無駄な時間を使わないようにお気を付けください。
- 投稿日:2020-05-19T12:59:01+09:00
HerokuデプロイでMySQLのConnectionErrorが出たときの対処
状況
heroku上にアプリを作成するまでは完了していて、URLにアクセスしたら「Welcome to your new app!」と出て、
herokuへgitでプッシュまでしたのですが、最後にデータベースを作成しようとしました。しかし、ここでConnectionError。$ heroku run rails db:migrate :1033:in `retrieve_connection' /app/vendor/bundle/ruby/2.5.0/gems/activerecord-5.2.4.3/lib/active_record/connection_handling.rb:118:in `retrieve_connection' /app/vendor/bundle/ruby/2.5.0/gems/activerecord-5.2.4.3/lib/active_record/connection_handling.rb:90:in `connection' /app/vendor/bundle/ruby/2.5.0/gems/activerecord-5.2.4.3/lib/active_record/tasks/database_tasks.rb:172:in `migrate' /app/vendor/bundle/ruby/2.5.0/gems/activerecord-5.2.4.3/lib/active_record/railties/databases.rake:60:in `block (2 levels) in <top (required)>' /app/vendor/bundle/ruby/2.5.0/gems/railties-5.2.4.3/lib/rails/commands/rake/rake_command.rb:23:in `block in perform' /app/vendor/bundle/ruby/2.5.0/gems/railties-5.2.4.3/lib/rails/commands/rake/rake_command.rb:20:in `perform' /app/vendor/bundle/ruby/2.5.0/gems/railties-5.2.4.3/lib/rails/command.rb:48:in `invoke' /app/vendor/bundle/ruby/2.5.0/gems/railties-5.2.4.3/lib/rails/commands.rb:18:in `<top (required)>' /app/vendor/bundle/ruby/2.5.0/gems/bootsnap-1.4.6/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:23:in `require' /app/vendor/bundle/ruby/2.5.0/gems/bootsnap-1.4.6/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:23:in `block in require_with_bootsnap_lfi' /app/vendor/bundle/ruby/2.5.0/gems/bootsnap-1.4.6/lib/bootsnap/load_path_cache/loaded_features_index.rb:92:in `register' /app/vendor/bundle/ruby/2.5.0/gems/bootsnap-1.4.6/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:22:in `require_with_bootsnap_lfi' /app/vendor/bundle/ruby/2.5.0/gems/bootsnap-1.4.6/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:31:in `require' /app/vendor/bundle/ruby/2.5.0/gems/activesupport-5.2.4.3/lib/active_support/dependencies.rb:291:in `block in require' /app/vendor/bundle/ruby/2.5.0/gems/activesupport-5.2.4.3/lib/active_support/dependencies.rb:257:in `load_dependency' /app/vendor/bundle/ruby/2.5.0/gems/activesupport-5.2.4.3/lib/active_support/dependencies.rb:291:in `require' /app/bin/rails:9:in `<main>' Tasks: TOP => db:migrate (See full trace by running task with --trace)解決した方法
色々なサイトをみているうちに、DATABASE_URLが関係あるということがわかったので、見てみる。
$ heroku config | grep CLEARDB_DATABASE_URL => CLEARDB_DATABASE_URL=mysql://~省略「mysql://」を「mysql2://」に変える必要がある!
gemではmysql2を使っていたので対応させる必要があった。なので上書きします
$ heroku config:set DATABASE_URL=mysql2://~省略 Setting DATABASE_URL and restarting ⬢ アプリ名... done, v9 DATABASE_URL: mysql2://~省略これで上書きされました。
そして再度データベース作成をしてみます$ heroku run rails db:migrate ...省略 Migrating to CreateIntros (20200518235947) == 20200518235947 CreateIntros: migrating ===================================== -- create_table(:intros) (10.1ms) CREATE TABLE `intros` (`id` bigint NOT NULL AUTO_INCREMENT PRIMARY KEY, `created_at` datetime NOT NULL, `updated_at` datetime NOT NULL) -> 0.0106s == 20200518235947 CreateIntros: migrated (0.0106s) ============================これで正常にDBが作成され、公開できます。
- 投稿日:2020-05-19T12:51:06+09:00
Ruby public protected private
- 投稿日:2020-05-19T11:40:34+09:00
Dockerコンテナ実行時に、You must use Bundler 2 or greater with this lockfile.
dockerコンテナ上で
docker-compose exec app rails console
コマンドでrailsのコンソールを立ち上げようとしたところ、You must use Bundler 2 or greater with this lockfile.
と出てしまったときの対処法。[メモ]
docker-compose exec app gem install bundler docker-compose exec app bundle install以上。
- 投稿日:2020-05-19T10:54:29+09:00
Railsデータベース基礎
テーブル
表形式の収納場所でデータベースの中にいくつも作成することができる。
データベースが存在していても、このテーブルがなければデータを保存することはできません。レコードとカラム
テーブルは表形式になっていますが、その横一行のことをレコードと言います。また。縦一列のことをカラムと言います。
テーブルのレコードを特定するために、idというカラムが用意されています。DOA
DOAとはデータ中心アプローチのことで、プログラムよりも前にデータ設計を先に行う方法のことです。
サービス開発がより効率的になることが期待されます。データベース設計
手順としては
1.テーブルの抽出
途中でテーブルを追加すると関係性を見直さなければいけなくなる。
予約語は使わないように。2.テーブルの定義
各テーブルが持つカラムを決める。途中で追加するとコードを書き直したり、ビューを変更しなくてはいけない場合が出てくるからです。
予約語は使わないように。3.テーブル構造を整理
同じカラム名を同じテーブル内に作ってはいけません。
そのような場合は別でテーブルを作りましょう。
EX)同じテーブルに imageカラム、 image2カラムなど。この場合はimageテーブルを作る。4.ER図の作成
テーブル同士の関係をわかりやすく表した図。
IE表記法という書き方で書く。モデル
モデルの命名規則
モデルクラス名は先頭は大文字の単数形
モデルクラスのファイル名は、先頭小文字の単数形
テーブル名は先頭小文字の複数形
EX)Animal モデルクラス名
animal モデルクラスのファイル名
animals テーブル名これらモデルファイルとテーブルを作成するコマンドがあります。
それがrails g model
コマンドです。このコマンドの後に作成したいモデルクラスの名前を全て小文字で続けます。
EX)rails g model animalこのコマンドを叩くとテーブルが作成されると言いましたが、テーブルの設計図ができているだけでテーブル自体はまだできていません。テーブルの設計図のことをマイグレーションファイルと言います。
マイグレーションファイル
changeメソッドを使って作成するカラムを指定できます。
カラムの型
integer 数字 idなど
string 少なめの文字 ユーザー名、パスワード
text 多めの文字 投稿文
boolean 真か偽か 真偽フラグ
datetime 日付と時刻 作成日時、更新日時マイグレーションファイルの設定
2020XXXXXXXXXXXXXXXX_create_XXXX.rbclass CreateXxxxxx < ActiveRecord::Migration[5.2] def change create_table :xxxxs do |t| t.string :name t.text :text t.text :image t.timestamps null: false end end endマイグレーションファイルの実行
rake db:migrate
このコマンドを行うと、ファイルが更新されます。
スキーマファイルには最新のマイグレーションファイルのバージョンが記録される。
schema_migrations
はデータベースの変更履歴のようなもので、どのマイグレーションファイルまでが実行されているかが記録されています。マイグレーションファイルはschema_migrationsと齟齬が生じる恐れがあるので消してはいけません。
マイグレーションファイルは一度rake db:migrate
で実行してしまうと、中身を書き換えて再実行はできません。
rake db:rollback
でデータベースの状態を最新のmigrationファイルを実行する前に戻せます。Active Record
Active RecordはRubyのGemの一種です。このGemはRailsにデフォルトでインストールされており、このGemのおかげでモデルとテーブルをつなぎ合わせられています。そのことによりRailsからテーブルのレコードにアクセスできます。
Actice Recordを利用するにはApplicationRecordというクラスを継承する必要があります。
ApplicationRecordを継承することでallメソッド、newメソッド、saveメソッド、findメソッドなどが利用できるようになります。SQL
データベースに保存されているデータをデータベースに要求するときに使う言語です。
RailsではActive Recordのおかげで簡単にデータを要求することができます。
- 投稿日:2020-05-19T10:08:14+09:00
Deviseで認証メールを手動で送信したい
再送方法
Qiita - deviseの確認メールの実装で困ったとき
RubyDoc - Module: Devise::Models::Confirmableほぼここに書いてあるとおりで、Devise参照先も書いてあるとおりなんですがこれです。
User.find(1).send_confirmation_instructions # manually send instructionsこの操作をするシチュエーション
- メーラー側でなんらかの不具合がありメールが送信されなかった
- Workerが止まってしまいメール送信用のキューをロストした
等が考えられます。
結構運用中に発生しがちで毎回どうやって再送するんだっけ?って調べてたので書きました。以上です。
- 投稿日:2020-05-19T08:41:00+09:00
【備忘録】Rails3ルーティング確認
はじめに
今回はタイトルの通りにRailsにおけるルーティングの確認方法を残します。
触れているシステムのバージョンが古いため、Webブラウザでの確認が出来ずに詰まりました・・・。環境
Rails 3.0.19
docker-compose version 2Dockerコンテナからコマンドで確認する
1. サービス用コンテナを起動する
docker-compose up -d-d:デタッチド・モード: バックグラウンドでコンテナを実行し、新しいコンテナ名を表示
2. railsがインストールされているコンテナに入る(今回はappコンテナ)
docker-compose run app /bin/bashdockerやRailsにバージョンによって、コマンドが変わります。
直近で多く見られるコマンドは以下の通り。docker-compose exec app bash3. ルーティング確認コマンドを実行する
[root@[コンテナID] trunk]# bundle exec rake routes上記コマンドですと全件出力されてしまい見づらいため、grepコマンドを利用すると見やすいです。
[root@[コンテナID] trunk]# bundle exec rake routes | grep [絞り込みたい文字列]参考
- 投稿日:2020-05-19T03:58:13+09:00
Rails で HTTP DELETE メソッドを使える条件
はじめに
Rails では RESTful な設計とするために各種 HTTP リクエストメソッドを使い分けていて、
config/routes.rb
では当たり前に DELETE メソッドを定義すると思います。が、このルーティング、正しく機能するためには条件があります。その条件を満たしていないと正しく動作しません。
結論
jquery-ujs.js
もしくはrails-ujs.js
が読み込まれていることが条件です。これら JavaScript がトリックによって DELETE をエミュレートしています。トリックの正体と有効/無効
一般的にブラウザでは GET と POST しか使えません。DELETE リクエストは送信されないので、当該ルートが発現することはありません。例えば
link_to method: :delete
と書いたとしてもブラウザの素の能力では GET が送信されてしまい、最悪誤動作を引き起こします。そこで前述 JavaScript が上手いことやって「DELETE のつもりでリクエストするんだぜ」というのを伝えることで、DELETE メソッドではないものの DELETE ルートを発現させています。具体的には form オブジェクトを作って「本来の意図は DELETE だよ」というパラメータを添えて POST しています。
そしてこのトリックは普通に
rails new
すれば自動的にお膳立てされ有効になります。が、
rails new --skip-javascript
すると無効になります。JavaScript に依存しているんだから当たり前ですね。そして前述のようにlink_to method: :delete
は GET になってしまうのです。手作業でトリックを有効にする方法
何らかの事情で
rails new --skip-javascript
しなければならない場合に手作業でトリックを有効にする方法は、下記です。各ファイルに各行を追記します。app/assets/javascripts/application.js//= require rails-ujs
app/views/layouts/application.html.erb<%= javascript_include_tag 'application' %>別法あります
ここまでは前置きです。
ここからが本題です。JavaScript を使わなくても DELETE ルートを使うことは出来ます。
button_to method: :delete
です。JavaScript が生成している form を静的に生成すればいいわけです。
より link_to ぽく
button_to では
input type='submit'
が1つ(とinput type='hidden'
が幾つか)の form が生成されますが、class='button_to'
になっています。さらに例えばbutton_to class: :anchor
とするとinput type='submit' class='anchor'
になります。生成される.html<form class="button_to" method="post" action="/logout"> <input type="hidden" name="_method" value="delete" /> <input type="hidden" name="authenticity_token" value="ナイショ" /> <input class="anchor" type="submit" value="LOGOUT" /> </form>なので、下記のような CSS (SCSS) を書いてやれば、機能も見た目も link_to の代わりに使うことが可能です。
app/assets/stylesheets/custom.scssform.button_to { display: inline; input.anchor[type='submit'] { | border-style: none; padding: 0; font-size: 1em; cursor: pointer; background-color: $bg-color; color: $link-color; } }終わりに
もともと --skip-javascript なんて使ってなかったんですが、Rails 6 が Webpacker で yarn や node_modules 必須になってたものの取り急ぎ小さく new したかったので --skip-javascript したら一旦良さそうだったけど logout 出来ず「!?」となって、、、ここに至りました。
静的最高♪
- 投稿日:2020-05-19T02:52:01+09:00
Vue.js+Webpackを導入したRails環境をdockerで構築してみる【part1】
はじめに
学習をする中での備忘録。
やることはタイトル通り。
※注意
これまでバックエンドを1ヶ月半ほど、フロントを3ヶ月半ほど勉強した初学者です。
内容に間違い/不合理な点などある可能性が高いです。
アドバイスや間違いの指摘など頂けると嬉しいです。ステップ1. dockerイメージの構築からRailsサーバ起動まで
まずはdocker+Railsの環境を整える。
・dockerインストール済み
・dbはmysql
・rails:5.2.3
・ruby:2.4.5
・sprocketsは削除せず、アセットパイプラインを使用その他詳しい解説などは省く。
それ用のディレクトリを任意の場所に用意
mkdir test配下に以下の4ファイルを作成
Gemfilesource 'https://rubygems.org' # バージョンは適宜指定 gem 'rails', '5.2.3'DockerfileFROM ruby:2.4.5 RUN apt-get update -qq && apt-get install -y build-essential nodejs RUN mkdir /app WORKDIR /app COPY Gemfile /app/Gemfile COPY Gemfile.lock /app/Gemfile.lock RUN bundle install COPY . /appdocker-compose.ymlversion: '3' services: web: build: . command: bundle exec rails s -p 3000 -b '0.0.0.0' volumes: - .:/app ports: - 3000:3000 depends_on: - db tty: true stdin_open: true db: image: mysql:5.7 volumes: - db-volume:/var/lib/mysql environment: MYSQL_ROOT_PASSWORD: password volumes: db-volume:Gemfile.lock# 空ファイル
Railsプロジェクトを作成
/testdocker-compose run web rails new . --force --database=mysql --skip-turbolinks
forceでGemfile等を上書き、turbolinksは使わないのでskip
dockerイメージを再構築
/testdocker-compose build
→Gemのインストールや作成されたRailsプロジェクトのファイル群をコンテナ内に取り込むために必要。
database.ymlを編集
test/config/database.yml... default: &default adapter: mysql2 encoding: utf8 pool: 5 username: root # 以下二行をmysql用に書き換え password: password host: db development: <<: *default database: app_development ...passwordはMYSQL_ROOT_PASSWORD環境変数の"password"
hostはMySQLサーバのコンテナのサービス名である"db"コンテナの起動と確認
・コンテナ起動
/testdocker-compose up
起動が確認できたら一旦停止してください。
データベースを作成
/testdocker-compose run web bundle exec rails db:create
ローカルサーバへのアクセス確認
再度コンテナを起動し、ローカルサーバにアクセスする
/testdocker-compose up
→http://localhost:3000 へ飛びRailsサーバの起動を確認
ステップ2. Webpack+Vue.jsの導入
Webpackとパッケージのインストール
まずはRailsのルートディレクトリ(test)に/frontendを作成、移動
/testmkdir frontend cd frontend
package.jsonを作成(設定はデフォルト値)
/frontendyarn init
必要なパッケージ達をインストール
/frontendyarn add vue webpack webpack-cli vue-loader vue-template-compiler css-loader style-loader babel-loader @babel/core @babel/preset-env sass-loader node-sass --save
webpack.config.jsの作成
/frontend/config/development/webpack.config.js
/frontend/config/production/webpack.config.js
の2つを作成。/frontendmkdir config mkdir config/development mkdir config/production touch config/development/webpack.config.js touch config/production/webpack.config.js
エントリーポイントとなるフォルダの作成
/frontend/src/javascripts/entry.js
を作成します。/frontendmkdir src mkdir src/javascripts touch src/javascripts/entry.js
各種設定ファイルの編集
・development環境用の設定ファイルを編集
※ test/app/assets/javascript配下に出力されるようoutputパスを書き換えてください/frontend/config/development/webpack.config.jsconst VueLoaderPlugin = require('vue-loader/lib/plugin'); module.exports = { devtool: 'inline-source-map', mode: 'development', entry: { webpack: './src/javascripts/entry.js' }, output: { // /app/assets以下に出力するよう、path:のキーを絶対パスで書き換え path: 'ここを書き換え/test/app/assets/javascripts', filename: '[name].js' }, module: { rules: [ { test: /\.js$/, exclude: /node_modules/, loader: 'babel-loader' }, { test: /\.vue$/, loader: 'vue-loader' }, { test: /\.css$/, use: ['vue-style-loader', 'css-loader'] }, { test: /\.scss$/, use: [ 'vue-style-loader', 'css-loader', { loader: 'sass-loader', }, ], } ] }, resolve: { extensions: ['.js', '.vue'], alias: { vue$: 'vue/dist/vue.esm.js', }, }, plugins: [ new VueLoaderPlugin() ] }・production環境用の設定ファイルを編集
※ development同様、outputパスを書き換えてください/frontend/config/production/webpack.config.jsconst VueLoaderPlugin = require('vue-loader/lib/plugin'); module.exports = { mode: 'production', entry: { webpack: './src/javascripts/entry.js' }, output: { // 書き換え path: '書き換え/test/app/assets/javascripts', filename: '[name].js' }, module: { rules: [ { test: /\.js$/, exclude: /node_modules/, loader: 'babel-loader', options: { presets: [ "@babel/preset-env" ] } }, { test: /\.vue$/, loader: 'vue-loader' }, { test: /\.css$/, use: ['vue-style-loader', 'css-loader'] }, { test: /\.scss$/, use: [ 'vue-style-loader', 'css-loader', { loader: 'sass-loader', }, ], } ] }, resolve: { extensions: ['.js', '.vue'], alias: { vue$: 'vue/dist/vue.esm.js', }, }, plugins: [ new VueLoaderPlugin() ], }ビルド用コマンドの追加
frontend/package.jsonに
以下を追記。frontend/package.json"scripts": { "release": "webpack --config config/production/webpack.config.js", "build": "webpack --config config/development/webpack.config.js", "watch": "webpack --watch --config config/development/webpack.config.js" },ここまででVueを動かす環境と、Webpackを用いてバンドルファイルをビルドする準備が完了。
最後に、動作確認のため以下の作業を行う。ステップ3. ここまでの動作確認
必要なファイルの準備
適当なコントローラを作る
/frontendcd .. docker-compose run web bundle exec rails g controller tests
コントローラとルートを編集
/app/controllers/tests_controller.rbdef index end/config/routes.rb# 追加 resources :testsビューを作成
/app/views/tests/index.html.erb<div id="app"> <p>{{name}}</p> </div>Vueを書く
/frontend/src/javascripts/entry.jsimport Vue from 'vue'; document.addEventListener("DOMContentLoaded", function(event) { new Vue({ el: '#app', data: { name: '動作しています' } }); });ビルドの実行
(frontend配下に移動)
/frontendyarn run build
動作確認
http://localhost:3000/tests にアクセスし、'動作しています'と表示されていれば完了。
- 投稿日:2020-05-19T01:25:29+09:00
【Rails】date_selectのクラス指定
最初に
hamlでdate_selectを使用した際クラスを付与できなかったため、クラス指定の仕方を備忘録として残します。
date_selectとは
https://gyazo.com/29cf6b960c4c2391a24e70069a9d8659
こんな感じでドロップダウン形式の生年月日のフォームを自動で生成してくれるのがdate_select。ちなみにデフォルトだとこんな感じ。
https://gyazo.com/4100a51de9a365f337e142bad0d7507b最初form_forのselect_boxを使用しており、年、月、日と3つフォームを生成してオプションつけて、データをまとめて保存する様にして、、、と生年月日のフォームを実装するまでに時間がかかったため、
早く知っておきたかった。。(泣)
https://gyazo.com/0bd5ca777d38932db77858cd64f87448
今後はこの便利すぎるdate_selectを使用していきます。使用方法
collection_select(オブジェクト名, メソッド名, 要素の配列, value属性の項目, テキストの項目 [, オプション or HTML属性 or イベント属性])手順
1.コードの記載(今回はコントローラーで@adreess変数に空のハッシュを代入済み、カラムはbirthdayを想定します。)
html.haml= form_for (@address) do |f| = f.date_select :birthdayこれでフォーム自体は使用できます。
2.オプションの追加
html.haml= form_for (@address) do |f| = f.date_select :birthday, use_month_numbers: true, start_year: 1970, end_year: Time.now.year, prompt:"--"use_month_numbers: true, → 月の表示を数字に。デフォルトだと英語表記。
start_year: 1970, → 選択肢として何年からスタートするかを指定。デフォルトだと10年前からになる。
end_year: Time.now.year, → 選択肢の終わりの年を現在に指定。
prompt:"--" → セレクトボックスのデフォルトで表示される文字を”ーー”に指定。デフォルトだと現在の日付が適用される。(これ個人的におすすめ!)
3.クラスの指定
html.haml= form_for (@address) do |f| = f.date_select :birthday, use_month_numbers: true, start_year: 1970, end_year: Time.now.year, prompt:"--", class:"main__box__bottom__content__group3__box__barthday__box"これでクラスの付与完了!と思いきや、cssが反応しない。検証で調べてみるとクラスが指定されていないということがわかった。最初これでなぜクラスが当たらないのか謎でした。
ソースコードを調べてると、option(use_month_numbers:やprompt:)は第3引数に設定し、html_options(classなどのhtml/css)は第4引数に設定するようです。
https://railsdoc.com/form
要は指定する場所が決められているということで、上記の場合だと第3引数でクラス指定をしていることになり反映されなかったのが原因です。なので第3引数と第4引数を{}で別々に括ると、
html.haml= form_for (@address) do |f| = f.date_select :birthday, {use_month_numbers: true, start_year: 1970, end_year: Time.now.year, prompt:"--"}, {class:"main__box__bottom__content__group3__box__barthday__box"}これでクラスが付与されました!
ちなみにオプションなし、クラスのみ指定(第4引数のみ指定)したい場合は、html.haml= f.date_select :birthday, {}, {class:"main__box__bottom__content__group3__box__barthday__box"}カラムと第4引数の間に空の{}を設けることによりクラスが付与されます!
参考文献
・https://railsdoc.com/form
・https://qiita.com/nakanoyoshiki/items/e87a6238f8febbeb208a
- 投稿日:2020-05-19T00:12:39+09:00
Rails + Vue.js でページネーション付きのテーブルを簡単作成
概要
- 業務でページネーション機能を実装したので、ほとんどそのままの構成で手順を紹介
- 使用した技術は
kaminari(Rails)
とVuetify(Vue.js)
- api経由でデータを取得し、ページネーション付きで表示する
- ソースコード
Railsの開発環境は特に説明しないが、以下の記事を参考に構築しました
Rails 6 + MySQL on Dockerの環境を秒速で構築するBookモデルの定義とサンプルデータの作成
今回はデータベースに保存したBookの一覧をapiで取得します
まずはBookモデルを作成しましょう# マイグレーションファイルの作成 bin/rails g model Book name:string # マイグレーションを実行し、Booksテーブルを作成 bin/rails db:migrate
db/seeds.rb
を編集しサンプルデータを作成db/seeds.rb100.times do |n| name = "example-#{n+1}" Book.create!(name: name) endseedを実行
bin/rails db:seedこれでBookレコードが100件作成されました
kaminariのインストールとBook一覧取得用apiの作成
Bookテーブルからデータを取得する際にkaminariを使用します
kaminariをインストールします
https://github.com/kaminari/kaminariGemfile# kaminariを追記 gem 'kaminari'# kaminariのインストール。インストール完了後にサーバーを再起動させましょう bundle
app/controllers/api/books_controller.rb
を作成し、Book一覧を返すapiを実装しますapp/controllers/api/books_controller.rbclass Api::BooksController < ApplicationController def index # 表示するページの番号を指定 page = params[:page] || 1 # 1ページあたりの表示件数を指定 per = params[:per] || 10 # ページネーションで指定レコードを取得 books = Book.page(page).per(per) # ページネーションした時の全ページ数 total_pages = books.total_pages # レスポンスデータの定義 response = { # bookレコードはidとnameフィールドのみ表示する books: books.select(:id, :name), total_pages: total_pages } # json形式でレスポンスを返却 render json: response end endconfig/routes.rbRails.application.routes.draw do # Book一覧取得用のパス get '/api/books', to: 'api/books#index' # Book一覧表示用のパス get '/books', to: 'books#index' end
http://localhost:3000/api/books
にアクセスすると次のようなjsonが返ってきますBook一覧表示ページの作成
Book一覧表示用のページを作成します
Vuetifyのv-data-tableコンポーネント
とv-pagination
を使い、Axiosでapiを叩きます
※ ここでは面倒を避けるためCDN経由で環境構築をしてあります。適宜ご自身の環境に合わせた環境構築を行なってくださいapp/views/layouts/application.html.erb<!DOCTYPE html> <html> <head> <title>AppName</title> <%= csrf_meta_tags %> <%= csp_meta_tag %> <%# CDNで Vue.js, Vuetify, Axios をインストールする %> <link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet"> <link href="https://cdn.jsdelivr.net/npm/@mdi/font@4.x/css/materialdesignicons.min.css" rel="stylesheet"> <link href="https://cdn.jsdelivr.net/npm/vuetify@2.x/dist/vuetify.min.css" rel="stylesheet"> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, minimal-ui"> <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %> <%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %> </head> <%# ここも追加 %> <script src="https://cdn.jsdelivr.net/npm/vue@2.x/dist/vue.js"></script> <script src="https://cdn.jsdelivr.net/npm/vuetify@2.x/dist/vuetify.js"></script> <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/es6-promise@4/dist/es6-promise.auto.min.js"></script> <body> <%= yield %> </body> </html>app/views/books/index.html.erb<div id="app"> <v-app> <v-container> <h2>Book一覧</h2> <%# テーブル作成用コンポーネント %> <v-data-table :headers="headers" :items="items" :items-per-page="itemsPerPage" hide-default-footer /> </v-container> <%# ページネーション表示用コンポーネント %> <v-pagination v-model="currentPage" :length="totalPages" <%# ページを変更した時にfetchBooksを呼び出す %> @input="fetchBooks" /> </v-ap> </div> <script> new Vue({ el: "#app", vuetify: new Vuetify(), data() { return { // テーブルのヘッダー情報。valueの値がレコードのフィールド名に紐付く headers: [ { text: "ID", value: "id"}, { text: "本の名前", value: "name"}, ], // テーブルのボディー情報。apiで取得したBook一覧をここに格納する items: [], // 表示するページの番号 currentPage: 1, // 1ページあたりの表示件数 itemsPerPage: 10, // ページネーションした時の全ページ数 totalPages: null, } }, methods: { // AxiosでBook取得apiにリクエストを送る fetchBooks() { const url = `/api/books?page=${this.currentPage}?per=${this.itemsPerPage}`; axios .get(url) .then(res => { // Book一覧を取得 this.items = res.data.books; // ページネーションした時の全ページ数を取得 this.totalPages = res.data.total_pages; }) } }, // DOMが作成された時に fetchBooks を呼び出す created() { this.fetchBooks() }, }); </script>
http://localhost:3000/books
これでページネーションは完成です
以下のようにページを切り替える度に表示が変わればOKです!