20200811のRubyに関する記事は20件です。

【Rails】いいね機能を非同期実装

1. はじめに

以下のデモ動画の様に、ユーザーが投稿した内容に対して"いいね"が出来る機能を実装していきます。
Image from Gyazo

2. 前提条件

既にユーザー登録機能と投稿機能は実装されている前提で、そこに"いいね機能"を追加実装する。という流れで進めていきます。

下記の様なデータベース構造をイメージしてもらえたら分かりやすいと思います。
ER 図(Qiita).png

3. いいね機能の実装

■実装するまでの流れ

ざっくり説明すると、以下の流れで実装していきます。
・モデルの作成
   ↓
・ルーティングの追加
   ↓
・コントローラーの作成
   ↓
・ビューの作成

それでは、早速いってみましょー。

3-1. Likeモデルの作成

まずはLikeモデルを作成します。
ターミナルで以下のコマンドを実行してください。

ターミナル
$ rails g model Like

新しくマイグレーションファイルが作成されるので、以下の通りに編集してください。

db>migrate>xxxxxx_create_likes.rb
class CreateLikes < ActiveRecord::Migration[6.0]
  def change
    create_table :likes do |t|
      # ===追記部分===
      t.references :tweet, foreign_key: true, null: false
      t.references :user, foreign_key: true, null: false
      # ===追記部分===
      t.timestamps
    end
  end
end

上記の様にreferences型で保存すると、tweet_iduser_idを外部キーとして指定することが出来ます。
それではマイグレーションファイルを実行して、likesテーブルを作成しましょう。

ターミナル
$ rails db:migrate

上記のコマンドを実行した後、likesテーブルが作成されたかどうか確認して下さい。
無事作成されている事が確認出来たら、次はアソシエーションの設定です。

3-2. アソシエーションの設定

アソシエーションとは、2つのモデル同士の関連付けのことを指します。
UserモデルとLikeモデル、TweetモデルとLikeモデル、それぞれのアソシエーションを設定していきます。

UserモデルとLikeモデルのアソシエーションの設定

まずはUserモデルとLikeモデルのアソシエーションを設定していきます。

2つのモデルの関係性は以下の通りです。
・ ユーザーは複数のいいねが可能
・ いいねAをしたユーザーは1人しかいない

つまり、UserモデルとLikeモデルは「1対多」の関係になります。
それでは、実際にコードを書いていきましょう。

Userモデルに以下の通りコードを追記して下さい。

app>models>user.rb
class User < ApplicationRecord

  has_many :tweets, dependent: :destroy

  # この行を追加
  has_many :likes

end

has_many は、他のモデルとの間に「1対多」の関係があることを示します。

次はLikeモデルに以下の通りコードを追記して下さい。

app>models>like.rb
class Like < ApplicationRecord

  # この行を追加
  belongs_to :user

end

belongs_tohas_many の逆で、他のモデルとの間に「多対1」の関係があることを示しています。

これで、UserモデルとLikeモデルのアソシエーション設定が出来ました。

TweetモデルとLikeモデルのアソシエーションの設定

同じ要領でTweetモデルとLikeモデルのアソシエーションも設定していきます。

2つのモデルの関係性は以下の通りです。
・ 1つの投稿に対して、複数のいいねがつく
・ いいねAに紐づく投稿は1つしかない

つまり、TweetモデルとLikeモデルも「1対多」の関係になります。
それでは、実際にコードを書いていきましょう。

Tweetモデルに以下の通りコードを追記して下さい。

app>models>tweet.rb
class Tweet < ApplicationRecord
  belongs_to :user

  # この行を追加
  has_many :likes, dependent: :destroy

end

dependent: :destroy をつける事で、投稿が削除された時に、その投稿に紐づくいいねも削除されます。

次はLikeモデルです。

app>models>like.rb
class Like < ApplicationRecord

  belongs_to :user

  # この行を追加
  belongs_to :tweet

end

以上で、全てのモデルのアソシエーションの設定が完了しました。

3-3. バリデーションの設定

投稿Aに対して1人のユーザーがいいねを押せる回数は1回にしたいので、1回以上は押せない様にバリデーションを設定します。

Likeモデルに以下の通り追記して下さい。

app>models>like.rb
class Like < ApplicationRecord

  belongs_to :user
  belongs_to :tweet

  # この行を追加
  validates :user_id, uniqueness: { scope: :tweet_id }

end

上記の様に書く事で、user_idtweet_id が重複しない様にする事が出来ます。
以上で、バリデーションの設定は完了です。

3-4. ルーティングの追加

いよいよ本格的にいいね機能を実装していきます。

まずは、いいね機能で使うルーティングを追加しましょう。
以下の通りコードを追記して下さい。

config>routes.rb
Rails.application.routes.draw do
  devise_for :users,
    controllers: { registrations: 'registrations' }

  resources :tweets, only: [:index, :new, :create, :show, :destroy] do

    # この行を追加
    resources :likes, only: [:create, :destroy]

  end

end

いいね情報の保存と削除のルーティングを追加する必要があるので、likesコントローラーのcreate アクションとdestroy アクションを定義しています。

ルーティングをネストにする事で、いいねがどの投稿に紐づくかを明示できます。

コードを追加したらrails routes コマンドで、ルーティングの設定が問題ないか忘れずに確認しておきましょう。

3-5. likesコントローラーの作成

次にlikesコントローラーを作成していきます。
ターミナルで以下のコマンドを実行してください。

ターミナル
$ rails g controller likes

上記のコマンドを実行すると、likesコントローラーが作成できます。

それでは作成したlikesコントローラーにcreate アクションとdestroy アクションを作成していきます。
以下の通りコードを追記して下さい。

app>controllers>likes_controller.rb
class LikesController < ApplicationController

  # ===追記部分===
  def create
    @like = current_user.likes.build(like_params)
    @tweet = @like.tweet
    if @like.save
      respond_to :js
    end
  end

  def destroy
    @like = Like.find_by(id: params[:id])
    @tweet = @like.tweet
    if @like.destroy
      respond_to :js
    end
  end

  private
    def like_params
      params.permit(:tweet_id)
    end
  # ===追記部分===

end

privateメソッドやparamsは理解できているものとして、追加したコードについて簡単に説明していきます。

createアクション

まず@like には投稿に"いいね"をしたユーザーのuser_id と、"いいね"された投稿のtweet_id の情報が入っています。
このコードはbuildメソッドを使って、インスタンスを作成しています。

次に@tweet には@like に紐づく投稿の情報、つまり"いいね"された投稿の情報が入ります。
@tweet はどの投稿に"いいね"を押したのかを判断するために、ビューを作成するところで使います。

最後のif @like.save の部分は、"いいね"が押された時に返すレスポンスのフォーマットをrespond_to メソッドで切り替えています。
"いいね"が押されたらリアルタイムでビューを反映させるために、JS形式のフォーマットでレスポンスを返すようにしています。

destroyアクション

createアクションのところで説明した内容と重複している部分が多いので簡単に説明すると、受け取ったHTTPリクエストからid を判別し、@like に指定のレコードの情報を入れています。

こちらもリアルタイムでビューを反映させるために、JS形式のフォーマットでレスポンスを返すようにしています。

3-5. ビューの作成

いよいよビューの作成です。

まずは投稿一覧のビュー画面を編集していきましょう・・・と言いたいところですが、ビューで使うためのメソッドを先に定義しておきます。

Tweetモデルに以下の通りコードを追記して下さい。

