20211010のRailsに関する記事は16件です。

メソッドによるコード省略!

コントローラーに同じ記述があった際、まとめる為の記述を解説します! 下記の例を参考にして、before_actionを使用して、メソッドとしてまとめます! ①.before_actionメソッドを使用して、同じコードをまとめる! 例として、下記の記述では, @eat = Eat.find(params[:id])が、繰り返し使用されています! class eatsController < ApplicationController def index @eats = Eat.all end def edit @eat = Eat.find(params[:id]) end def show @eat = Eat.find(params[:id]) end private def eat_params params.require(:eat).permit(:name, :image, :text) end end この記述をまとめるために、before_actionを使用して、メソッドとしてまとめます! before_actionを使用する際の書き方は、以下の通りです! class コントローラ名 < ApplicationController before_action :処理させたいメソッド名 before_actionを使用すると、コントローラで定義されたアクションが実行される前に、共通の処理を行うことができます! 更に、resourcesと同様にonlyやexceptなどのオプションを使用することによって、どのアクションの実行前に、処理を実行させるかなど制限が可能です! ②.onlyオプションとexceptオプション! onlyは、そのアクションだけを適用させると言う意味です! exceptは、そのアクションだけを取り除くと言う意味です! 使う際は、条件にあった方を使用します! 今回はeditとshowだけを取り除かないで処理させたいので、onlyを使用します! 下記のように記述します! class eatsController < ApplicationController before_action :set_eat, only: [:edit, :show] def index @eats = Eat.all end def edit end def show end private def eat_params params.require(:eat).permit(:name, :image, :text) end def set_eat @eat = Eat.find(params[:id]) end end before_action :set_eat, only: [:edit, :show]と記述することで、 editアクションとshowアクションが実行される前に、set_eatに定義されている処理が実行されるようになります! つまり、editアクションとshowアクションが実行される前に、@eat = Eat.find(params[:id])が実行されるということです! このように、before_actionを用いることで、重複した記述を1つのメソッドにまとめることができます! ③.まとめ ちなみに、set_eatの命名の部分はなんでもOKです! 基本的に他の人が見てわかるような物であれば、全然ありです! 例として、double_eatやtwo_eatなどでも大丈夫です! 個人的に最初はこの部分の名前は、なぜこうなっているのだろう? と言うことが多々ありましたが、なんでもいいと言うのが1番困るんですよね汗 決まりとかある方がわかりやすいと思いますので^^; これは完全に慣れだと思いますが、こう言う箇所も覚えて行こうと思います! 何か説明で間違っていたらご指導お願い致します(_ _)
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Railsでフォロー機能を作成する方法【改】

前提 ☆必要なテーブル ・usersテーブル ・relationshipsテーブル(中間テーブルです) ☆ポイント ・アソシエーションが普通の「多対多」とは違う事(ちゃんと解説します!!) ・Userモデル、usersテーブルは作っている前提で説明します!! 流れ ⓵relationshipsモデルを作る ⓶relationshipsのマイグレーションファイルを編集&実行 ⓷userモデルとrelationshipsモデルにアソシエーションを書く ⓸userモデルにフォロー機能のメソッドを書く ⓹relationshipsコントローラを作成&編集 ⓺フォローボタン(form_for)をviewに設置 ⓻ルーティングを書く!終了! ⓵relationshipsモデルを作る 今回はuserとtweetsの関係性とは違い、userテーブル同士で「多対多」の関係を作ります。何故ならフォロワーもまたuserだからです。イメージとしてはuserテーブル同士をrelationshipsという中間テーブルでアソシエーションを組むイメージです! まずは、realtionshipsモデルを作っていきます。 ターミナル $ rails g model Relationship ⓶relationshipsのマイグレーションファイルを編集&実行 下記のように編集してください。 db/migrate/年月日時_create_relationships.rb class CreateRelationships < ActiveRecord::Migration[5.0] def change create_table :relationships do |t| t.references :user, foreign_key: true t.references :follow, foreign_key: { to_table: :users } t.timestamps t.index [:user_id, :follow_id], unique: true end end end しっかり解説します。まず、relationshipsテーブルのカラムは カラム タイプ オプション user_id integer foreign_key: true follow_id integer foreign_key:{to_table: users} となります。 そもそも、relationshipsテーブルは中間テーブルなので、user_idとfollow_idは「t.references」で作ってあげる必要があります。 そして、外部キーとしての設定をするためにオプションは「foreign_key: true」とします。 でも!注意したいのがfollow_idの参照先のテーブルはusersテーブルにしてあげたいので、{to_table: :users}としてあげてます。 foreign_key: trueにすると存在しないfollowsテーブルを参照してしまうからです。 t.index [:user_id, :follow_id], unique: true は、 user_id と follow_id のペアで重複するものが保存されないようにするデータベースの設定です! これは、あるユーザがあるユーザをフォローしたとき、フォローを解除せずに、重複して何度もフォローできてしまうような事態を防いでいるだけです。 終わったら、マイグレーションファイルを実行してください! ターミナル $ rails db:migrate ⓷relationshipsモデルとuserモデルにアソシエーションを書く まずは、relationshipsモデルにアソシエーションを書いていきます! app/models/relationship.rb class Relationship < ApplicationRecord belongs_to :user belongs_to :follow, class_name: 'User' validates :user_id, presence: true validates :follow_id, presence: true end class_name: ‘User’ と補足設定することで、Followクラスという存在しないクラスを参照することを防ぎ、User クラスであることを明示しています。 要は「followモデルなんて存在しないので、userモデルにbelongs_toしてね!」って事です。 さらに、バリデーションも追加してどちらか一つでも無かった場合保存されないようにします! 次にuserモデルにアソシエーションを書いていくのですが、、、 ここが山場です。理解しにくい部分なのでしっかり解説します。 app/models/user.rb class User < ApplicationRecord has_many :relationships has_many :followings, through: :relationships, source: :follow has_many :reverse_of_relationships, class_name: 'Relationship', foreign_key: 'follow_id' has_many :followers, through: :reverse_of_relationships, source: :user end 1行目のhas_many :relationshipsは大丈夫ですね。 2行目のhas_many :followingsとありますが、これはいまこのタイミングで命名したものです!followingクラス(モデル)を架空で作り出しました。 勿論、followingクラス(モデル)なんて存在しません。 なので、補足を付け足す必要があります。 through: :relationships は「中間テーブルはrelationshipsだよ」って設定してあげてるだけです。 source: :followとありますが、これは 「relationshipsテーブルのfollow_idを参考にして、followingsモデルにアクセスしてね」って事です。 結果として、user.followings と打つだけで、user が中間テーブル relationships を取得し、その1つ1つの relationship のfollow_idから、「フォローしている User 達」を取得しています。 次にフォロワー(フォローされているuser達)をとってくるための記述をします。 結論から言うとフォローの逆をしてあげればいいのです。 3行目のhas_many :reverse_of_relationshipsは has_many :relaitonshipsの「逆方向」って意味です。 これはこのタイミングで命名したものです。勿論reverse_of_relationshipsなんて中間テーブルは存在しません。なので、これも補足を付け足してやります。 class_name: 'Relationship'で「relationsipモデルの事だよ〜」と設定してあげます。 次のforeign_key: 'follow_id'ですが、これ何のこっちゃ分からないと思います。 これ、「relaitonshipsテーブルにアクセスする時、follow_idを入口として来てね!」っていう事です。 ちょっと1行目のhas_many :relationshipsを思い出してください。実はこれ has_many :relationships, foreign_key: 'user_id' って意味なんです! 要はこれもuser_idを入り口にしてね、っていうだけです! user_idを入口として、relationshipsテーブルという家に「おじゃましま〜す」と入って、follow_idという出口(=source: :follow)から出て、followingsテーブルからフォローしている人のデータをとってくるイメージです! foregin_key = 入口 source = 出口 というのを念頭においてください。 これで100%理解出来るはずです。 4行目に行きます。has_many :followersもこのタイミングで命名してます。勿論、followersなんてクラス存在しません。 through: :reverses_of_relationshipで「中間テーブルはreverses_of_relationshipにしてね」と設定し、 source: :userで「出口はuser_idね!それでuserテーブルから自分をフォローしているuserをとってきてね!」と設定してます。 ⓸userモデルにフォロー機能のメソッドを書く userモデルにフォロー機能のメソッドを書いておきます。 これやった方が後々めちゃくちゃ楽です。 app/models/user.rb class User < ApplicationRecord has_many :relationships has_many :followings, through: :relationships, source: :follow has_many :reverse_of_relationships, class_name: 'Relationship', foreign_key: 'follow_id' has_many :followers, through: :reverse_of_relationships, source: :user def follow(other_user) unless self == other_user self.relationships.find_or_create_by(follow_id: other_user.id) end end def unfollow(other_user) relationship = self.relationships.find_by(follow_id: other_user.id) relationship.destroy if relationship end def following?(other_user) self.followings.include?(other_user) end end 注意すべき点は、フォローが自分自身ではないか?とすでにフォローしていないか?の2点です!!!! def follow では、unless self == other_user によって、フォローしようとしている other_user が自分自身ではないかを検証しています。self には user.follow(other) を実行したとき user が代入されます。つまり、実行した User のインスタンスが self です! 更に、self.relationships.find_or_create_by(follow_id: other_user.id) は、見つかれば Relation を返し、見つからなければ self.relationships.create(follow_id: other_user.id) としてフォロー関係を保存(create = new + save)することができます。これにより、既にフォローされている場合にフォローが重複して保存されることがなくなります! def unfollow では、フォローがあればアンフォローしています。また、relationship.destroy if relationshipは、relationship が存在すれば destroy します!if文はこのように書けます! def following? では、self.followings によりフォローしている User 達を取得し、include?(other_user) によって other_user が含まれていないかを確認しています!含まれている場合には、true を返し、含まれていない場合には、false を返します! ⓹relationshipsコントローラを作成&編集 relationshipsコントローラ作ってください。 ターミナル $ rails g controller relationships 下記のように書いていきます。 app/controllers/relationships_controller.rb class RelationshipsController < ApplicationController before_action :set_user def create following = current_user.follow(@user) if following.save flash[:success] = 'ユーザーをフォローしました' redirect_to @user else flash.now[:alert] = 'ユーザーのフォローに失敗しました' redirect_to @user end end def destroy following = current_user.unfollow(@user) if following.destroy flash[:success] = 'ユーザーのフォローを解除しました' redirect_to @user else flash.now[:alert] = 'ユーザーのフォロー解除に失敗しました' redirect_to @user end end private def set_user @user = User.find(params[:follow_id]) end end ⓺フォローボタン(form_for)をviewに設置 app/views/relationships/_follow_button.html.erb <% unless current_user == user %> <% if current_user.following?(user) %> <%= form_for(current_user.relationships.find_by(follow_id: user.id), html: { method: :delete }) do |f| %> <%= hidden_field_tag :follow_id, user.id %> <%= f.submit 'Unfollow', class: 'btn btn-danger btn-block' %> <% end %> <% else %> <%= form_for(current_user.relationships.build) do |f| %> <%= hidden_field_tag :follow_id, user.id %> <%= f.submit 'Follow', class: 'btn btn-primary btn-block' %> <% end %> <% end %> <% end %> ※hamlで書くと下のような感じになります! - unless current_user == user - if current_user.following?(user) = form_for(current_user.relationships.find_by(follow_id: user.id), html: { method: :delete }) do |f| = f.hidden_field :follow_id, value: user.id = f.submit 'フォロー中', class: 'follow-now' - else = form_for(current_user.relationships.build) do |f| = f.hidden_field :follow_id, value: user.id = f.submit 'フォロー', class: 'follows' あとは部分テンプレートでご自身の好きなところに置いちゃって下さい!!! app/views/users/show.html.erb <%= render 'relationships/follow_button', user: @user %> みたいな感じで! ⓻ルーティングを書く!終了! config/routes.rb Rails.application.routes.draw do resources :relationships, only: [:create, :destroy] end ありがとうございました!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【自分用メモ】Ruby on Rails のwhereメソッドの条件を文字列だけで構成するのは危険らしい!

Webサービスを作成している中で「あるカラムに値が存在しているレコードだけ取得したいなー」って思いました。 上記では「selling_day」に値が設定されているものだけを取得したいです。 値が設定されていないだったらRailsのwhereメソッドに「selling_day:nil」みたいな感じで取得してあげれば良いかと思いますが stocks_controller.rb @stock = Stock.where(selling_day:nil) 何かしら値が設定されている場合どのように取得して来れば良いのでしょうか 下記の通り取得してくれば良いと考えました。 stocks_controller.rb @stock = Goal.where('selling_day like ?','%') ただ、文字列だけで条件を指定するとSQLインジェクションのリスクがあるようです。 なので下記のような感じで「selling_day」に値が設定されているかどうかのカラムを持たせました そしてハッシュ指定で取得してくるようにしました。 stocks_controller.rb @stock = Stock.where(sold:true) ちゃんと調べることの大切さを実感しました 下記サイトを参考にしました。 https://railsguides.jp/active_record_querying.html
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Ruby on Rails のwhereメソッドの条件を文字列だけで構成するとはSQLインジェクションの危険がある。

Railsのwhereメソッドの条件を文字列だけで構成することは危険なようです。 Webサービス作成する中で「あるカラムに値が設定されているレコードを取得する」為、下記のようにコーディングしていました。 値が設定されていないだったらRailsのwhereメソッドに「selling_day:nil」みたいな感じで取得してあげれば良いかと思いますが stocks_controller.rb @stock = Goal.where('selling_day like ?','%') ただ、文字列だけで条件を指定するとSQLインジェクションのリスクがあるようです。 具体的には stocks_controller.rb @stock = Goal.where("selling_day = '#{params[:day]}'") みたいに書くとparams[:day]に悪意のある文字列を設定され、認証をすり抜けるリスクがあります。 下記のように条件をハッシュ値で指定するか、配列で指定するようにするとリスク回避できるようです。 stocks_controller.rb @stock = Stock.where(sold:true) 下記サイトを参考にしました。 https://railsguides.jp/active_record_querying.html https://railsguides.jp/security.html#sql%E3%82%A4%E3%83%B3%E3%82%B8%E3%82%A7%E3%82%AF%E3%82%B7%E3%83%A7%E3%83%B3
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Rails6】cocoonによる動的フォーム作成時に注意すべき点。「"accepts_nested_attributes_for"」、「"can't be blank"」

cocoonを用いて、動的に変化するフォームを作成した際にハマったことを記します。 cocoonの導入は以下の記事を参考にしました。 ・【Rails】cocoonを用いて親子孫関係のテーブルに複数のデータを同時保存する方法 - Qiita ・【Rails6】cocoonを使った動的フォーム入力画面の作り方 - Qiita 問題概要  以下のような3つのモデルを作成し、関連づけたと仮定します。 関係 モデル名 親 Parent 子 Child 孫 Grandchild 上記記事を参考にしながらフォームを作成し、できたフォームよりデータを送信したら、以下のようなバリデーションに引っかかりました。 Child Grandchild child can't be blank Child Parent can't be blank 原因 各モデルのvalidationの記述に問題がありました。 parent.rb has_many :children, dependent: :destroy accepts_nested_attributes_for :children child.rb belongs_to :parent has_many :grandchildren, dependent: :destroy accepts_nested_attributes_for :grandchildren validates :parent_id, presence: true grandchild.rb belongs_to :child validates :child_id, presence: true accepts_nested_attributes_forによって、親作成時にその子供のデータも同時に作成できるようになります。 このとき、childのparent_idやgrandchildのchild_idは各データの保存と同時に、そのデータのidが格納されます。 従って、データを保存し終わるまでは各フォームから、 _children_fields.html.erb <%= hidden_field_tag :parent_id, @parent.id %> _grandchildren_fields.html.erb <%= hidden_field_tag :child_id, @child.id %> のようにインスタンス変数から直接値を代入するよう試みても、各データは保存される前でありidを持たないため、バリデーションのpresenceに引っかかってしまいます。 解決策 方法は非常にシンプルで、validates :child_id, presence: trueとvalidates :parent_id, presence: trueを削除します。 おわりに accepts_nested_attributes_forのような1行で大きな効果を有するコードは、その動作を理解できていないと、予想外のエラーの原因になります。便利なものほどその本質の理解を心がけようと思いました。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

RailsアプリでTwitter認証実装中にルーティングエラーになった時の解決法

色々な記事を見ながらRailsアプリにomniauth-twitterを使用してTwitter認証を実装していたのですが、どういうわけかかなりハマりました。 最終的にうまく行ったのでその方法を備忘録がてら記載しておきます。 前提 諸々のバージョン 使用しているPC: MacBook Air (M1, 2020) Railsバージョン: 6.1.4.1 Rubyバージョン: ruby 2.7.2p137 (2020-10-01 revision 5445e04352) [arm64-darwin20] omniauthバージョン: 2.0.4 deviseは使用していません。 最終的に参考にした記事 ハマったこと omniauth-twitterを使用して認証を実装後、/auth/twitterにアクセスするとルーティングエラーになる 原因 (おそらく)omniauthバージョンが2以上なのにそれ用の対策をしていなかったこと 最終的にこうしたらローカルでもうまくいった 基本的な部分は参考の1番目の記事の通りに実装していますので省略します。 そこに以下を追加で実装しました。(詳細は参考の二番目の記事をご参照ください) 1.Gemfileにomniauth-rails_csrf_protectionを追加する gem 'omniauth-rails_csrf_protection' gem 'omniauth-twitter' 2./auth/twitterにはPOSTでアクセスする xxx.html.erb <%= link_to '/auth/twitter', method: :post do %>認証<% end %> おかしな点ありましたらコメント等で指摘いただけると幸いです。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Rails6+mysql5.7+Docker+AWSで作成したポートフォリオの概要