app>models>tweet.rb
class Tweet < ApplicationRecord
  belongs_to :user
  has_many :likes, dependent: :destroy

  # 追加部分(liked_byメソッド)
  def liked_by(user)
    Like.find_by(user_id: user.id, tweet_id: id)
  end
  # 追加部分

end

上記で追加したliked_by メソッドは、user_idtweet_id が一致するlikeを探して、無ければnillを返します。

それでは、app/views/tweets/index.html.erb に以下のコードを追記して下さい。

app>views>tweets>index.html.erb
<% @tweets.each do |tweet| %>

  # いいねボタンを表示したい部分に追加
  <div class="content-like">
    <ul class="content-like__icons">
      <li id="<%= tweet.id.to_s %>">
        <% if tweet.liked_by(current_user).present? %>
          <%= link_to (tweet_like_path(tweet.id, tweet.liked_by(current_user)), method: :DELETE, remote: true, class: "liked") do %>
            <i class="far fa-thumbs-up"></i>
          <% end %>
        <% else %>
          <%= link_to (tweet_likes_path(tweet), method: :POST, remote: true, class: "like") do %>
            <i class="far fa-thumbs-up"></i>
          <% end %>
        <% end %>
      </li>
    </ul>
  </div>
  # 追加部分はここまで

<% end %>

liked_by に引数としてcurrent_userを渡すことで、現在ログインしているユーザーが投稿に"いいね"をしているかどうか判断しています。

これでユーザーが"いいね"をしていない時に"いいねボタン"をクリックすると、先ほど作成したcreate アクションを実行、ユーザーが"いいね"をしている時はdestroy アクションを実行と、条件分岐させる事ができました。

リンクが押された時に.js.erb ファイルを呼び出す必要があるので、link_toremote: true オプションを追加することを忘れないでください。

なお"いいねボタン"のアイコンについては、Font Awesome を利用しています。
導入方法については、以下のqiita記事などが参考になるかと思います。
rails font-awesome-sass導入方法

次は、createアクションが実行された時に出力するファイルを作成します。
app/views フォルダ直下にlikes フォルダを作成し、その中にcreate.js.erb ファイルを作成してください。

ファイルの作成ができたら、以下の通りコードを追記してください。

app>views>likes>create.js.erb
$('#<%= @tweet.id.to_s %>').
  html('<%= j render "tweets/liked", { tweet: @tweet } %>');

上記のコードで、createアクションが実行されたらtweets フォルダ内の_liked.html.erb ファイルを呼び出しています。

tweets フォルダの中に_liked.html.erb ファイルを作成し、以下のコードを追加してください。

app>views>tweets>_liked.html.erb
<%= link_to (tweet_like_path(tweet.id, tweet.liked_by(current_user)), method: :DELETE, remote: true, class: "liked") do %>
  <i class="far fa-thumbs-up"></i>
<% end %>

上記のコードで、"いいねボタン"を押したら"いいね"を取り消すHTMLを表示するようにしています。

同じ流れで、destroyアクションが実行された時に呼び出されるファイルも作っていきましょう。
app/views>likes フォルダの中にdestroy.js.erb ファイルを作成してください。

ファイルの作成ができたら、以下の通りコードを追記してください。

app>views>likes>destroy.js.erb
$('#<%= @tweet.id.to_s %>').
  html('<%= j render "tweets/like", { tweet: @tweet } %>');

tweets フォルダの中に_like.html.erb ファイルを作成し、以下のコードを追加してください。

app>views>tweets>_like.html.erb
<%= link_to (tweet_likes_path(tweet), method: :POST, remote: true, class: "like") do %>
  <i class="far fa-thumbs-up"></i>
<% end %>

以上で非同期でいいね機能を実装する事ができました。

あとは見た目ですが、クラス名を、いいねされている時はliked されていない時はlike としていますので、CSSで自分好みにカスタマイズしてみてください。

私の場合は以下の様にして、いいねがされた時はレッド、されていない時はグレーにアイコンの色を変えています。

app>assets>stylesheets>tweets>_tweet.css
.like {
  color: gray;
}

.liked {
  color: red;
}

4. さいごに

今回がはじめての投稿になりますが、記事を書くのって想像していたよりも大変ですね。
もし分かりにくい部分や、間違っている部分がある場合はご指摘いただけると嬉しいです。

最後まで読んでいただき、ありがとうございました☺️

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ハッシュ(hash)

keyの取り出し方

h = {"apple" => "red"}

h.keys #=> ["apple"]

h.keys[0] # => "apple"

flatten(多次元配列の平坦化)

a = [1, [2, [3, [4, 5]]]]

a.flatten(1) #=> [1, 2, [3, [4, 5]]]
a.flatten(2) #=> [1, 2, 3, [4, 5]]
a.flatten(3) #=> [1, 2, 3, 4, 5]
a.flatten    #=> [1, 2, 3, 4, 5]

merge(ハッシュの結合)

h1 = {"red" => "apple"}
h2 = {"red" => "tomato"}
h1.merge(h2) #=> {"red"=>"tomato"}
h2.merge(h1) #=> {"red"=>"apple"}

上のように、キーが同じ場合、引数のハッシュの値で上書きされてしまう。
mergeは下のようにブロックを受け取ることができ、キーが重複した時の挙動を指定することができる。

h1 = {"red" => "apple"}
h2 = {"red" => "tomato"}
h1.merge(h2){|key,h1v,h2v| "#{h1v}" + "," + "#{h2v}"}
#=> {"red"=>"apple,tomato"}

key? , has_key?(キーの存在を確かめる)

h = {"red" => "apple"}
h.key?("red")     #=> true
h.has_key?("red") #=> true

h.key?("blue")    #=> false
h.has_key?("blue")#=> false
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

独学未経験エンジニアがweb系自社開発企業でアルバイトを2ヶ月してみて感じたこと

簡単な自己紹介

  • 大学では機械工学を専攻 
  • プログラマに魅力を感じ2019年新卒でメーカー子会社のIT会社に入社
  • 入社してから10ヶ月で会社を退職
  • そこから4ヶ月間独学で勉強し、現在web系の自社開発企業でアルバイト中

ニートになって独学していた時代

新卒で入社したときに感じたことや退職理由はまた今度別の記事で書いてみたいと思います。

勉強したこと一覧

  • progate(HTML,CSS,Javascript,Ruby,RubyonRails)

  • railsチュートリアル解説動画
    2周はした。1周目は動画を見るだけで、2周目は手を動かしながらでした。
    かなりお世話になり、railsチュートリアルとは友達になった気がする

  • Ruby on Rails5 超入門
    amazonリンク
    読んだのは3割ぐらいだけ

  • Ruby on Rails5 速習実践ガイド
    amazonリンク
    辞書的な感じで使ったりした。暇なときに読んでみてもためになることが多い。

  • Gitが、おもしろいほどわかる基本の使い方33
    amazonリンク
    gitの操作の基礎を学んだ。すぐに読み終わる内容なので、読みやすい

  • キタミ式イラストIT塾 基本情報技術者
    amazonリンク
    コンピュターの基礎を理解するのにはちょーど良かった。時間をかけてちょっとずつ読んだ

  • webを支える技術
    amazonリンク
    何を書いているのか全然分からなかった。kindle版で技術書は読みにくい。

  • 図解即戦力 AWSのしくみと技術がしっかりわかる教科書
    amazonリンク
    AWSのサービスの概要は大体理解したけど、実装まではできず

  • プログラミングスクール受講(ポテパンキャンプ)
    ポテパンのリンク
    gitの操作、N+1問題、Rspecの書き方はここで自主的に学んだ

  • Everyday Rails - RSpecによるRailsテスト入門 購入リンク
    ちょくちょく参考にできた。これも詰まったときに検索する用。