はじめに この記事では私が作成したwebアプリのポートフォリオの解説をします。 作成したポートフォリオは下記になります。↓ 作成したポートフォリオ 自己紹介 年齢:27歳 職業:地元企業のエンジニアリング部に所属 住居:地方 趣味:映画、音楽、英語(TOEIC:770)、バレーボール 映画はSFが好きで特にスターウォーズが好きです(アイコンはマンダロリアン)。英語の勉強も兼ねて英語で鑑賞するようにしています。 大学時代は軽音部に所属しており音楽は今でもよく聴きます。 中高、社会人とバレーボールを続けており、春高やVリーグは今でもチェックしています(制作背景につながります)。 制作背景 私は中学生〜高校生、社会人とバレーボールを続けています。 社会人になってバレーボールチーム「forza-kanazawa」を立ち上げましたが、なかなか人が集まらず困難していました。そこで少しでも多くの人にチームの事を知ってもらおうとこのアプリを制作しました。 機能一覧 チームメンバーからのヒアリングにより以下の要望があり、機能として実現させました。 ログイン機能 管理者のみログイン機能を使用します。ログインすることで後述の投稿機能を利用できます。 投稿機能(actiontext,Ajax通信, 画像アップロード先 S3,modal形式) 記事は、「タイトル」「サムネ」「内容」「カテゴリ」が追加できます。 Ajaxを実装することでページ遷移なしでの投稿、編集することができます。 カレンダー機能(GoogleCalenderAPI) カレンダーはFullCalenderを導入し、GoogleCalenderAPIを使い同期させています。GoogleCalenderAPIから日本の祝日、練習日を取得します。 メール機能(ActionMailer) 問い合わせメールを管理者に送れるように、Action Mailerを導入しました。Loadingを実装することでユーザが待ち時間をわかるようにしています。 使用技術一覧 フロントエンド HTML/CSS JavaScript/jQuery Bootstarp 4.50 バックエンド Ruby (3.0.0) Ruby on Rails (6.1.3) MySQL (5.7) RSpec インフラ その他 AWS (EC2/Elastic IP/S3/RDS/VPC/IAM/ALB/ACM/Route53/Cloudfront) Nginx/puma Capistrano Git/GitHub VScode Docker/docker-compose ER図 インフラ構成図 工夫した点 UI/UX サイトに訪れるユーザがコンテンツを閲覧する時に迷わないように極力シンプルな構成を心がけました。 投稿のしやすさを意識しmodal表示で投稿できるようにしました。 GoogleCalenderAPIを使用することで日程管理をしやすくしました。 メールの送信時間がわかるようにJavascriptでloadingアニメーションを実装しました。 環境・技術 コードは「Git」で管理し、こまめに「GitHub」にプッシュしてバージョン管理を行いました。ブランチを切って作業しMasterブランチにマージするなど、チーム開発も意識しました。 実際の開発を想定し、Rspecでテストコードを記載いたしました。 実際の開発を想定し、ローカル環境での開発を「docker」と「docker-compose」の仮想環境に切り替えました。 苦労した点 FullCalender,GoogleCalenderAPIの利用 カレンダーを導入するためにFullCalender(ライブラリ)を導入しましたが、最新版ではjQueryが使用できずPure JavaScriptで実装しました。ライブラリの公式documentを読みながら進めることに非常に時間がかかりました。また、外部APIとしてGoogleCalenderAPIを使用しましたが初めてAPIを扱ったため、ここでも時間がかかりました。 dockerの利用 dockerを導入する上で、前提としてLinuxに関する基礎知識は必要不可欠です。したがって、まずLinuxへの基礎的理解を深める段階で時間がかかりました。 SQLに関する理解 RailsではActiveRecordがmodelに適用されるおかげで、簡単なクエリは直感的に書くことができますが、初学者にとってはこれがブラックボックス化してしまいます。実際に中間テーブルを用い、少し複雑なクエリを書くときに私は詰まってしまいました。SQLの基礎本を読み理解しながら進めることに時間がかかりました。 所感 最後にアプリ制作を通し感じたことを書こうと思います。 まず、基礎的理解を深めることの大切さです。私の場合は、まず書籍で理解を深めたあとに取り掛かるほうがスムーズに進めることができました。また、公式ドキュメントを読むことも大切だと思いました。どんな場合でも公式ドキュメントが一番正確な一次情報となるからです。公式ドキュメントは基本英語ですので今のうちに慣れておく必要があると思いました。 今後も継続して勉強を続けたいと思います! ご覧いただきありがとうございました!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【CircleCI】『Unable to find gem rubocop-discourse; is the gem installed? Gem::MissingSpecError』が出てRuboCopが失敗する際の解決方法

はじめに 本記事では、CI(RuboCop、RSpec)のみ動作させています。 設定ファイルの細かい説明については、分かりやすい記事がたくさんあるのでそちらにお任せします。 参考にさせていただいた記事↓ 最後に私の.circleci/config.ymlの設定ファイルを参考までに記載します。 CircleCI上でRuboCopがエラーになる CircleCIでRuboCopを動かすと次のようなエラーが発生しました。 Unable to find gem rubocop-discourse; is the gem installed? Gem::MissingSpecError ...(以下ディレクトリ/ファイル名の羅列) rubocop-discourseが見つからないと言われています。 ローカルではrubocop-discourseがなくても問題なく動いているのになぜ.. 解決方法1 言われた通りに、Gemfileに追記し、bundle installを実行。 Gemfile gem 'rubocop-discourse' rubocop-discourseのGitHubを確認しても、情報が少なく何をしているGemなのかはよく分かりませんでした。(discorseの意味から、rubocopとやりとりするために必要なGemなのではないかと思われます。ローカル環境とCircleCI環境ではファイル構成に違いがあるため、それが原因でエラーが起こっているんでしょうか...) GitHubに記載のある通り.rubocop.ymlに下記を追記しました。 .rubocop.yml inherit_gem: rubocop-discourse: default.yml 解決方法2 CircleCIを動かすと、今度はエラー内容が変わりました。 Error: RuboCop found unsupported Ruby version 2.4 in `TargetRubyVersion` parameter (in vendor/bundle/ruby/2.6.0/gems/msgpack-1.4.2/.rubocop.yml). 2.4-compatible analysis was dropped after version 1.12. vendor以下の.rubocop.ymlでRubyのバージョンがサポート外だよ〜というような内容が記述されています。 .rubocop.ymlのExcludeにvendor以下を追記します。 .rubocop.yml AllCops: TargetRubyVersion: 2.6.7 Exclude: - 'vendor/**/*' 再度CircleCIを起動させると無事に動かすことができました!! 最後に 私の場合は解決方法1・2のどちらかでも欠けているとエラーが出てしまいました。 また、参考までに最終的なCircleCIの設定ファイルを記載しておきます。 基本的には「はじめに」で参考にさせていただいた記事に則っています。 JavaScriptを読み込むために、yarnが必要なため、その部分を追記している点が主な変更点かと思います。 yml.circleci/config.yml version: 2.1 jobs: build: docker: - image: circleci/ruby:2.6.7-node-browsers environment: - BUNDLER_VERSION: 2.2.29 - RAILS_ENV: 'test' - image: circleci/mysql:8.0 environment: - MYSQL_ALLOW_EMPTY_PASSWORD: 'true' working_directory: ~/repo steps: - checkout - restore_cache: keys: - v1-dependencies-{{ checksum "Gemfile.lock" }} - v1-dependencies- - run: name: install dependencies command: | gem install bundler -v 2.2.29 bundle install --jobs=4 --retry=3 --path vendor/bundle - run: yarn install #ここを追記 - save_cache: paths: - ./vendor/bundle key: v1-dependencies-{{ checksum "Gemfile.lock" }} - run: mv config/database.yml.ci config/database.yml - run: bundle exec rails db:create - run: bundle exec rails db:schema:load - run: name: Rubocop command: bundle exec rubocop - run: name: run tests command: | mkdir /tmp/test-results TEST_FILES="$(circleci tests glob "spec/**/*_spec.rb" | \ circleci tests split --split-by=timings)" bundle exec rspec \ --format progress \ --format RspecJunitFormatter \ --out /tmp/test-results/rspec.xml \ --format progress \ $TEST_FILES - store_test_results: path: /tmp/test-results - store_artifacts: path: /tmp/test-results destination: test-results
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Rails】map関数で行うリファクタリング

状況 UserテーブルとPostテーブルが1対1のアソシエーションの場合。 アクティブなUserの投稿した記事のidを配列形式で取得する post_ids = User.where(status:"active").post.pluck(:id) こんな感じで1行で取得したいが、User.where(status:"active")は配列なのでpostを一意に識別できずエラーになる 冗長なコード users = User.where(status:"active") post_ids = [] users.each do |user| post_ids.push(user.post) end あまりスタイリッシュじゃない、、。 map関数でリファクタリング post_ids = User.where(status:"active").map { |u| u.post.id } ワンラインで記載できていい感じ。 コメントを元に追記 下記でも取得できる。 User.where(status: 'active').joins(:posts).pluck('posts.id') Another worksでは一緒に働ける仲間を探しています
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【図解】個人aを例に、APIの概要とRailsでの使い方を一番やさしく説明をする

記事の目的 「そもそもAPIとは?」って人がAPIの概要を理解できる Rails初学者がAPIの使い方を理解できる この記事を理解できる人 Webにおけるリクエストとレスポンスのイメージを、なんとなくでいいので理解している人 ProgateのRubyとRailsを完走できるレベルの人(APIの概要だけ見るなら不問) 目次 例に出すサービスの内容 APIとは APIが分かりにくい2つの理由 Railsでの一番簡単な使い方 リクエスト編 Railsでの一番簡単な使い方 レスポンス編 まとめ 補足(JSONとは?) 開発環境 例に出すサービスの内容 サービス概要 「いらないモノ診断」というお片付けアプリです。 写真をアップロードすると、そこに映ったモノに対してお片づけのアドバイスをするアプリです。 使用しているAPI 「いらないモノ診断」では、写真からモノを検出できる「Cloud Vision」というGoogle製アプリのAPIを使っています。 APIとは 「Application Programming Interface」の頭文字です。 Interface(インターフェース)とは直訳で「接点」であり、コンピュータ用語では「何かと何かをつなぐもの」です。 では、「何のための、何と何をつなぐ接点」なのか? 一言でいうと「アプリがアプリを使うための、アプリとアプリをつなぐ接点」ということになりますが、 アプリアプリ言い過ぎてさすがに分かりにくいと思うので図解します。 「いらないモノ診断」を使っているとき、 一見すると人間がブラウザを操作して「いらないモノ診断」を使っているだけのように見えますが、 実はその裏で「いらないモノ診断」が「Cloud Vision」を使っています。 そして「API」とは、”使われる側”のアプリに設置する「ドア」のようなものだと考えれば分かりやすいでしょう。 このドアのおかげで「いらないモノ診断」は「Cloud Vision」にアクセスし利用することができるのです。 ※以下、”使う側”のアプリを「APIユーザー」、”使われる側”のアプリを「APIプロバイダ」と呼びます。 APIが分かりにくい2つの理由 ①実体がない 先ほどは分かりやすく説明するためにAPIを「ドア」に例えましたが、厳密にいうとAPIは アプリがアプリを使うために必要な「仕組み」であり、実体のない抽象概念なのです。 (だから、「ドア」そのものに該当するコードを探しても見つかりません。) 初学者にしてみたら、APIという用語を理解するだけでも一苦労なのに、 その実体はなく、肝心の仕組みもAPIプロバイダの中にあるんだから、分かりにくくて当然です。 なので最初のうちは、上の図解でイメージを掴むだけでOKです。 ②主語がない 調べていくうちに「APIを使う」とか「APIを公開する」というようなワードを目にすると思いますが、 前者はAPIユーザー(今回でいう「いらないモノ診断」)が主語で、 後者はAPIプロバイダ(今回でいう「Cloud Vision」)が主語です。 日常会話でも主語がなくて分かりにくいことはありますが、APIはその典型といえるでしょう。 ましてや、これからAPIを理解する人にとっては尚更です。 「API」という言葉に触れるときは、主語が「ユーザー」なのか「プロバイダ」なのか、最初に考えてみると良いでしょう。 Railsでの一番簡単な使い方 リクエスト編 自分のアプリでAPIを利用するとき、通常のアクションとの一番の違いは「アプリがアプリにリクエストを送る」という点です。 ブラウザはURLの送信やリンクのクリックによってリクエストを送信しますが、 Railsアプリでリクエストを送る場合はこうです。 xxxx_controller.rb require 'net/http' def xxx api_key = "xxxxxxxxxxxxx" ・・・② api_url = URI("https://vision.googleapis.com/v1/images:annotate?key=#{vision_api_key}") ・・・③ body = { requests: [ { features: [ { maxResults: 10, type: "OBJECT_LOCALIZATION" } ], image: { content: "画像URLを記載" } } ] }.to_json ・・・④ headers = { "Content-Type" => "application/json" } ・・・⑤ response = Net::HTTP.post(api_url, body, headers) ・・・① end 以下ひとつずつ解説していきます。 ① ruby: response = Net::HTTP.post(api_url, body, headers) Net::HTTP.postメソッドによってAPIプロバイダにリクエストが送信され、そのレスポンスが変数responseに格納されています。 ちなみに今回はPOSTリクエストを送りたかったのでNet::HTTP.postというメソッドですが、GETリクエストを送りたい場合は Net::HTTP.getというメソッドになります。 (GET/POSTなどのいわゆる「HTTP動詞」はAPIプロバイダが指定するものなので、 自分が使いたいAPIプロバイダの公式リファレンスを見てください) 引数であるapi_url, body, headersについては以下で解説します。 ② ruby: api_key = "xxxxxxxxxxxxx" APIキーとは、文字通りですがAPIを使うために必要な認証キーです。 人間がアプリを使うときは、メールアドレスとパスワードを認証キーとしてログインする場面がよくあると思いますが、 アプリがアプリを使うときはこのAPIキーが認証キーとなります。 さっきの図でいうと、「ドア」であるAPIを開けるための「鍵」です。 このAPIキーはパスワードと同じで他人には絶対知られてはいけないのですが、 コントローラはGitHubなどから見れてしまうので、実は上の書き方は推奨されません。 Rails5.2以上ならconfig/credentials.yml.encを使うのがおすすめです。 credentials.yml.encはざっくりいうと「秘匿性のある情報を安全に保管できるファイル」です。(詳しくはRailsガイド参照) ここに credentials.yml.enc api_key: xxxxxxxxxxxxxxxxxxx と書けば、以下のより安全なコードに書き換えることができます。 xxxx_controller.rb api_key = Rails.application.credentials.api_key 基本的にAPIキーはAPIプロバイダに発行してもらうものなので、 使いたいAPIプロバイダの公式リファレンスで発行してもらうようにしてください。 (中にはAPIキーなしで使えるものもあるようです。) ③ ruby api_url = URI("https://vision.googleapis.com/v1/images:annotate?key=#{api_key}") ここはAPIプロバイダであるCloud Visionの公式リファレンスに従っているだけなので、 他のAPIプロバイダを使いたいときはその公式リファレンスに従ってください。 URLの文字列そのままではNet::HTTP.postメソッドの引数として適切な記法ではないためURIメソッドを使っていますが、 本題ではないので割愛します。 また認証をパスするため、?key=#{api_key}の部分でパラメータにAPIキーを渡しています。 ④ body = { ... }.to_json { }の中はurl同様、APIプロバイダの公式リファレンスに従ったまでです。 同じく公式リファレンスで「JSON形式にしろ」と言われているので、to_jsonメソッドでJSON形式に変換しています。 ⑤ headers = { "Content-Type" => "application/json" } リクエストヘッダーを決めるための記述です。 今回はJSON形式でリクエストを送信したいので"Content-Type" => "application/json"を指定しました。 (昨今のAPIのやりとりのほとんどがJSON形式なので、基本的に必要になる記述だと思います) 他に指定したい項目がある場合は { "Content-Type" => "application/json", "xxx" => "xxx", "xxx" => "xxx", ... } みたいに複数指定することもできます。 Railsでの一番簡単な使い方 レスポンス編 response = Net::HTTP.post(api_url, body, headers) この一文によって、APIプロバイダが返してくれたレスポンスは既に変数responseに格納されています。 「Cloud Vision」の場合、例えばこの写真をリクエストとして送信すると、 以下のようなJSON形式でレスポンスを返してくれます。 { "responses": [ { "localizedObjectAnnotations": [ { "mid": "/m/01bqk0", "name": "Bicycle wheel", "score": 0.89648587, "boundingPoly": { "normalizedVertices": [ (中略) ] } }, { "mid": "/m/0199g", "name": "Bicycle", "score": 0.886761, "boundingPoly": { "normalizedVertices": [ (中略) ] } }, (中略) ] } ] } 長いので一部割愛しましたが、写真に映ったモノの名前を返してくれていることが分かるでしょう。 あとはこの中の使いたい部分を取り出すことができれば、無事「APIを使えた」ことになります。 では解説していきます。 上述のレスポンスの内容はresponse.bodyで呼び出すことができますが、 映ったモノの名前など、さらに奥にあるデータを取り出すには JSON.perseメソッドでRubyオブジェクトに変換することをおすすめします。 JSON.parse(response.body) これにより、まるでハッシュや配列から値を取り出すように、欲しいデータを取り出すことができます。 例えば、最初に検出したモノの名前を取り出したければこうです。 JSON.parse(response.body)['responses'][0]["localizedObjectAnnotations"][0]['name'] # => "Bicycle wheel" 言葉にすると、 「responses配列の一番最初の要素の、localizedObjectAnnotations配列の一番最初の要素の、nameキーに対応する値」 ということになります。 筆者の場合は映ったモノの名前を全て取り出し、それを配列にしたかったのでこうです。 JSON.parse(response.body)['responses'][0]["localizedObjectAnnotations"]&.map {|i| i['name']} # => ["Bicycle wheel", "Bicycle wheel", "Bicycle", "Picture frame"] 今回は構造が複雑なので難しく感じますが、ハッシュや配列から要素を取り出す方法はProgate(ruby)でも学習したと思います。 必要に応じて復習しながら、あなたの用途に合わせて記述を変えてみるといいでしょう。 まとめ APIとは? アプリがアプリを使うために必要な「仕組み」 あくまで「仕組み」(抽象概念)であり、実体はない APIにはユーザーとプロバイダが存在する RailsにおけるAPIの使い方 リクエスト編 APIプロバイダの公式リファレンスを参考に、リクエストに必要なURL、APIキー、ボディ、ヘッダーを定義する。 定義した変数を引数に入れ、Net::HTTPメソッドでリクエストを送信する。 レスポンス編 返ってきたレスポンスをJSON.perseメソッドでRubyオブジェクトに変換する。 ハッシュや配列から要素を取り出すのと同じ要領で、自分の欲しいデータを取り出す。 補足 JSONとは Railsの学習初期ではあまりJSON形式は出てこないのでハードルが高いと感じるかもしれませんが、あくまで書き方のひとつです。 人間やブラウザがアプリを使うときは、人間にとって読みやすいHTML形式でレスポンスが返ってきますが、 アプリがアプリを使うときは、機械にとって読みやすいJSON形式でレスポンスが返されているというだけのことです。 なので、はじめは「そういう書き方があるんだ」という認識でもいいと思います。 開発環境 Ruby 3.0.0 Rails 6.1.4.1 その他 記事の分かりにくい箇所や過不足、誤りなどあればコメントいただけると幸いです。 本サービスのコード詳しく知りたい場合はGitHubをご覧ください。 (記事のコードは分かりやすさ重視のため、GitHubと若干コードが異なる部分もあります)
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【図解】個人サービスを例に、APIの概要とRailsでの使い方を一番やさしく説明をする