ポートフォリオ作成

当時はAWS,Docker, CI/CD, Kubernetes等についてはほぼほぼ理解できずに、断念していました。
開発環境なんかはrailsチュートリアルで使っていたcloud9を使っていました。
まずはHerokuに自分が一生懸命作成したアプリケーションをデプロイし、公開できるようにしました。
一応独自ドメイン,SSL化程度は行っておき、Herokuは有料プランを使用し、少しでも応答速度が早くなるようにしておきました。
一応当時のポートフォリオのソースコードのリンクを貼っておきます。
https://github.com/ak2-lucky/clothes-app
ファッションが好きだった僕は洋服のレビューサイトを作りました。

この記事を見ている駆け出しエンジニアの日々勉強されている方々はこう思っているかもしれません。
AWSにデプロイすらできないのに、webエンジニアになれるの?
Dockerで開発環境も構築できないの?
自動テストぐらいはやっといたら?

現役のwebエンジニアも同じことを思うでしょう。
ポートフォリオも作りきれないような奴はエンジニアになる資格なんかないよって。
なぜならポートフォリオだけは運にも左右されない自分の努力だけで100パーセント作りきれる成果物だからです。

確かにそうです。
僕の努力不足です。何の異論もありません。
認めます。

そして就職活動をはじめます。

就職活動時代

結果からゆうとほぼ全落ち。
面接までいったのは1.2回でした。
面談してくれた会社で研究開発で人材を募集しているからそこに来ないか?と言ってくれた企業もありました。(結局いかず)
コロナの影響とかいう言い訳はしません。
全て自分の実力不足。
アルバイトも採用している企業に応募し,1社だけ何とかアルバイトとして採用していただきました。

今回で自分の市場価値を知りました。
大学は何も考えずに過ごし、新卒で入社した会社を何の成果も残さず10ヶ月で退職。
世間はそんな奴のことを評価はしてくれません。
もちろん当然の評価です。

アルバイトとしてweb系自社開発企業で働く(今)

技術スタック:AWS,Docker,Laravel+vue.js

働いてみるまでLaravelはおろかPHPも触ったことありませんでした。vue.jsもですが。
詳細は省きますが、実際に働いてみて感じるのは、プログラムを書く以外のことです。
技術のキャッチアップ云々の話ではなくて、組織作り、開発の体制やフローなどの重要さについてです。
自分はプログラミングが苦ではありません。
しかし、プログラミング業務以外の部分でストップすることが多い場合があります。(例えば、なぜこの変更を加えられたのかというコメントがないandコードを見ても分からない)
連携がうまく取れなくて、個々の意思で変更が加えられたりするので、デザインがバラバラ。
issue作成者等に確認もしないで変更を進められていたり。
CI/CDもそのうちの一つですが、issueを作成するのは誰なのか、誰の判断を最終的に仰ぐのか、UIのデザインは好きに決めていいのか、プルリクではどこを見ればいいのか、など他にもいろいろありますが。。。

会社によって開発の進め方などは違うと思うので、一概にあれが悪い、これが悪いというわけではありませんが、開発体制や組織作りはサービス開発にかなり大きく影響するように感じました。

開発言語や技術以前にこういった根本的な開発の導線を確保する重要性を学びました。

最後に

ここまで読んでいただいた方には、いろいろ思うことがあると思います。
2ヶ月しか働いていない、しかもアルバイト如きが何を偉そうなこと言ってるんだ!
とか思ってる方いるかもしれません。

ですが、これは個人の一意見であります。
ただ同じように駆け出しエンジニアの方の参考になればいいなと思って書きました。

webエンジニアへの道は高く険しいように感じます。
しかし、自分にとって登りたい山がどれだけ高かろうが、険しかろうが、関係ありません。
ただ登るだけ
毎日頑張って積み上げて、疲れたら一緒にサボりましょう。

長くなりましたが、初投稿は以上になります。

ここまで読んでいただきありがとうございました。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Rails datetime_fieldでの取得で「有効な値を入力してください」とエラーが出た時の対処法

エラー発生

Railsで投稿フォームを実装していた時にPCでは問題なく動作していたのですが、

なぜかスマホで使おうとするとエラーが出る部分があったので書いておきます。

new.html.erb
<%= form_for @ride, method: :post do |f| %>
    <h1>新しいライドを投稿しよう!</h1>
    <label>タイトル</label>
    <p><%= f.text_field :title %></p>
    <label>予定日</label>
    <br />
    <%= f.datetime_field :sch_datetime %><br />
    <br />
    <input class="btn btn-primary" type="submit" value="投稿">
  <% end %>

config/initializers/time_formats.rb
Time::DATE_FORMATS[:datetime] = '%Y年%m月%d日 %H時%M分'
config/locales/application.rb
class Application < Rails::Application
    config.load_defaults 5.2
    config.i18n.default_locale = :ja
    config.assets.paths << config.root.join("vendor/assets/javascripts")
    config.assets.paths << config.root.join("vendor/assets/stylesheets/")
    config.action_view.embed_authenticity_token_in_remote_forms = true
    config.time_zone = 'Tokyo'
end

最初に記述していたのはこんな感じでdatetime_fieldを使うことで日時をまとめて取得できるようにしていました。

この方法でPCでは全く問題なく動作しているのを確認していたのでこの状態でデプロイしたのですが、

ふとスマホで動作確認しようと思い触ってみると投稿しようとすると日時の部分で

「有効な値を入力してください」とエラーがでて投稿できませんでした。。。

原因はなんだろう?

と考えてみましたがPCで正常に動作しているのでコードのミスではないと推測しました。

スマホとPCで入力する時のフォームも変化しているのでdatetime_field自体に問題がありそうだな〜と

思ったのでdate_fieldとtime_fieldに分けて書いてみることにしました。

new.html.erb
<%= form_for @ride, method: :post do |f| %>
    <h1>新しいライドを投稿しよう!</h1>
    <label>タイトル</label>
    <p><%= f.text_field :title %></p>
    <label>予定日</label>
    <br />
    #ここから
    <%= f.date_field :sch_datetime %><br />
    <br />
    <%= f.time_field :sch_datetime %><br />
  #ここまで変更
    <br />
    <input class="btn btn-primary" type="submit" value="投稿">
  <% end %>

この状態で動作確認してみると無事問題なく動作しました!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

削除機能の追加方法

削除機能の追加の備忘録です。

設定手順

① ルーティングの設定 
・httpメソッド 「delete」

②削除ボタンの作成 →ビューファイルの変更
 ・条件の指定に注意。(例:ログインユーザかつ投稿したユーザ❓)
 

③コントローラのアクション作成
 ・「destroy」メソッドの定義。
 ・削除権限を考える。例は②と同様。

④削除後のビューファイルの作成。
 ・コントローラのアクションが「destroy」なので、ファイル名は「destroy」をつける。
 ・トップページのURL作成。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Secretsantasができるまで③  post機能(CRUD)

更新予定

memo
- index
- new
- show
- destroy
- edit

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Ruby on Rails】アプリケーション作成〜サーバー起動まで&ポート番号って何?

Ruby on Railsの初歩中の初歩ですが、まとめです。

1.アプリケーションを作成する。

ターミナルを起動します。

$ rails new アプリケーション名