記事の目的 「そもそもAPIとは?」って人がAPIの概要を理解できる Rails初学者がAPIの使い方を理解できる この記事を理解できる人 Webにおけるリクエストとレスポンスのイメージを、なんとなくでいいので理解している人 ProgateのRubyとRailsを完走できるレベルの人(APIの概要だけ見るなら不問) 目次 例に出すサービスの内容 APIとは APIが分かりにくい2つの理由 Railsでの一番簡単な使い方 リクエスト編 Railsでの一番簡単な使い方 レスポンス編 まとめ 補足(JSONとは?) 開発環境 例に出すサービスの内容 サービス概要 「いらないモノ診断」というお片付けアプリです。 写真をアップロードすると、そこに映ったモノに対してお片づけのアドバイスをするアプリです。 使用しているAPI 「いらないモノ診断」では、写真からモノを検出できる「Cloud Vision」というGoogle製アプリのAPIを使っています。 APIとは 「Application Programming Interface」の頭文字です。 Interface(インターフェース)とは直訳で「接点」であり、コンピュータ用語では「何かと何かをつなぐもの」です。 では、「何のための、何と何をつなぐ接点」なのか? 一言でいうと「アプリがアプリを使うための、アプリとアプリをつなぐ接点」ということになりますが、 アプリアプリ言い過ぎてさすがに分かりにくいと思うので図解します。 「いらないモノ診断」を使っているとき、 一見すると人間がブラウザを操作して「いらないモノ診断」を使っているだけのように見えますが、 実はその裏で「いらないモノ診断」が「Cloud Vision」を使っています。 そして「API」とは、”使われる側”のアプリに設置する「ドア」のようなものだと考えれば分かりやすいでしょう。 このドアのおかげで「いらないモノ診断」は「Cloud Vision」にアクセスし利用することができるのです。 ※以下、”使う側”のアプリを「APIユーザー」、”使われる側”のアプリを「APIプロバイダ」と呼びます。 APIが分かりにくい2つの理由 ①実体がない 先ほどは分かりやすく説明するためにAPIを「ドア」に例えましたが、厳密にいうとAPIは アプリがアプリを使うために必要な「仕組み」であり、実体のない抽象概念なのです。 (だから、「ドア」そのものに該当するコードを探しても見つかりません。) 初学者にしてみたら、APIという用語を理解するだけでも一苦労なのに、 その実体はなく、肝心の仕組みもAPIプロバイダの中にあるんだから、分かりにくくて当然です。 なので最初のうちは、上の図解でイメージを掴むだけでOKです。 ②主語がない 調べていくうちに「APIを使う」とか「APIを公開する」というようなワードを目にすると思いますが、 前者はAPIユーザー(今回でいう「いらないモノ診断」)が主語で、 後者はAPIプロバイダ(今回でいう「Cloud Vision」)が主語です。 日常会話でも主語がなくて分かりにくいことはありますが、APIはその典型といえるでしょう。 ましてや、これからAPIを理解する人にとっては尚更です。 「API」という言葉に触れるときは、主語が「ユーザー」なのか「プロバイダ」なのか、最初に考えてみると良いでしょう。 Railsでの一番簡単な使い方 リクエスト編 自分のアプリでAPIを利用するとき、通常のアクションとの一番の違いは「アプリがアプリにリクエストを送る」という点です。 ブラウザはURLの送信やリンクのクリックによってリクエストを送信しますが、 Railsアプリでリクエストを送る場合はこうです。 xxxx_controller.rb require 'net/http' def xxx api_key = "xxxxxxxxxxxxx" ・・・② api_url = URI("https://vision.googleapis.com/v1/images:annotate?key=#{vision_api_key}") ・・・③ body = { requests: [ { features: [ { maxResults: 10, type: "OBJECT_LOCALIZATION" } ], image: { content: "画像URLを記載" } } ] }.to_json ・・・④ headers = { "Content-Type" => "application/json" } ・・・⑤ response = Net::HTTP.post(api_url, body, headers) ・・・① end 以下ひとつずつ解説していきます。 ① response = Net::HTTP.post(api_url, body, headers) Net::HTTP.postメソッドによってAPIプロバイダにリクエストが送信され、そのレスポンスが変数responseに格納されています。 ちなみに今回はPOSTリクエストを送りたかったのでNet::HTTP.postというメソッドですが、GETリクエストを送りたい場合は Net::HTTP.getというメソッドになります。 (GET/POSTなどのいわゆる「HTTP動詞」はAPIプロバイダが指定するものなので、 自分が使いたいAPIプロバイダの公式リファレンスを見てください) 引数であるapi_url, body, headersについては以下で解説します。 ② api_key = "xxxxxxxxxxxxx" APIキーとは、文字通りですがAPIを使うために必要な認証キーです。 人間がアプリを使うときは、メールアドレスとパスワードを認証キーとしてログインする場面がよくあると思いますが、 アプリがアプリを使うときはこのAPIキーが認証キーとなります。 さっきの図でいうと、「ドア」であるAPIを開けるための「鍵」です。 このAPIキーはパスワードと同じで他人には絶対知られてはいけないのですが、 コントローラはGitHubなどから見れてしまうので、実は上の書き方は推奨されません。 Rails5.2以上ならconfig/credentials.yml.encを使うのがおすすめです。 credentials.yml.encはざっくりいうと「秘匿性のある情報を安全に保管できるファイル」です。(詳しくはRailsガイド参照) ここに credentials.yml.enc api_key: xxxxxxxxxxxxxxxxxxx と書けば、以下のより安全なコードに書き換えることができます。 xxxx_controller.rb api_key = Rails.application.credentials.api_key 基本的にAPIキーはAPIプロバイダに発行してもらうものなので、 使いたいAPIプロバイダの公式リファレンスで発行してもらうようにしてください。 (中にはAPIキーなしで使えるものもあるようです。) ③ api_url = URI("https://vision.googleapis.com/v1/images:annotate?key=#{api_key}") ここはAPIプロバイダであるCloud Visionの公式リファレンスに従っているだけなので、 他のAPIプロバイダを使いたいときはその公式リファレンスに従ってください。 URLの文字列そのままではNet::HTTP.postメソッドの引数として適切な記法ではないためURIメソッドを使っていますが、 本題ではないので割愛します。 また認証をパスするため、?key=#{api_key}の部分でパラメータにAPIキーを渡しています。 ④ body = { ... }.to_json { }の中はurl同様、APIプロバイダの公式リファレンスに従ったまでです。 同じく公式リファレンスで「JSON形式にしろ」と言われているので、to_jsonメソッドでJSON形式に変換しています。 ⑤ headers = { "Content-Type" => "application/json" } リクエストヘッダーを決めるための記述です。 今回はJSON形式でリクエストを送信したいので"Content-Type" => "application/json"を指定しました。 (昨今のAPIのやりとりのほとんどがJSON形式なので、基本的に必要になる記述だと思います) 他に指定したい項目がある場合は { "Content-Type" => "application/json", "xxx" => "xxx", "xxx" => "xxx", ... } みたいに複数指定することもできます。 Railsでの一番簡単な使い方 レスポンス編 response = Net::HTTP.post(api_url, body, headers) この一文によって、APIプロバイダが返してくれたレスポンスは既に変数responseに格納されています。 「Cloud Vision」の場合、例えばこの写真をリクエストとして送信すると、 以下のようなJSON形式でレスポンスを返してくれます。 { "responses": [ { "localizedObjectAnnotations": [ { "mid": "/m/01bqk0", "name": "Bicycle wheel", "score": 0.89648587, "boundingPoly": { "normalizedVertices": [ (中略) ] } }, { "mid": "/m/0199g", "name": "Bicycle", "score": 0.886761, "boundingPoly": { "normalizedVertices": [ (中略) ] } }, (中略) ] } ] } 長いので一部割愛しましたが、写真に映ったモノの名前を返してくれていることが分かるでしょう。 あとはこの中の使いたい部分を取り出すことができれば、無事「APIを使えた」ことになります。 では解説していきます。 上述のレスポンスの内容はresponse.bodyで呼び出すことができますが、 映ったモノの名前など、さらに奥にあるデータを取り出すには JSON.perseメソッドでRubyオブジェクトに変換することをおすすめします。 JSON.parse(response.body) これにより、まるでハッシュや配列から値を取り出すように、欲しいデータを取り出すことができます。 例えば、最初に検出したモノの名前を取り出したければこうです。 JSON.parse(response.body)['responses'][0]["localizedObjectAnnotations"][0]['name'] # => "Bicycle wheel" 言葉にすると、 「responses配列の一番最初の要素の、localizedObjectAnnotations配列の一番最初の要素の、nameキーに対応する値」 ということになります。 筆者の場合は映ったモノの名前を全て取り出し、それを配列にしたかったのでこうです。 JSON.parse(response.body)['responses'][0]["localizedObjectAnnotations"]&.map {|i| i['name']} # => ["Bicycle wheel", "Bicycle wheel", "Bicycle", "Picture frame"] 今回は構造が複雑なので難しく感じますが、ハッシュや配列から要素を取り出す方法はProgate(ruby)でも学習したと思います。 必要に応じて復習しながら、あなたの用途に合わせて記述を変えてみるといいでしょう。 まとめ APIとは? アプリがアプリを使うために必要な「仕組み」 あくまで「仕組み」(抽象概念)であり、実体はない APIにはユーザーとプロバイダが存在する RailsにおけるAPIの使い方 リクエスト編 APIプロバイダの公式リファレンスを参考に、リクエストに必要なURL、APIキー、ボディ、ヘッダーを定義する。 定義した変数を引数に入れ、Net::HTTPメソッドでリクエストを送信する。 レスポンス編 返ってきたレスポンスをJSON.perseメソッドでRubyオブジェクトに変換する。 ハッシュや配列から要素を取り出すのと同じ要領で、自分の欲しいデータを取り出す。 補足 JSONとは Railsの学習初期ではあまりJSON形式は出てこないのでハードルが高いと感じるかもしれませんが、あくまで書き方のひとつです。 人間やブラウザがアプリを使うときは、人間にとって読みやすいHTML形式でレスポンスが返ってきますが、 アプリがアプリを使うときは、機械にとって読みやすいJSON形式でレスポンスが返されているというだけのことです。 なので、はじめは「そういう書き方があるんだ」という認識でもいいと思います。 開発環境 Ruby 3.0.0 Rails 6.1.4.1 その他 記事の分かりにくい箇所や過不足、誤りなどあればコメントいただけると幸いです。 本サービスのコード詳しく知りたい場合はGitHubをご覧ください。 (記事のコードは分かりやすさ重視のため、GitHubと若干コードが異なる部分もあります)
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【図解】個人サービスを例に、APIの概要とRailsでの使い方を一番やさしく説明する