上記コマンド実行により、入力したアプリケーション名と同名のフォルダが作成され、その中に開発に必要なフォルダやファイルが用意されます。

アプリケーション名/
  ├ app/ アプリケーションのメインフォルダ
  ├ config/ 設定情報に関するフォルダ
  ├ db/ データベースに関するフォルダ
  └: その他

2.サーバーを起動する。

ターミナルに入力

$ rails server

Google ChromeやSafariなどのブラウザでlocalhostを3000番ポートで開きます。

localhost:3000

スクリーンショット 2020-08-09 9.27.41.png
無事、Ruby on Railsが起動しました。

参考: Ruby on Rails5 学習コース I | プログラミングの入門なら基礎から学べるProgate[プロゲート]

ポート番号とはなんでしょうか?

今回、3000番ポートと出てきましたが、ポート番号という言葉は、インフラ関係の知識としては必須です。

インターネット用語1分解説~ポート番号とは~ - JPNICには、以下のように説明されています。

ポート番号とは、TCP/IP通信において、 コンピュータが通信に使用するプログラムを識別するための番号です。 ポート番号は16ビットの整数であり、 0番~65535番まであります。

更に深いところで、ポート番号には大きく分けて3種類あり
* ウェルノウンポート番号(0番~1023番) - 使用目的が定められたポート番号
* 登録ポート番号(1024番~49151番) - IANAが登録を受け付け、 公開
* ダイナミック/プライベートポート番号(49152番~65535番) - 誰でも自由に使用できるポートとして開放

上記のように分類されます。

ちなみに、今回は、Ruby on Railsだと3000番ポート、Djangoだと8000番ポートがデフォルトで使われていますが、この3000番と8000番は登録ポート番号(1024番~49151番)に該当する為、IANAが登録を受け付け、 公開できるようになっています。

IANAとは?

Internet Assigned Numbers Authorityの略称。
ドメイン名、IPアドレス及びAS番号、各プロトコルで使われるプロトコル名及び番号といったインターネット資源を管理する機能です。
IANAは、南カリフォルニア大学情報科学研究所(ISI)の故ジョン・ポステル(Jonathan Bruce Postel)氏が中心となり、1988年に設立されました。IANAはインターネットに関する最も古い機関の一つであり、その活動は1970年代にまで遡ることができます。
その後、1998年10月にICANNが設立され、IANAが行っていた各種資源のグローバルな管理・調整の役割は ICANNの一部局として引き継がれました。そのような経緯から、歴史的なことも含めインターネット資源を管理する機能を表す意味で使用されています。 引用:JPRS用語辞典|IANA(アイアナ)

TCP/IP通信やHTTPなどは、更に深掘りできるので機会があったら記事にする予定です。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Ruby on Railsの手順】アプリケーション作成〜サーバー起動まで&ポート番号って何?

Ruby on Railsの初歩中の初歩ですが、まとめです。

1.アプリケーションを作成する。

ターミナルを起動します。

$ rails new アプリケーション名

上記コマンド実行により、入力したアプリケーション名と同名のフォルダが作成され、その中に開発に必要なフォルダやファイルが用意されます。

アプリケーション名/
  ├ app/ アプリケーションのメインフォルダ
  ├ config/ 設定情報に関するフォルダ
  ├ db/ データベースに関するフォルダ
  └: その他

2.サーバーを起動する。

ターミナルに入力

$ rails server

Google ChromeやSafariなどのブラウザでlocalhostを3000番ポートで開きます。

localhost:3000

スクリーンショット 2020-08-09 9.27.41.png
無事、Ruby on Railsが起動しました。

参考: Ruby on Rails5 学習コース I | プログラミングの入門なら基礎から学べるProgate[プロゲート]

ポート番号とはなんでしょうか?

今回、3000番ポートと出てきましたが、ポート番号という言葉は、インフラ関係の知識としては必須です。

インターネット用語1分解説~ポート番号とは~ - JPNICには、以下のように説明されています。

ポート番号とは、TCP/IP通信において、 コンピュータが通信に使用するプログラムを識別するための番号です。 ポート番号は16ビットの整数であり、 0番~65535番まであります。

更に深いところで、ポート番号には大きく分けて3種類あり
* ウェルノウンポート番号(0番~1023番) - 使用目的が定められたポート番号
* 登録ポート番号(1024番~49151番) - IANAが登録を受け付け、 公開
* ダイナミック/プライベートポート番号(49152番~65535番) - 誰でも自由に使用できるポートとして開放

上記のように分類されます。

ちなみに、今回は、Ruby on Railsだと3000番ポート、Djangoだと8000番ポートがデフォルトで使われていますが、この3000番と8000番は登録ポート番号(1024番~49151番)に該当する為、IANAが登録を受け付け、 公開できるようになっています。

IANAとは?

Internet Assigned Numbers Authorityの略称。
ドメイン名、IPアドレス及びAS番号、各プロトコルで使われるプロトコル名及び番号といったインターネット資源を管理する機能です。
IANAは、南カリフォルニア大学情報科学研究所(ISI)の故ジョン・ポステル(Jonathan Bruce Postel)氏が中心となり、1988年に設立されました。IANAはインターネットに関する最も古い機関の一つであり、その活動は1970年代にまで遡ることができます。
その後、1998年10月にICANNが設立され、IANAが行っていた各種資源のグローバルな管理・調整の役割は ICANNの一部局として引き継がれました。そのような経緯から、歴史的なことも含めインターネット資源を管理する機能を表す意味で使用されています。 引用:JPRS用語辞典|IANA(アイアナ)

TCP/IP通信やHTTPなどは、更に深掘りできるので機会があったら記事にする予定です。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Rails】RSpecでテストしたい。そんなあなたの一歩を応援します【導入手順】

参考対象者

  • Rails6.0で、RSpecでテストしたいなと考えている方

環境

$ rails -v
Rails 6.0.3.1
$ ruby -v
ruby 2.7.0p0 (2019-12-25 revision 647ee6f091) [x86_64-darwin19]

RSpecを導入する

Gemfile
group :development, :test do
  gem 'rspec-rails'
end
$ bundle install

$ rails g rspec:install

gemをインストールし、設定ファイルをジェネレータで作成する。

.rspec
--require spec_helper
--format documentation

テストをドキュメント形式に設定する。

System Specを導入する ブラウザテスト

Gemfile
group :test do
  gem 'capybara', '>= 2.15'
  gem 'webdrivers'
end
$ bundle install

まずは、gemをインストールする。

spec/rails_helper.rb
RSpec.configure do |config|
# 一番下の直前に追加
  config.before(:each) do |example|
    if example.metadata[:type] == :system
      driven_by :selenium, using: :headless_chrome, screen_size: [1400, 1400]
    end
  end
end

ブラウザテストが機能するように、RSpecの設定を変更する。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[Rails] 画像の投稿機能を実装する

概要

Railsプロジェクトで掲示板サイトを作成中、画像投稿機能を実装する機会がありました。
備忘録としてここに手順を残しておきます。

1. Imageモデルの作成

Modelとマイグレーションファイルを作成

テーブルはpostsテーブルimageテーブルの2つを用意します。
imageテーブルのpost_idカラムがpostテーブルへのリレーションを持っています。

terminal
$ rails g model Image image_url:string post:references

作成されたマイグレーションファイル開いて確認をします。

db/migrate/年月日時_create_images.rb
class CreateImages < ActiveRecord::Migration[5.0]
  def change
    create_table :images do |t|
      t.string :image_url
      t.references :post, foreign_key: true

      t.timestamps
    end
  end