記事の目的 「そもそもAPIとは?」って人がAPIの概要を理解できる Rails初学者がAPIの使い方を理解できる この記事を理解できる人 Webにおけるリクエストとレスポンスのイメージを、なんとなくでいいので理解している人 ProgateのRubyとRailsを完走できるレベルの人(APIの概要だけ見るなら不問) 目次 例に出すサービスの内容 APIとは APIが分かりにくい2つの理由 Railsでの一番簡単な使い方 リクエスト編 Railsでの一番簡単な使い方 レスポンス編 まとめ 補足(JSONとは?) 開発環境 例に出すサービスの内容 サービス概要 「いらないモノ診断」というお片付けアプリです。 写真をアップロードすると、そこに映ったモノに対してお片づけのアドバイスをするアプリです。 使用しているAPI 「いらないモノ診断」では、写真からモノを検出できる「Cloud Vision」というGoogle製アプリのAPIを使っています。 APIとは 「Application Programming Interface」の頭文字です。 Interface(インターフェース)とは直訳で「接点」であり、コンピュータ用語では「何かと何かをつなぐもの」です。 では、「何のための、何と何をつなぐ接点」なのか? 一言でいうと「アプリがアプリを使うための、アプリとアプリをつなぐ接点」ということになりますが、 アプリアプリ言い過ぎてさすがに分かりにくいと思うので図解します。 「いらないモノ診断」を使っているとき、 一見すると人間がブラウザを操作して「いらないモノ診断」を使っているだけのように見えますが、 実はその裏で「いらないモノ診断」が「Cloud Vision」を使っています。 そして「API」とは、”使われる側”のアプリに設置する「ドア」のようなものだと考えれば分かりやすいでしょう。 このドアのおかげで「いらないモノ診断」は「Cloud Vision」にアクセスし利用することができるのです。 ※以下、”使う側”のアプリを「APIユーザー」、”使われる側”のアプリを「APIプロバイダ」と呼びます。 APIが分かりにくい2つの理由 ①実体がない 先ほどは分かりやすく説明するためにAPIを「ドア」に例えましたが、厳密にいうとAPIは アプリがアプリを使うために必要な「仕組み」であり、実体のない抽象概念なのです。 (だから、「ドア」そのものに該当するコードを探しても見つかりません。) 初学者にしてみたら、APIという用語を理解するだけでも一苦労なのに、 その実体はなく、肝心の仕組みもAPIプロバイダの中にあるんだから、分かりにくくて当然です。 なので最初のうちは、上の図解でイメージを掴むだけでOKです。 ②主語がない 調べていくうちに「APIを使う」とか「APIを公開する」というようなワードを目にすると思いますが、 前者はAPIユーザー(今回でいう「いらないモノ診断」)が主語で、 後者はAPIプロバイダ(今回でいう「Cloud Vision」)が主語です。 日常会話でも主語がなくて分かりにくいことはありますが、APIはその典型といえるでしょう。 ましてや、これからAPIを理解する人にとっては尚更です。 「API」という言葉に触れるときは、主語が「ユーザー」なのか「プロバイダ」なのか、最初に考えてみると良いでしょう。 Railsでの一番簡単な使い方 リクエスト編 自分のアプリでAPIを利用するとき、通常のアクションとの一番の違いは「アプリがアプリにリクエストを送る」という点です。 ブラウザはURLの送信やリンクのクリックによってリクエストを送信しますが、 Railsアプリでリクエストを送る場合はこうです。 xxxx_controller.rb require 'net/http' def xxx api_key = "xxxxxxxxxxxxx" ・・・② api_url = URI("https://vision.googleapis.com/v1/images:annotate?key=#{vision_api_key}") ・・・③ body = { requests: [ { features: [ { maxResults: 10, type: "OBJECT_LOCALIZATION" } ], image: { content: "画像URLを記載" } } ] }.to_json ・・・④ headers = { "Content-Type" => "application/json" } ・・・⑤ response = Net::HTTP.post(api_url, body, headers) ・・・① end 以下ひとつずつ解説していきます。 ① response = Net::HTTP.post(api_url, body, headers) Net::HTTP.postメソッドによってAPIプロバイダにリクエストが送信され、そのレスポンスが変数responseに格納されています。 ちなみに今回はPOSTリクエストを送りたかったのでNet::HTTP.postというメソッドですが、GETリクエストを送りたい場合は Net::HTTP.getというメソッドになります。 (GET/POSTなどのいわゆる「HTTP動詞」はAPIプロバイダが指定するものなので、 自分が使いたいAPIプロバイダの公式リファレンスを見てください) 引数であるapi_url, body, headersについては以下で解説します。 ② api_key = "xxxxxxxxxxxxx" APIキーとは、文字通りですがAPIを使うために必要な認証キーです。 人間がアプリを使うときは、メールアドレスとパスワードを認証キーとしてログインする場面がよくあると思いますが、 アプリがアプリを使うときはこのAPIキーが認証キーとなります。 さっきの図でいうと、「ドア」であるAPIを開けるための「鍵」です。 このAPIキーはパスワードと同じで他人には絶対知られてはいけないのですが、 コントローラはGitHubなどから見れてしまうので、実は上の書き方は推奨されません。 Rails5.2以上ならconfig/credentials.yml.encを使うのがおすすめです。 credentials.yml.encはざっくりいうと「秘匿性のある情報を安全に保管できるファイル」です。(詳しくはRailsガイド参照) ここに credentials.yml.enc api_key: xxxxxxxxxxxxxxxxxxx と書けば、以下のより安全なコードに書き換えることができます。 xxxx_controller.rb api_key = Rails.application.credentials.api_key 基本的にAPIキーはAPIプロバイダに発行してもらうものなので、 使いたいAPIプロバイダの公式リファレンスで発行してもらうようにしてください。 (中にはAPIキーなしで使えるものもあるようです。) ③ api_url = URI("https://vision.googleapis.com/v1/images:annotate?key=#{api_key}") ここはAPIプロバイダであるCloud Visionの公式リファレンスに従っているだけなので、 他のAPIプロバイダを使いたいときはその公式リファレンスに従ってください。 URLの文字列そのままではNet::HTTP.postメソッドの引数として適切な記法ではないためURIメソッドを使っていますが、 本題ではないので割愛します。 また認証をパスするため、?key=#{api_key}の部分でパラメータにAPIキーを渡しています。 ④ body = { ... }.to_json { }の中はurl同様、APIプロバイダの公式リファレンスに従ったまでです。 同じく公式リファレンスで「JSON形式にしろ」と言われているので、to_jsonメソッドでJSON形式に変換しています。 ⑤ headers = { "Content-Type" => "application/json" } リクエストヘッダーを決めるための記述です。 今回はJSON形式でリクエストを送信したいので"Content-Type" => "application/json"を指定しました。 (昨今のAPIのやりとりのほとんどがJSON形式なので、基本的に必要になる記述だと思います) 他に指定したい項目がある場合は { "Content-Type" => "application/json", "xxx" => "xxx", "xxx" => "xxx", ... } みたいに複数指定することもできます。 Railsでの一番簡単な使い方 レスポンス編 response = Net::HTTP.post(api_url, body, headers) この一文によって、APIプロバイダが返してくれたレスポンスは既に変数responseに格納されています。 「Cloud Vision」の場合、例えばこの写真をリクエストとして送信すると、 以下のようなJSON形式でレスポンスを返してくれます。 { "responses": [ { "localizedObjectAnnotations": [ { "mid": "/m/01bqk0", "name": "Bicycle wheel", "score": 0.89648587, "boundingPoly": { "normalizedVertices": [ (中略) ] } }, { "mid": "/m/0199g", "name": "Bicycle", "score": 0.886761, "boundingPoly": { "normalizedVertices": [ (中略) ] } }, (中略) ] } ] } 長いので一部割愛しましたが、写真に映ったモノの名前を返してくれていることが分かるでしょう。 あとはこの中の使いたい部分を取り出すことができれば、無事「APIを使えた」ことになります。 では解説していきます。 上述のレスポンスの内容はresponse.bodyで呼び出すことができますが、 映ったモノの名前など、さらに奥にあるデータを取り出すには JSON.perseメソッドでRubyオブジェクトに変換することをおすすめします。 JSON.parse(response.body) これにより、まるでハッシュや配列から値を取り出すように、欲しいデータを取り出すことができます。 例えば、最初に検出したモノの名前を取り出したければこうです。 JSON.parse(response.body)['responses'][0]["localizedObjectAnnotations"][0]['name'] # => "Bicycle wheel" 言葉にすると、 「responses配列の一番最初の要素の、localizedObjectAnnotations配列の一番最初の要素の、nameキーに対応する値」 ということになります。 筆者の場合は映ったモノの名前を全て取り出し、それを配列にしたかったのでこうです。 JSON.parse(response.body)['responses'][0]["localizedObjectAnnotations"]&.map {|i| i['name']} # => ["Bicycle wheel", "Bicycle wheel", "Bicycle", "Picture frame"] 今回は構造が複雑なので難しく感じますが、ハッシュや配列から要素を取り出す方法はProgate(ruby)でも学習したと思います。 必要に応じて復習しながら、あなたの用途に合わせて記述を変えてみるといいでしょう。 まとめ APIとは? アプリがアプリを使うために必要な「仕組み」 あくまで「仕組み」(抽象概念)であり、実体はない APIにはユーザーとプロバイダが存在する RailsにおけるAPIの使い方 リクエスト編 APIプロバイダの公式リファレンスを参考に、リクエストに必要なURL、APIキー、ボディ、ヘッダーを定義する。 定義した変数を引数に入れ、Net::HTTPメソッドでリクエストを送信する。 レスポンス編 返ってきたレスポンスをJSON.perseメソッドでRubyオブジェクトに変換する。 ハッシュや配列から要素を取り出すのと同じ要領で、自分の欲しいデータを取り出す。 補足 JSONとは Railsの学習初期ではあまりJSON形式は出てこないのでハードルが高いと感じるかもしれませんが、あくまで書き方のひとつです。 人間やブラウザがアプリを使うときは、人間にとって読みやすいHTML形式でレスポンスが返ってきますが、 アプリがアプリを使うときは、機械にとって読みやすいJSON形式でレスポンスが返されているというだけのことです。 なので、はじめは「そういう書き方があるんだ」という認識でもいいと思います。 開発環境 Ruby 3.0.0 Rails 6.1.4.1 その他 記事の分かりにくい箇所や過不足、誤りなどあればコメントいただけると幸いです。 本サービスのコード詳しく知りたい場合はGitHubをご覧ください。 (記事のコードは分かりやすさ重視のため、GitHubと若干コードが異なる部分もあります)
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【図解】個人サービスを例に、Web APIの概要とRailsでの使い方を一番やさしく説明する