問題なくマイグレーションファイルが作成されているようです。

マイグレーションの実行

terminal
$ rails db:migrate

Image Modelを確認

app/model/image.rb
class Image < ApplicationRecord
  belongs_to :post
end

マイグレーションファイルでreferencesの設定をしたためbelongs_to :postが書かれています。

既存のPost Modelにリレーションを追加

has_many :imagesを書き足します。

app/models/post.rb
class Post < ApplicationRecord

  has_many :images #この行を追加
end

これで1対多の関係を表現できました。

2. accepts_nested_attributes_forを利用して1つのフォームから複数モデルの更新を可能にする

今回は、postを投稿した時にimageも同時に投稿出来るように一つのフォームで複数のモデルの登録をまとめて行うようにします。
その為に必要なのが

・accepts_nested_attributes_for

です。
これを使うとhas_many関連の子レコードをまとめて登録出来るようになります。

入れ子のフォームを扱う為の下準備

テーブルをまとめて登録するために入れ子のフォームを作成することになります。それを可能にするためにaccepts_nested_attributes_forというメソッドを使いましょう。

それでは、accepts_nested_attributes_forの設定を行ます。
Postモデルに以下のように設定を追記します。

app/models/post.rb
class Post < ApplicationRecord

  has_many :images
  accepts_nested_attributes_for :images #この行を追加
end

postsコントローラーの編集

posts_controller.rbにも設定を追記していきます。

app/controllers/posts_controller.rb
class PostsController < ApplicationController

  def new
    @post = Post.new
    @post.images.build #この行を追加
  end

  def create
    @post = current_user.posts.build(post_params)
    if @post.save
      flash[:success] = 'メッセージを投稿しました。'
      redirect_to root_url
    else
      @posts = current_user.feel_posts.order('created_at DESC').page(params[:page]).per(10)
      flash.now[:danger] = 'メッセージを投稿に失敗しました。'
      render 'posts/new'
    end
  end

  private

  def post_params
    params.require(:post).permit(:content, :security, images_attributes: [:image_url]) #この行を追加
  end

@post.images.build
とparams内の
images_attributes: [:image_url]
を追記しました。
nested modelの許可するパラメーターの値はparams内images_attributes:を使って記述します。

fields_forを使ってフォームの中に入れ子を作る

views/posts/new.html.erb
<%= form_for(@post) do |f| %>
  <div class="form-group">
    <%= f.label :content, 'コメント' %>
    <%= f.text_area :content, class: 'form-control', rows: 5, placeholder: 'コメントを入力してください'  %>
  </div>

  <div class="form-group">
    <%= f.label :security, 'Security_Level' %>
    <%= f.number_field :security, class: 'hoge', min: 0, max: 100 %>
  </div>

  <%= f.fields_for :images do |i| %>  #この行に追加
    <%= i.file_field :image_url %>
  <% end %>

  <div class="text-right">
    <%= f.submit 'Post', class: 'btn btn-primary' %>
  </div>
<% end %>

さて、これで一つのフォームで複数モデルの登録をまとめて行うよにはできました。
次に画像のアップロード機能を作ります。

3. CarrierWaveをインストールして画像をアップロードできるようにする

Gemfileに「CarrierWave」gemを追加します。

Gemfile
gem 'carrierwave' #画像アップロード

bundle installを実行します。

terminal
$ bundle install

アップローダーの作成

terminal
$ rails g uploader image

imageのところは、適当な名前を設定してください。今回は、imageと名付けました。
コマンドを実行すると、

create app/uploaders/image_uploader.rb

となり、imageアップローダーが作成されました。

モデルの関連付け

/models/image.rbに以下を追記し、カラムの名前をmount_uploaderに指定します。

app/models/image.rb
class Image < ApplicationRecord
  belongs_to :post

  mount_uploader :image_url, ImageUploader #この行に追加
end

imageモデルにはimage_urlというカラムがあり、そこに画像のURLを格納するような仕様になっています。
mount_uploaderにカラムを指定することでCarrierwaveがカラム更新時に自動で画像のアップロードから、アップロード先のURL保存を行ってくれます。

Carrierwaveで保存した画像をViewに表示する

view/posts/_posts.html.erb
 <div>
   <%= link_to post.user.name, user_path(post.user) %><span class="text-muted">posted at<% post.created_at %></span>
 </div>
 <div>
   <p><%= post.content %></p>
 </div>
 <div>
   <% post.images.each do |image| %>  
     <%= image_tag image.image_url.url %>  #ここに表示
   <% end %>
 </div>
 <div>
   <p>Security_Level <%= post.security %></p>
 </div>

 <div class="batton">
   <%= render 'favorites/favorite_button', post: post %>
   <% if current_user == post.user %>
     <%= link_to "Delete", post, method: :delete, data: { confirm: "本当に削除しますか?" }, class: 'btn btn-danger btn-xs' %>
   <% end %>

以上で画像投稿機能が実装できました。

終わりに

以上でRailsプロジェクトに画像の投稿機能を実装することができました。
画像の複数投稿など改善できる点はありますが、とりあえずひと段落です。

ありがとうございます。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

画像の投稿機能

はじめに

初心者なので間違ってるところがあれば教えてください(>_<)

掲示板サイトのpostに画像投稿機能をつけました。
難しかったので再確認の為に記事を書きます。

今回はpostに対して複数の画像を投稿出来るようにしたかったのでpostに対して1対多の関係になるようにimageモデルを作りました。

1. Imageモデルの作成

Modelとマイグレーションファイルを作成します!

$ rails g model Image image_url:string post:references

作成されたマイグレーションファイル開いて確認をします!

db/migrate/年月日時_create_images.rb
class CreateImages < ActiveRecord::Migration[5.0]
  def change
    create_table :images do |t|
      t.string :image_url
      t.references :post, foreign_key: true

      t.timestamps
    end
  end

特に変更する所はありません。
カラムが合っているか確認します。

マイグレーションの実行

$ rails db:migrate

Image Modelを開きます

app/model/image.rb
class Image < ApplicationRecord
  belongs_to :post
end

既にbelongs_to :postが書かれています。

Post Modelを開きます

app/models/post.rb
class Post < ApplicationRecord
  belongs_to :user

  validates :content, presence: true, length: { maximum: 255 }

  has_many :favorites
  has_many :likeds, through: :favorites, source: :user
end

has_many :imagesを書き足します!

app/models/post.rb
class Post < ApplicationRecord
  belongs_to :user

  validates :content, presence: true, length: { maximum: 255 }

  has_many :favorites
  has_many :likeds, through: :favorites, source: :user

  has_many :images #この行を追加
end

これでとりあえず1対多の関係はできました。

2. accepts_nested_attributes_forとfields_forを使ってhas_many関連の子レコードを作成/更新するフォームを作成

今回は、postを投稿した時にimageも同時に投稿出来るように一つのフォームで複数のフィールドの登録をまとめて行うようにします。
その為に必要なのが

・accepts_nested_attributes_for
・fields_for

です!
これを使うとhas_many関連の子レコードをまとめて登録出来るようになります!

入れ子のフォームを扱う為の下準備

テーブルをまとめて登録するために入れ子のフォームを作成することになります。それを可能にするためにaccepts_nested_attributes_forというメソッドを使いましょう。

それでは、accepts_nested_attributes_forの設定を行ます。
post.rbに追記していきましょう。

app/models/post.rb
class Post < ApplicationRecord
  belongs_to :user

  validates :content, presence: true, length: { maximum: 255 }

  has_many :favorites
  has_many :likeds, through: :favorites, source: :user

  has_many :images
  accepts_nested_attributes_for :images #この行を追加
end

posts_controller.rbの追記

posts_controller.rbにも追記していきます。

app/controllers/posts_controller.rb
class PostsController < ApplicationController

  def new
    @post = Post.new
    @post.images.build #この行を追加
  end

  def create
    @post = current_user.posts.build(post_params)
    if @post.save
      flash[:success] = 'メッセージを投稿しました。'
      redirect_to root_url
    else
      @posts = current_user.feel_posts.order('created_at DESC').page(params[:page]).per(10)
      flash.now[:danger] = 'メッセージを投稿に失敗しました。'
      render 'posts/new'
    end
  end

  private

  def post_params
    params.require(:post).permit(:content, :security, images_attributes: [:image_url]) #この行を追加
  end

@post.images.build
とparams内の
images_attributes: [:image_url]
を追記しました。
nested modelの許可するパラメーターの値はparams内images_attributes:を使って記述します。

fields_forを使ってフォームの中に入れ子を作る

views/posts/new.html.erb
<%= form_for(@post) do |f| %>
  <div class="form-group">
    <%= f.label :content, 'コメント' %>
    <%= f.text_area :content, class: 'form-control', rows: 5, placeholder: 'コメントを入力してください'  %>
  </div>

  <div class="form-group">
    <%= f.label :security, 'Security_Level' %>
    <%= f.number_field :security, class: 'hoge', min: 0, max: 100 %>
  </div>

  <%= f.fields_for :images do |i| %>  #この行に追加しました。
    <%= i.file_field :image_url %>
  <% end %>

  <div class="text-right">
    <%= f.submit 'Post', class: 'btn btn-primary' %>
  </div>
<% end %>

さて、これで一つのフォームで複数のフィールドの登録をまとめて行うよにはできましたがまだ画像をアップロードできません(+_+)

次は、CarrierWaveというgemを使って画像をアップロード出来るようにしていきます!!

3. CarrierWaveをインストールして画像をアップロードできるようにする

Gemfileにgemを追加します。

Gemfile
gem 'carrierwave' #画像アップロード
$ bundle install

コマンドを実行します!

アップローダーの作成

$ rails g uploader image

imageのところは、適当な名前を記入してください。今回は、imageと名付けました。
コマンドを実行すると、

create app/uploaders/image_uploader.rb

となり、アップローダーが作成されました。

モデルの関連付け

/models/image.rbに以下を追記し、カラムの名前をmount_uploaderに指定します。

app/models/image.rb
class Image < ApplicationRecord
  belongs_to :post

  mount_uploader :image_url, ImageUploader #この行に追加
end

imageモデルにはimage_urlというカラムがあり、そこに画像のURLを格納するような仕様になっています。

Viewに表示

view/posts/_posts.html.erb
 <div>
   <%= link_to post.user.name, user_path(post.user) %><span class="text-muted">posted at<% post.created_at %></span>
 </div>
 <div>
   <p><%= post.content %></p>
 </div>
 <div>
   <% post.images.each do |image| %>  
     <%= image_tag image.image_url.url %>  #ここに表示
   <% end %>
 </div>
 <div>
   <p>Security_Level <%= post.security %></p>
 </div>

 <div class="batton">
   <%= render 'favorites/favorite_button', post: post %>
   <% if current_user == post.user %>
     <%= link_to "Delete", post, method: :delete, data: { confirm: "本当に削除しますか?" }, class: 'btn btn-danger btn-xs' %>
   <% end %>

以上で画像投稿機能終わりです!!

終わりに

今回複数の画像を投稿出来るようにしたかったのですが、今のままだと画像を一つしか投稿できませんでした。
勉強不足です。すみません。(>_<)

また複数画像を投稿出来るやり方がわかったら記事を書こうと思います!!!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

RailsアプリをAWSにあげるために必要な知識

はじめに

プログラミング未経験の筆者がRailsアプリをAWSにあげるのに、必要となった最低限の知識をざっくりとまとめました。

まとめた内容は以下の通りです。
・AWS
・VPC
・EC2
・RDS

AWSのネットワークサービス

image.png
参照:アベイラビリティゾーンとは

まずはじめにAWSのネットワークについてです。
AWSを使うときにはじめに触れるのがリージョンアベイラビリティーゾーン(AZ)です。

リージョン

リージョンはAWSがサービスを提供している拠点(国と地域)のことを指しています。
遠いリージョンをを使うとネットワーク遅延が発生してしまう可能性があるので、基本的には東京リージョンを使いましょう。

アベイラビリティーゾーン(AZ)

アベイラビリティーゾーン(AZ)データセンター(サーバー機などのIT機器を設置・収容する場所を提供し、安定的に運用できるようさまざまなサービスを提供する施設)とほぼ一緒です。
AZはリージョンごとに用意されていて、東京リージョンでは4つのAZが用意されています。

AWSでは複数のAZを利用すること(マルチAZ構成)が推奨されています。
マルチAZ構成であれば、もし一つのAZに障害が起きても、別のAZを利用することでネットワーク障害を回避できるからです。

続いてAWSのサービスについて説明していきます。

VPC(Virtual Private Cloud)

image.png

参照:VPC とサブネット

VPCはネットワークを作成するサービスです。
上図の通りAWSのネットワークの中にVPCのネットワークを作成します。
そしてVPCはサブネットを作成することで分割できます。

ざっくり言うと
大きな箱(AWS)の中にそこそこ大きい箱(VPC)があって、その中に小さな箱(サブネット)があるイメージですね。

そして、この小さな箱(サブネット)の中にこれから説明するEC2やRDSが入っていきます。

EC2(Elastic Compute Cloud)

image.png

参照:インスタンスの開始方法

EC2は仮想サーバ(インスタンス)ファイアウォール(セキュリティグループ)などを利用できるサービスです。

知らない単語が出てきましたね...

ざっくり説明していきます。

インスタンス

インスタンスは従来のオンプレミス環境上のサーバに相当します。

インスタンスはOS、CPU、メモリ等の情報を持っています。

つまり「インスタンスを作成する」というのは
「OS、CPU、メモリ等の条件を選択し、自分が求めるサーバーを作成する」ことです。

セキュリティグループ

セキュリティグループはAWS標準のファイアウォール機能です。
EC2インスタンスへのアクセスを許可したり、トラフィックを制御することができます。

デフォルトでは全ての通信が遮断してあります。(重要)
そのため特定の通信を許可する必要があります。

アクセスの許可は通信の方向で分けられ、インバウンドアウトバウンドに分けられています。
インバウンド: 外部からインスタンスへの通信を許可(外側→インスタンス)
アウトバウンド: インスタンスから外部への通信許可(インスタンス→外側)

初心者がAWSを扱う上で一番エラーが発生しやすい部分がこのセキュリティグループだと思います。

複数のサービスを紐づけるためにセキュリティグループは必須なのでよく理解しておきましょう。

RDS(Relational Datebase Service)

image.png

参照:VPC の DB インスタンスにアクセスするシナリオ(公式)

RDSはクラウド上でリレーショナルデータベース(RDBMS)を利用できるサービスです。