記事の目的 「そもそもWebAPIとは?」って人がWebAPIの概要を理解できる Rails初学者がWebAPIの使い方を理解できる この記事を理解できる人 Webにおけるリクエストとレスポンスのイメージを、なんとなくでいいので理解している人 ProgateのRubyとRailsを完走できるレベルの人(WebAPIの概要だけ見るなら不問) 目次 例に出すサービスの内容 APIとは APIが分かりにくい2つの理由 Railsでの一番簡単な使い方 リクエスト編 Railsでの一番簡単な使い方 レスポンス編 まとめ 補足(JSONとは?) 開発環境 例に出すサービスの内容 サービス概要 「いらないモノ診断」というお片付けアプリです。 写真をアップロードすると、そこに映ったモノに対してお片づけのアドバイスします。 使用しているWebAPI 「いらないモノ診断」では、写真からモノを検出できる「Cloud Vision」という Google製サービスのWebAPIを使っています。 APIとは 「Application Programming Interface」の頭文字です。 Interface(インターフェース)とは直訳で「接点」であり、コンピュータ用語では 「何かと何かをつなぐもの」です。 ソフトウェアだとイメージが湧かないかもしれませんが、 ハードウェアだと例えばケーブル類は「何かと何かをつなぐ」のでインターフェースの一種です。 では、「何のための、何と何をつなぐ接点」なのか? 一言でいうと、APIは「アプリがアプリを使うための、アプリとアプリをつなぐ接点」です。 そして、中でもWeb上のリクエスト/レスポンスを利用する「接点」を「WebAPI」といいます。 (APIは総称であり、その中にWebAPIがあるというイメージを持てればOKです。 WebAPI以外のAPIもありますが、本題から逸れるのでここでは説明しません。) ※ここからは、便宜上WebAPIを「API」と呼んで説明します 図解するとこんな感じです。 「いらないモノ診断」を使っているとき、 一見すると人間がブラウザを操作して「いらないモノ診断」を使っているだけのように見えますが、 実はその裏で「いらないモノ診断」が「Cloud Vision」を使っています。 そして「API」とは、”使われる側”のアプリに設置する「ドア」のようなものだと考えれば分かりやすいでしょう。 このドアのおかげで「いらないモノ診断」は「Cloud Vision」にアクセスし利用することができるのです。 ※以下、”使う側”のアプリを「APIユーザー」、”使われる側”のアプリを「APIプロバイダ」と呼びます。 APIが分かりにくい2つの理由 ①実体がない 先ほどは分かりやすく説明するためにAPIを「ドア」に例えましたが、厳密にいうとAPIは アプリがアプリを使うために必要な「仕組み」であり、実体のない抽象概念なのです。 (だから、「ドア」そのものに該当するコードを探しても見つかりません。) 初学者にしてみたら、APIという用語を理解するだけでも一苦労なのに、 その実体はなく、肝心の仕組みもAPIプロバイダの中にあるんだから、分かりにくくて当然です。 なので最初のうちは、上の図解でイメージを掴むだけでOKです。 ②主語がない 調べていくうちに「APIを使う」とか「APIを公開する」というようなワードを目にすると思いますが、 前者はAPIユーザー(今回でいう「いらないモノ診断」)が主語で、 後者はAPIプロバイダ(今回でいう「Cloud Vision」)が主語です。 日常会話でも主語がなくて分かりにくいことはありますが、APIはその典型といえるでしょう。 ましてや、これからAPIを理解する人にとっては尚更です。 「API」という言葉に触れるときは、主語が「ユーザー」なのか「プロバイダ」なのか、最初に考えてみると良いでしょう。 Railsでの一番簡単な使い方 リクエスト編 自分のアプリでAPIを利用するとき、通常のアクションとの一番の違いは「アプリがアプリにリクエストを送る」という点です。 ブラウザはURLの送信やリンクのクリックによってリクエストを送信しますが、 Railsアプリでリクエストを送る場合はこうです。 xxxx_controller.rb require 'net/http' def xxx api_key = "xxxxxxxxxxxxx" ・・・② api_url = URI("https://vision.googleapis.com/v1/images:annotate?key=#{vision_api_key}") ・・・③ body = { requests: [ { features: [ { maxResults: 10, type: "OBJECT_LOCALIZATION" } ], image: { content: "画像URLを記載" } } ] }.to_json ・・・④ headers = { "Content-Type" => "application/json" } ・・・⑤ response = Net::HTTP.post(api_url, body, headers) ・・・① end 以下ひとつずつ解説していきます。 ① response = Net::HTTP.post(api_url, body, headers) Net::HTTP.postメソッドによってAPIプロバイダにリクエストが送信され、そのレスポンスが変数responseに格納されています。 ちなみに今回はPOSTリクエストを送りたかったのでNet::HTTP.postというメソッドですが、GETリクエストを送りたい場合は Net::HTTP.getというメソッドになります。 (GET/POSTなどのいわゆる「HTTP動詞」はAPIプロバイダが指定するものなので、 自分が使いたいAPIプロバイダの公式リファレンスを見てください) 引数であるapi_url, body, headersについては以下で解説します。 ② api_key = "xxxxxxxxxxxxx" APIキーとは、文字通りAPIを使うために必要な認証キーです。 人間がアプリを使うときは、メールアドレスとパスワードを認証キーとしてログインする場面がよくあると思いますが、 アプリがアプリを使うときはこのAPIキーが認証キーとなります。 さっきの図でいうと、「ドア」であるAPIを開けるための「鍵」です。 このAPIキーはパスワードと同じで他人には絶対知られてはいけないのですが、 コントローラはGitHubなどから見れてしまうので、実は上の書き方は推奨されません。 Rails5.2以上ならconfig/credentials.yml.encを使うのがおすすめです。 credentials.yml.encはざっくりいうと「秘匿性のある情報を安全に保管できるファイル」です。(詳しくはRailsガイド参照) ここに credentials.yml.enc api_key: xxxxxxxxxxxxxxxxxxx と書けば、以下のより安全なコードに書き換えることができます。 xxxx_controller.rb api_key = Rails.application.credentials.api_key 基本的にAPIキーはAPIプロバイダに発行してもらうものなので、 使いたいAPIプロバイダの公式リファレンスで発行してもらうようにしてください。 (中にはAPIキーなしで使えるものもあるようです。) ③ api_url = URI("https://vision.googleapis.com/v1/images:annotate?key=#{api_key}") ここはAPIプロバイダであるCloud Visionの公式リファレンスに従っているだけなので、 他のAPIプロバイダを使いたいときはその公式リファレンスに従ってください。 URLの文字列そのままではNet::HTTP.postメソッドの引数として適切な記法ではないためURIメソッドを使っていますが、 本題ではないので割愛します。 また認証をパスするため、?key=#{api_key}の部分でパラメータにAPIキーを渡しています。 ④ body = { ... }.to_json { }の中はurl同様、APIプロバイダの公式リファレンスに従ったまでです。 同じく公式リファレンスで「JSON形式にしろ」と言われているので、to_jsonメソッドでJSON形式に変換しています。 ⑤ headers = { "Content-Type" => "application/json" } リクエストヘッダーを決めるための記述です。 今回はJSON形式でリクエストを送信したいので"Content-Type" => "application/json"を指定しました。 (昨今のAPIのやりとりのほとんどがJSON形式なので、基本的に必要になる記述だと思います) 他に指定したい項目がある場合は { "Content-Type" => "application/json", "xxx" => "xxx", "xxx" => "xxx", ... } みたいに複数指定することもできます。 Railsでの一番簡単な使い方 レスポンス編 response = Net::HTTP.post(api_url, body, headers) この一文によって、APIプロバイダが返してくれたレスポンスは既に変数responseに格納されています。 「Cloud Vision」の場合、例えばこの写真をリクエストとして送信すると、 以下のようなJSON形式でレスポンスを返してくれます。 { "responses": [ { "localizedObjectAnnotations": [ { "mid": "/m/01bqk0", "name": "Bicycle wheel", "score": 0.89648587, "boundingPoly": { "normalizedVertices": [ (中略) ] } }, { "mid": "/m/0199g", "name": "Bicycle", "score": 0.886761, "boundingPoly": { "normalizedVertices": [ (中略) ] } }, (中略) ] } ] } 長いので一部割愛しましたが、写真に映ったモノの名前を返してくれていることが分かるでしょう。 あとはこの中の使いたい部分を取り出すことができれば、無事「APIを使えた」ことになります。 では解説していきます。 上述のレスポンスの内容はresponse.bodyで呼び出すことができますが、 映ったモノの名前など、さらに奥にあるデータを取り出すには JSON.perseメソッドでRubyオブジェクトに変換することをおすすめします。 JSON.parse(response.body) これにより、まるでハッシュや配列から値を取り出すように、欲しいデータを取り出すことができます。 例えば、最初に検出したモノの名前を取り出したければこうです。 JSON.parse(response.body)['responses'][0]["localizedObjectAnnotations"][0]['name'] # => "Bicycle wheel" 言葉にすると、 「responses配列の一番最初の要素の、localizedObjectAnnotations配列の一番最初の要素の、nameキーに対応する値」 ということになります。 筆者の場合は映ったモノの名前を全て取り出し、それを配列にしたかったのでこうです。 JSON.parse(response.body)['responses'][0]["localizedObjectAnnotations"]&.map {|i| i['name']} # => ["Bicycle wheel", "Bicycle wheel", "Bicycle", "Picture frame"] 今回は構造が複雑なので難しく感じますが、ハッシュや配列から要素を取り出す方法はProgate(ruby)でも学習したと思います。 必要に応じて復習しながら、あなたの用途に合わせて記述を変えてみるといいでしょう。 まとめ APIとは? アプリがアプリを使うために必要な「仕組み」 あくまで「仕組み」(抽象概念)であり、実体はない APIにはユーザーとプロバイダが存在する RailsにおけるAPIの使い方 リクエスト編 APIプロバイダの公式リファレンスを参考に、リクエストに必要なURL、APIキー、ボディ、ヘッダーを定義する。 定義した変数を引数に入れ、Net::HTTPメソッドでリクエストを送信する。 レスポンス編 返ってきたレスポンスをJSON.perseメソッドでRubyオブジェクトに変換する。 ハッシュや配列から要素を取り出すのと同じ要領で、自分の欲しいデータを取り出す。 補足 JSONとは Railsの学習初期ではあまりJSON形式は出てこないのでハードルが高いと感じるかもしれませんが、あくまで書き方のひとつです。 人間やブラウザがアプリを使うときは、人間にとって読みやすいHTML形式でレスポンスが返ってきますが、 アプリがアプリを使うときは、機械にとって読みやすいJSON形式でレスポンスが返されているというだけのことです。 なので、はじめは「そういう書き方があるんだ」という認識でもいいと思います。 開発環境 Ruby 3.0.0 Rails 6.1.4.1 その他 記事の分かりにくい箇所や過不足、誤りなどあればコメントいただけると幸いです。 本サービスのコード詳しく知りたい場合はGitHubをご覧ください。 (記事のコードは分かりやすさ重視のため、GitHubと若干コードが異なる部分もあります)
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Failure/Error: config.include FactoryBot::Syntax::Methodsが出た時の対処方法