AWS上でRDBMSを利用する方法は2種類あります。(重要

1. EC2インスタンスにRDBMSをインストールする方法
2. RDSを利用する方法

RDSではデータベース用のインスタンス(仮想サーバー)が作成され、その上にOSやデータベースエンジンが構築されます。そのため、利用者はサーバやミドルウェアのメンテナンスが不要となります。

基本的にはRDSを利用した方が構築・運用のコスト削減できるため、RDBMSを運用する場合はRDSを選択されることが多いです。

まとめ

かなりざっくりですがAWSに関する知識をまとめました。

以下の記事を参考にしながら実際にAWSを触れば、詳細についての理解も深まると思います。

参照

世界一丁寧なAWS解説。EC2を利用して、RailsアプリをAWSにあげるまで

【画像付きで丁寧に解説】AWS(EC2)にRailsアプリをイチから上げる方法【その1〜ネットワーク,RDS環境設定編〜】

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

RailsのRoutesをcsvで出力

何を書いた記事か

Railsのroutes一覧をcsv形式で出力する方法

→ 新しい組織でシステムキャッチアップする際、ルーティングから辿って全体を俯瞰したい、その情報を体系的にSpreadSheetなどにまとめたい場合に利用できる

どうやるか

参考になるソース

railsのroutesの実装を参照
https://github.com/rails/rails/blob/5ccdd0bb6d1262a670645ddf3a9e334be4545dac/railties/lib/rails/tasks/routes.rake
- inspector に全てのRoute情報を詰めて、 .format() で整形すれば良さそう
- ConsoleFormatter の実装を真似て独自のFormatterを作れば良さそう

実践

適当なブランチを切る

  • 個人的な理解のために出力する情報なので、本番ソースに影響ださないよう、ローカルで適当なブランチを切る

taskを作成

$ bundle exec rails g task route_formatter csv
lib/tasks/route_formatter.rake
namespace :route_formatter do
  desc "get route as csv format"
  task csv: :environment do |t|
    class CSVFormatter
      def initialize
        @buffer= []
      end

      def result
        @buffer.join("\n")
      end

      def section_title(title)
      end

      def section(routes)
        routes.each do |r|
          @buffer << [r[:name], r[:verb], r[:path], r[:reqs]].join(",")
        end
      end

      def header(routes)
        @buffer << %w"Prefix Verb URI_Pattern Controller#Action".join(",")
      end

      def no_routes
        @buffer << ""
      end
    end
    require "action_dispatch/routing/inspector"
    all_routes = Rails.application.routes.routes
    inspector = ActionDispatch::Routing::RoutesInspector.new(all_routes)
    puts inspector.format(CSVFormatter.new, ENV['CONTROLLER'])
  end

end

実行

bin/rails route_formatter:csv
  • MacでClipboardに入れたい場合は下記
bin/rails route_formatter:csv | pbcopy
  • あとはExcelとかSpreadSheetで処理

参考リンク

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Rails5】gem gonの使い方 ~RailsからJSに変数を渡す方法~

実装した機能

開発環境

ruby > 2.6.5
rails > 5.2.4.2
gon > 6.3.2

今回はシンプルに、RailsのControllerで定義した変数をJSに渡してhtmlに表示します。
Railsに標準搭載されているhoge.js.erb形式やcoffeescriptで書いたほうがスムーズだったりしますが、うまく表示できないときの回避策としても使えるGemかなと思ったのでご紹介します。

※注意
Gemの仕様上、htmlソース内に変数自体が表示されるので、セキュリティ的に隠す必要があるものには使わないほうが良いです。

導入方法

まずは、Gemfileに追加

Gemfile
gem 'gon'

そして、インストール

Terminal
$ bundle install

RailsのView内にコードを記述
今回は全ページで使う想定ですが、必要なviewに記述されていればOKです。
JSを読み込むのと同じく、読み込みのタイミングによって挙動が異なるので読み込み順には注意しましょう。

application.html.erb
・・・
<%= include_gon %>
<%= javascript_include_tag "application" %>
・・・
</body>

これで準備完了です。

変数を渡す

RailsのControllerでGon用の変数を定義します。
といっても、変数の頭にgon.をつけるだけです。

Users.erb
def show
  @user = User.find(1)
  gon.username = @user.name #これをJSに渡します
end

JSに変数を渡してhtmlに表示します。

index.html.erb
・・・
<p id="name"></p>
・・・
application.js
・・・
let name = gon.username
$('#name').html(name);
・・・

このように表示されればOKです。

index.html
・・・
<p id="name">こうへい</p>
・・・

html内の表示について

冒頭で「html内に変数が見えちゃう」という話をしましたが
実際にはこのように読み込まれています。
良くも悪くもわかりやすい構造になっていますね笑

index.html
・・・
  <script>
    //<![CDATA[
      window.gon={};gon.username="こうへい";
    //]]>
  </script>
</body>
・・・

その他機能

単純に変数を渡す以外にも

  • 配列、ハッシュを渡す
  • 変数をすべて読み込む

などの使い方もできるようです。
むしろ、Gemの役割としてはこっちのほうが大きいのかもしれませんね。
詳しくは公式ページをご確認ください。

Gon公式
https://github.com/gazay/gon

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[Rails]コントローラでUserAgentを取得する

UserAgentとは?

UserAgentとはHTTPリクエストヘッダーに含まれるWEBの使用環境に関する情報です。
ブラウザの種類、ブラウザのバージョン、端末のOSの種類などの情報が含まれています。

HTTPリクエストヘッダーとは?

HTTPリクエストヘッダーとはWEBサイトにアクセスされた時にブラウザからWEBサイト側に送られるリクエスト情報と一緒に送られる付加的な情報です。
UserAgent、Referer(リンク元URL)、Authorization(認証情報)などの情報があります。

RailsにおけるUserAgentの取得方法

Railsのコントローラにはrequestオブジェクトを指すアクセサメソッドが用意されており、
それを利用することでコントローラにおいて、以下のように簡単にUserAgentを取得することができます。

request.user_agent

UserAgent以外にも色々と取得できるrequestオブジェクト

requestオブジェクトを利用すると以下のようにリクエスト情報を簡単に取得することができます。

request.url           # リクエストで使われるURL全体
request.remote_ip     # クライアントのIPアドレス
request.query_string  # URLのクエリ文字


(参考)
Railsガイド:requestオブジェクトとresponseオブジェクト

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[ruby]ドリルアウトプット

内容

image.png

実装

image.png

解説

今回作成したのは、1〜10までの数字を順番に足し合わせていくプログラムです。
私が最初に試したコードが下記です。
image.png
出力されたものが下記です。
image.png
このプログラムだと1+2+3+4+5...となってしまっているので失敗です。

それでは、どうすればよいのか(-_-;)
1つずつ説いていきましょう

①合計値を保存しておく変数sumを用意する
②変数sumに1〜10の数値を順番に足していく
③順番に足していく処理をtimes文の繰り返しで置き換える
④変数sumの値をターミナルに出力

まず①です。
1に2を足し、
その結果に3を足し、
その結果に4を足し、
その結果に5を足し、...と10まで繰り返していきます。

よって常に結果を保存しておく変数が必要になります。これを変数名sumとして定義しておきます。まだ何も足してない状態なので、sumには0を代入しておきます。

②変数sumに1〜10の数値を順番に足していく
変数sumに1〜10の数値を順番に足していくプログラムをそのまま書いてみましょう。
image.png
このコードは非常に長く、かつ同じ処理が続いてるため、times文を使って効率的なコードに書き換えます。

③順番に足していく処理をtimes文の繰り返しで置き換える
times文を使えば、何度も繰り返される同じ処理をまとめることができます。今回まとめられるのはsum += 数値の部分です。

times文は繰り返したい回数.timesと記載して繰り返す数を決めます。今回は1〜10まで順番に足していくため、10回同じような処理が繰り返されます。よって繰り返したい回数は10回です。
image.png
数値の部分はどうすればいいでしょうか。繰り返す回数ごとにこの数値は変わります。1回目は1、2回目は2、3回目は3となります。つまり、繰り返しの回数と同じです。
times文では、変数iの中に繰り返しの回数が数値として自動で代入されます。よって、変数iを使えば繰り返しの回数を変数sumに足していくことができます。
ただし、プログラムなので1回目のiの数値は0となります。よってsumに足すのは1増やしたi + 1にしましょう。
image.png
④変数sumの値をターミナルに出力
最後にputsメソッドでsumをターミナルに出力すれば終了です。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

bundle install でmysql2がインストールされない

はじめに

僕のローカル環境で毎回エラーになるので解決策をメモします
*まだ厳密な原因はわかってませんが、とりあえずこれで通りました程度の内容です

$ bundle install --path vendor/bundle 
...
エラー文↓
An error occurred while installing mysql2 (0.5.3), and Bundler cannot continue.

解決方法

$ bundle config --local build.mysql2 "--with-ldflags=-L/usr/local/opt/openssl/lib"
$ bundle install --path vendor/bundle

上記コマンドを実行すると、.bundle/configに下記一行が追加されます

BUNDLE_BUILD__MYSQL2: "--with-ldflags=-L/usr/local/opt/openssl/lib"

とおるようになる。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Rails Tutorialを咀嚼する【第1章ゼロからデプロイまで】

1.1 はじめに

■REST
SQLでよく使う「Create/Read/Update/Delete」をそれぞれ「GET/POST/PUT/DELETE」に当てはめたもの。セッションなどの状態管理を行わないため、命令をいちいち書いていく必要がある。
基本的には「route.rb」に記載する。

■コマンドライン
ターミナル。クラウドIDEに標準的に備わっている。

1.2 さっそく動かす

■Cloud9
AWSが提供しているクラウド上で開発可能な統合開発環境。面倒な環境設定もいらないため超便利

■gem
パッチファイル?追加要素?みたいなもの。「Gemfile」というファイルに記載して、bundle installとターミナルに打ち込むと自動でインストールしてくれる。

1.3 最初のアプリケーション

■rails new
Railsを使ってアプリケーションを作る際に初めに書く呪文。必要なファイルを自動で生成してくれる。

■フレームワーク
Railsがフレームワーク。エディタがあれば自由にプログラミングできるが、将来的にめちゃくちゃな書き方になってしまうため、「ある程度書き方を揃えましょうね」というもの。
Rubyで書くと何十行も掛かる処理をRailsを使えば独自の短い表現で同じ処理ができる。まだ実感値はない。

■gameごとのバージョン
バージョンが違うと挙動も違う可能性があるので、バージョンを固定させて開発をした方が良い。
spring 2.0.2がインストールできないときは「bundle update spring」を打ってから再度インストール。

【演習】
railsサーバーを立ち上げれた先に書いてある。

■MVCモデル
どこにどのファイルを置くのかを定義した概念。本来どこに何を置いてもいいが、後々管理が面倒になるため、ある程度統一性をもって書こうというもの。
どこに何を書くべきかという実感値はまだない。

■renderメソッド
レスポンスの出力をするメソッド。コントローラーでもビューでも使う。

■メソッド
関数。defとendの間に挟んで使う。
呼び出すときは定義したメソッド名を書く。

■routes.rb
どのリクエストにはどのページを返すか、を記載する。
基本的にはコントローラーを記載するのかな?

■1.3.4 Hello, world!に書き換える
最初の「Yay!You're on Rails!」をHello, world!に書き換える。
今回は大した内容じゃないので恐らくビューはいじらない。
「hello, world!」というHTMLを表示する、というrenderメソッドをコンロトーラーで定義して、
rootをhelloメソッドにする。

【演習】
1.文面を変えればOK
2.Windowsだから表示の仕方が分からないため跳ばす。
3.
def goodbye
render html: "goodbye, world!"

end

Rails.application.routes.draw do
root 'application#goodbye'
end

こんな感じ。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Rails Tutorialを咀嚼する【第1章ゼロからデプロイまで】前半

1.1 はじめに

■REST
SQLでよく使う「Create/Read/Update/Delete」をそれぞれ「GET/POST/PUT/DELETE」に当てはめたもの。セッションなどの状態管理を行わないため、命令をいちいち書いていく必要がある。
基本的には「route.rb」に記載する。

■コマンドライン
ターミナル。クラウドIDEに標準的に備わっている。

1.2 さっそく動かす

■Cloud9
AWSが提供しているクラウド上で開発可能な統合開発環境。面倒な環境設定もいらないため超便利

■gem
パッチファイル?追加要素?みたいなもの。「Gemfile」というファイルに記載して、bundle installとターミナルに打ち込むと自動でインストールしてくれる。

1.3 最初のアプリケーション

■rails new
Railsを使ってアプリケーションを作る際に初めに書く呪文。必要なファイルを自動で生成してくれる。

■フレームワーク
Railsがフレームワーク。エディタがあれば自由にプログラミングできるが、将来的にめちゃくちゃな書き方になってしまうため、「ある程度書き方を揃えましょうね」というもの。
Rubyで書くと何十行も掛かる処理をRailsを使えば独自の短い表現で同じ処理ができる。まだ実感値はない。

■gameごとのバージョン
バージョンが違うと挙動も違う可能性があるので、バージョンを固定させて開発をした方が良い。
spring 2.0.2がインストールできないときは「bundle update spring」を打ってから再度インストール。

【演習】
railsサーバーを立ち上げれた先に書いてある。

■MVCモデル
どこにどのファイルを置くのかを定義した概念。本来どこに何を置いてもいいが、後々管理が面倒になるため、ある程度統一性をもって書こうというもの。
どこに何を書くべきかという実感値はまだない。

■renderメソッド
レスポンスの出力をするメソッド。コントローラーでもビューでも使う。

■メソッド
関数。defとendの間に挟んで使う。
呼び出すときは定義したメソッド名を書く。

■routes.rb
どのリクエストにはどのページを返すか、を記載する。
基本的にはコントローラーを記載するのかな?

■1.3.4 Hello, world!に書き換える
最初の「Yay!You're on Rails!」をHello, world!に書き換える。
今回は大した内容じゃないので恐らくビューはいじらない。
「hello, world!」というHTMLを表示する、というrenderメソッドをコンロトーラーで定義して、
rootをhelloメソッドにする。

【演習】
1.文面を変えればOK
2.Windowsだから表示の仕方が分からないため跳ばす。
3.

app/controllers/application_controller.rb
def goodbye
    render html: "goodbye, world!"
end
config/routes.rb
Rails.application.routes.draw do
  root 'application#goodbye'
end

こんな感じ。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

selfとは

selfとは

オブジェクトそのもの。メソッドの中では、そのメソッドが属しているインスタンスをselfという名前の擬似変数で参照できる。他の言語でいうthis。

selfの特徴

メソッドの中で、レシーバを省略したメソッド呼び出しが行われた時は、selfがレシーバとなる。
レシーバは省略できる場合には省略することが多い。

使い方

class Numbers
  attr_accessor :number
  def set_number
    self.number = 30 #このクラスのnumberを呼んだ時に30を入れておく
  end
end

num1 = Numbers.new
num1.set_number
num1.number # => 30
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む