今回は記述場所を間違えるという非常に初歩的なミスが原因でしたが、他の方の記事を見ても、どこかしらで記述ミスしていることが多いという印象を受けました。 同じようなエラーで詰まっている方の参考になれば幸いです。 やりたいこと rspecによるテストの実行。 Failure/Error: config.include FactoryBot::Syntax::MethodsとNameError:uninitialized constant FactoryBotの解決。 やったこと ターミナルでbundle exec rspecを実行すると、下記のエラーが発生した。 エラー内容 ターミナル An error occurred while loading rails_helper. Failure/Error: config.include FactoryBot::Syntax::Methods NameError: uninitialized constant FactoryBot # ./spec/spec_helper.rb:19:in `block in <top (required)>' # ./spec/spec_helper.rb:18:in `<top (required)>' # ./spec/rails_helper.rb:4:in `require' # ./spec/rails_helper.rb:4:in `<top (required)>' エラーの原因 初歩的すぎるが、config.include FactoryBot::Syntax::Methodsを記述する場所を間違っていた。 具体的には下記が原因で間違えました。 rspecをインストールすると、spec_helper.rbとrails_helper.rbが作成される。 config.include FactoryBot::Syntax::Methodsはrails_helper.rbファイルのRSpec.configure do |config|の下部に追記する。 RSpec.configure do |config|という記述がspec_helper.rbとrails_helper.rbの両方に存在することに気づかず、spec_helper.rbの方に追記してしまった。 解決策 rails_helper.rbのRSpec.configure do |config|下に追記する。 rails_helper.rb RSpec.configure do |config| config.include FactoryBot::Syntax::Methods (中略) end 学んだこと 今回のミスはただ記述する場所を間違えたという初歩的すぎるものだが、たったこれだけでエラー解決に時間を取られてしまうため、どこのファイルに記述するか・スペルミスはないかなどケアレスミスに注意して開発を進める。 参考 Rails + RSpec で FactoryBot(旧 FactoryGirl)を使う 【RSpec】NameError: uninitialized constant FactoryBotというエラーが出た話 factory_bot_rails
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Railsで出てくるparams[:id]ってなんだ?paramsについて深く理解してみる

はじめに どうも、27歳未経験からエンジニア転職を目指しているもきおです。 Ruby on Railsを学習しているとよくコントローラーにおいてparamsってやつが出てきますよね? 例としてはこんな感じ users_controller.rb def show @user = User.find(params[:id]) end でもshowの他にeditとかcreateとかでも出てきてしかも記載の仕方がちょくちょく変わっている。 自分自身もとりあえず見様見真似でnewの時はこの記載、showはこの記載みたいな感じで記載してまあエラー起きず動いたら満足って感じでコードを書いてました。 今回はparamsについて理解を深めたのでただコピペでなくちゃんと理解をした上でparamsを使用できるようこの記事に書き記しておきます。 ※createに関してのparamsの記載は後日別記事にて記載します。 paramsってなんぞ? paramsとは送られてきた値を受け取るためのメソッドのことです。っていっても分からないので例を見てみましょう。 ユーザー一覧はこんな感じのURLになっています。URLの最後がusersとなってますね ユーザー一覧で一番上のid:1のkkkkというユーザーの詳細画面(Show)を押すと するとURLの最後に/1が追加されました。 ここでターミナルを見てみると黄色い枠にidに1が代入されている事がわかります。 このようにparamsは送られて来た値を受け取る事ができます。 users_controller.rb def show @user = User.find(params[:id]) end このparamsにおいてユーザーの:idを取得している事がわかります。 これはidに紐ずくユーザー情報を全て取って来ているので次のような事もできます。 View index.htm.erb 今までこのような記載だったのを nameをキーとしてユーザーネームも渡してあげます。 するとidの後に名前も挿入されることが分かります。少しparamsが理解できてきたのではないかなと思います。 あとがき 今回でparamsの理解を少し深める事ができました。 この記事が少しでも良いと感じていただけましたらLGTMポチっとしていただけると幸いです。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【備忘録】WebAPIサーバを作るとはどういうことか

RailsとReactでSPA化を実装したいのですが、そもそもWebAPIサーバの意味が理解できていなかったため、記事に残しました。 SPAでは、最初のページにあたるHTMLのみをサーバから取得し、その後の画面の書き換え等をすべてクライアント側(ブラウザ内)のJavaScriptで実施する。 そのため、SPAのアプリケーションでは、サーバ側(Rails側)のアプリケーションの役割はいわゆるWebAPIとしてブラウザ側のJavaScriptとAjax通信を行うのみ、というケースも多い。 API専用Railsアプリケーションの生成コマンド $ rails new my_api --api ▼詳細はRailsガイドを参照 ▼参考記事 大変わかりやすかったです!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む