20210305のRubyに関する記事は22件です。

【Rails】ルーティングを名前空間でグループ分けしている場合のform_withの記法【Ruby】

はじめに

ヘルパーメソッドのform_withを使用して入力フォームを作ろうとしていたところ、NoMethodErrorが出てしまい詰まっていました。
スクリーンショット 2021-03-05 21.50.46.png

結論

route.rbにおいてルーティングを名前空間shopsでグループ分けしていたにもかかわらず、shopsをform_withの引数に渡していなかった。

コード

route.rb
namespace :shops do
    resources :posts  
---中略---
end
shops/posts_controller.rb
class Shops::PostsController < ApplicationController
  --- 中略 ---
  def new
    @post = Post.new
  end
  --- 中略 ---
end

shops/post/new.html.erb
<%= form_with model:[:shops,@post], local: true do |f| %>
      --- 中略 ---
    <div>
      <%= f.submit "送信"%>
    </div>
<% end %>

resourcesをネストしているときに親モデルを引数に渡すのと同じ感覚です。

参考

https://techracho.bpsinc.jp/ohno/2019_12_10/84349
https://railsdoc.com/page/form_with

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

binding.pryを使用したエラー解決例

①controllerでbinding.pryを設定します。

def create
    binding.pry
    comment = Comment.create(comment_params)
    redirect_to "/items/#{comment.item_id}"
  end

②ターミナルでcreateを確認すると、ROLLBACKが表示されています。

[3] pry(#<CommentsController>)> comment = Comment.create(comment_params)
   (0.2ms)  BEGIN
  ↳ (pry):3:in `create'
  User Load (0.5ms)  SELECT `users`.* FROM `users` WHERE `users`.`id` = 11 LIMIT 1
  ↳ (pry):3:in `create'
   (0.1ms)  ROLLBACK
  ↳ (pry):3:in `create'
=> #<Comment:0x00007fe2f9494f38 id: nil, user_id: 11, item_id: 24, text: "a", created_at: nil, updated_at: nil>

③comment.errors.full_messages こちらの記述でエラーメッセージを取得します。

[4] pry(#<CommentsController>)> comment.errors.full_messages
=> ["Tweet must exist"]

④バリデーションのエラーなのでmodels/comment.rbを確認します。

class Comment < ApplicationRecord
  belongs_to :tweet
  belongs_to :user
end

⑤アソシエーションをitemに変更して修正完了です。

class Comment < ApplicationRecord
  belongs_to :item
  belongs_to :user
end
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Rails】私が成長を実感したエラーの対処法

はじめに

本記事では、私がRailsで学習をする際に、エラーが出た場合の向き合い方について記載しております。
「エラーが出たときが成長する一番のチャンス」という考えの元、エラーとしっかり向き合う姿勢を持って取り組んできたので、その方法を共有します。

前提

以下のgemをインストールします。
既に導入済みの方は読み飛ばしてください?‍♂️

導入するgem一覧
① better_errors
② binding_of_caller
③ pry-byebug

better_errorsとは

Better Errors replaces the standard Rails error page with a much better and more useful error page. It is also usable outside of Rails in any Rack app as Rack middleware.
(better_errorsのGitHub公式から引用)

要するに、標準のRailsのエラーページをより見やすく、より便利なエラーページに置き換えてくれるgemです。

binding_of_callerとは

Using binding_of_caller we can grab bindings from higher up the call stack and evaluate code in that context. Allows access to bindings arbitrarily far up the call stack, not limited to just the immediate caller.
(binding_of_callerのGitHub公式から引用)

要するに、binding_of_callerを使うと、irbを使用して、エラー画面上でコードを評価することができるようになるということです。

pry-byebugとは

Adds step-by-step debugging and stack navigation capabilities to pry using byebug.
(pry-byebugのGitHub公式から引用)

要するに、pryを使用してデバッグするためのデバッグツールです。
irbのように対話的にrubyを実行できるようになります。

To use, invoke pry normally. No need to start your script or app differently. Execution will stop in the first statement after your binding.pry.
(pry-byebugのGitHub公式から引用)

ブレークポイントをうちたい場所にbinding.pryを書いて処理を実行すればその箇所で処理が止まり、変数の値などを確認できるようになります。

では3つのgemをインストールしましょう

Gemfile
gem 'better_errors'
gem 'binding_of_caller'

group :development, :test do
  gem 'pry-byebug'
end

ターミナルで$bundle installを行えばgemのインストールは完了です。

エラーの解決方法

① エラーログを確認する

エラー画面に表示される「エラー文」「トレース情報」「irb」をもとに『エラーの本質』と『エラーの場所』を特定します。
スクリーンショット 2021-03-05 20.36.59.png

② デバッグ

エラーの原因と場所が特定できたら、デバッグを行い「どのようなことが」「どんな風に起こったのか」をさらに詳しく具現化します。
エラー画面のirb上でも変数の値などを確認できます!
スクリーンショット 2021-03-05 20.37.23.png

③ 情報収集

エラーログとデバッグで得た情報をもとに、公式ドキュメントやGitHubの公式ページを見て問題に対応する情報を集めます。

④ 収集した情報をもとに仮説を立てる

集めた情報を自分で組み立てて仮説を立てます。
→この過程が一番頭を使うので成長していると実感できます。

⑤ 仮説をもとに検証する

仮説をもとに実際に検証します。
解決できない場合は再度仮説を立てて検証します。

⑥ 解決できるまで②〜⑤を繰り返す

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

Railsでおすすめ機能を作る

質問掲示板風サイトを作っている時、おすすめ機能を実装したいと思ったので作りました。

前提

・既読機能がある
・タグ機能がある(acts-as-taggable-on使用)
・devise使用

流れ

①自分が最近見た記事から30件取得
②記事に紐づいているタグを取得し、さらにその中から数が多い順に5件取得
③5件の中からランダムに1個のタグを取得
④取得したタグを含み、かつユーザー自身の投稿ではない投稿を取得
⑤他のユーザーからの既読数が多い投稿順に並べ替えて表示

実際の記述

参考程度にお願いします。(元はコントローラーに書いていたのですが、リファクタリングの際にService層を作りそこに移行したため)

app/controllers/top_pages_controller.rb
#Service層とやりとりするための記述です。実際の流れは次にあるのでそちらを参考にするといいと思います。

def index

    if user_signed_in?
      @recommend_tag   = Posts::Postservices.recommend_tag(current_user)
      @recommend_posts = Posts::Postservices.recommend_posts(current_user, @recommend_tag, params).includes(:user, :taggings)
    end

end
app/services/posts/postservices.rb
module Posts
  module Postservices
  
    def self.recommend_tag(current_user)
      #①自分が最近見た記事から30件取得
      recommends = current_user.already_reads.order("created_at DESC").limit(RECENTLY_READ_POST_COUNT)
      #②記事に紐づいているタグを取得し...
      array = Array.new
      recommends.each do |reco|
        reco = Post.find_by(id: reco.post_id)
        reco = reco.tag_counts_on(:tags).pluck(:name) #(Postモデルからtagsカラムのタグ名を取得。tag_counts_onはacts-as-taggable-onのメソッド。)
        array.push(reco)
      end
      #②...数が多いものから順に5件取得&③5件の中からランダムに1個のタグを取得
      return array.compact
                  .flatten
                  .group_by{|e| e}
                  .sort_by{|_,v|-v.size}
                  .map(&:first)[0..4]
                  .sample
    end

    def self.recommend_posts(user_id, recommend_tag, params)
   #④取得したタグを含み、かつユーザー自身の投稿ではない投稿を取得
      posts = Post.tagged_with(recommend_tag).where.not(user_id: user_id)
     #⑤他のユーザーからの既読数が多い順に並べ替えて表示
      return posts.select('posts.*', 'count(already_reads.id) AS already_reads')
                              .left_joins(:already_reads)
                              .group('posts.id')
                              .order('already_reads desc')
                              .order('created_at desc')
                              .limit(DEFAULT_PAGE_ITEM_COUNT)
                              .page(params[:page]).per(DEFAULT_PAGE_ITEM_COUNT)
    end
end
end

config/initializers/constants.rb
#あとで修正しやすいように件数などは変数で渡しています
DEFAULT_PAGE_ITEM_COUNT = 10
RECENTLY_READ_POST_COUNT = 30
app/views/top_pages/index.html.rb
<!-- viewの参考程度においときます... -->
<div class="main-contents">
<% if user_signed_in? && @recommend_posts.present?%>
  <h3 class="title-index"><%=@recommend_tag%>に興味がある人におすすめ</h3>
      <% @recommend_posts.each do |reco| %>
          <div class="post-index">
          <div class="overall-container">
              <%= link_to post_path(reco.id) do %>
                <div class="title"><%= reco.title %></div>
              <% end %>

              <div class="tag-container">
                <% reco.tag_list.each do |tag| %>
                  <span class="post-tag"><%= link_to tag, root_path(tag_name: tag) %></span>
                <% end %>
              </div>

              <div class="other-container">
                <% if user_signed_in? %>
                  <div class="already-read"><%= render 'shared/alreadyread', post: reco %></div>
                <% end %>

                <div class="comments-count"><i class="far fa-comment"></i> <%=  reco.comments.count %></div>
                <div class="likes-count"><i class="far fa-heart"></i> <%=  reco.likes.count %></div>

                <div class="user-info">
                    <% if reco.user.image? %>
                      <div><%= image_tag post.reco.image.url, class: "user-index-icon" %></div>
                    <% else %>
                      <div><%= image_tag "/assets/default.jpg", class: "user-index-icon" %></div>
                    <% end %>
                    <div class="user-name"> <%= reco.user.name %></div>
                </div>
              </div>

          </div>

      </div>
    <% end %>
<div class="paginate"><%= paginate @recommend_posts %></div>

<% end %>

</div>

↓こんな感じで表示できます(CSSはお好みで調整してください)
スクリーンショット 2021-03-05 20.32.19.png

終わりに

自分で作ったおすすめ機能を紹介しました。拙い機能ではありますが、自分で考えて色々調べて実装した初めての機能なのでとても思い入れがあります。
ほぼコードを載せただけになってしまいましたが誰かの参考になれば幸いです。

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

【Rails】Bootstrap 4 Tag Input Plugin With jQueryを使ってタグの見た目をよくする

タグ入力後の見た目をよくしよう

題名通りBootstrap 4 Tag Input Plugin With jQueryを用いてタグ入力後の見た目をよくしていきます。
(2回目の)初投稿なので誤字や脱字など至らない点はあると思いますが、よろしくお願いいたします。

完成形

現在のタグ入力機能は下のような感じですが、このままだと殺風景なので
Image from Gyazo


↓のように入力後にきれいに装飾されるようにしてみましょう。
またエンターキーでもタグの登録ができるようになります
Image from Gyazo

前提

Rails 6.0.3.5
Bootstrap 4.5
jQuery導入済み
タグ機能を実装済み

Bootstrap 4 Tag Input Plugin With jQueryの導入

Bootstrap 4 Tag Input Plugin With jQueryの公式サイト

上の公式ページからダウンロードしてきましょう。


解凍すると
Bootstrap-4-Tag-Input-Plugin-jQueryというディレクトリができます。
ディレクトリ内の
tagsinput.js

app/javascripts

tagsinput.css

tagsinput.scss
に名前を変えて
app/javascripts/stylesheets
にいれましょう。


tagsinput.jsを読み込めるように記述します。

application.js
require('jquery')
require('tagsinput') //←これを追加します

tagsinput.scssを読み込むための記述もします。

application.scss
@import '~bootstrap/scss/bootstrap';
@import '~@fortawesome/fontawesome-free/scss/fontawesome';
@import 'tagsinput'; //←これを追加します。

導入はこれで終わりです。

データをdata-roleで送ってtagsinputを起動させよう。

タグの入力フォームにdata-roleを追加します。

new.html.erb
<div class="tags">
  <%= f.label :tag_list %>
  <%= text_field_tag 'post[tag_list]', @post.tag_list, data: {role: "tagsinput"} %>   # ←を追加  
</div>

これで
Image from Gyazo
のようにタグ入力後に装飾されるようになりました!

少し設定を変えてみましょう

現状だとタグが無限に登録できてしまします。

追加できるタグの数と最大文字数を設定しましょう。
tagsinput.jsの中身を少しみてみましょう。

tagsinput.js
    maxTags: undefined,
    maxChars: undefined,

こちらを見るとタグの文字数の縛りもないことがわかりますね!!!
こちらを変えていきましょう。

tagsinput.js
    maxTags: 4,
    maxChars: 8,

タグの最大数4と最大文字数8と設定できました。


Image from Gyazo

↑半角英数ならいいのですが、全角入力時に入力画面にずれがでてしまいます。
こちらを直していきましょう。

tagsinput.js
    this.inputSize = Math.max(1, this.placeholderText.length);

こちらを

tagsinput.js
    this.inputSize = Math.max(20, this.placeholderText.length);

にかえてみましょう。
Image from Gyazo

いい感じになりましたね!!!

最後に

導入にするにあたっていろいろなエラーと戦いましたorz
bootstrap-tagsinput

最初はこちらを導入しようとしたのですが、古いためかなかなかうまく行かずorz
またTag itの導入もうまくいかずorz
いろいろ探し求めてこちらにたどり着きました。

またBootstrap 4 Tag Input Plugin With jQueryについての日本語の文献がなく、オプションなどについて英語の公式を参考にしました。
英語だからといって苦手意識を持たない。しっかりと読むことの大切さを知りました(遅い)
ついでにgifのマークダウン記法があるのを初めて知りました(遅い)


以上となります。拙い文章ですがご拝読いただきありがとうございました。

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

【Ruby】変数と定数のあれこれ

Rubyの変数や定数とは?

Ruby学習をしている中で、変数や定数の書き分けに混乱したのでまとめてみた。

【ポイント】
・変数や定数は以下のように宣言代入を同時に行う。
・変数名はスネークケースで書くことが一般的とされる。
・宣言された変数(定数)をスコープ内で呼び出して使用する。

# 数値
変数(定数) = 数値

変数(定数) = 数値 + 数値

# 文字列
変数(定数) = '文字列'

# 呼び出す
puts 変数名
puts "文字列#{変数名}文字列"

上記のように代入された変数を呼び出して使用する。

変数の種類と使い方

Rubyでは変数名の最初の一文字によって以下の変数/定数に区別される。

・ローカル変数
・インスタンス変数
・クラス変数
・グローバル変数
・定数

*上記以外にも疑似変数などがあるが、今回は割愛。

各変数の主な違いは「変数名の最初の一文字」「スコープ*」である。
*スコープ … 変数の有効範囲のこと。スコープ外では変数を参照できない。

ローカル変数

小文字もしくは'_'(アンダーバー)で始まる変数を「ローカル変数」と呼ぶ。 (*ASCII2の範囲外では変数名に漢字などを使える)
有効範囲(スコープ)は 宣言されたブロック、メソッド内、クラス/モジュール内のみ。一度有効範囲を抜けると消滅する。

# 「name」という変数に"Taro"という文字列を代入して変数を宣言
name = "Taro"

# 変数nameの呼び出し
puts name
#=> Taro

# 式展開*
puts "私は#{name}です。"
#=> 私はTaroです。

*式展開: #{変数名}という形で、ダブルコーテーションに囲まれた文字列の中に記述することで変数に格納されている値が文字列の中で展開される。

インスタンス変数

@で始まる変数を「インスタンス変数」と呼ぶ。
インスタンス変数は特定のオブジェクト(クラス)に所属している。
有効範囲は基本的に所属しているオブジェクト内部のみだが、ゲッター/セッターメソッドを使うことで外部から読み書きすることができるようになる。

class Menu #~~~~~インスタンス変数のスコープ~~~~~

  # 外部から @food を呼び出せるようにする
  attr_reader :food

  # インスタンスを初期化するときに使う(ことが多い)initializeメソッド
  def initialize(food)
    # メソッド内でインスタンス変数を宣言/代入
    @food = food
  end

  def order
    puts "#{@food}食べたい"
  end
end #~~~~~インスタンス変数のスコープ~~~~~


# インスタンスの作成
menu = Menu.new('そば')

# orderはクラス内で定義されているメソッドなのでゲッターがなくても呼び出せる
menu.order
#=> "そば食べたい"

# ゲッターメソッドを使ってスコープ外からインスタンス変数 "@food" を呼び出す
menu.food
#=> "そば"

クラス変数

@@で始まる変数を「クラス変数」と呼ぶ。
クラス内で定義する。
有効範囲は定義したクラス内のメソッドと継承したサブクラス、インスタンスである。
主にインスタンスに番号をつけたいときに使ってます。
*正直それ以外に思い浮かばなかった。。

class Menu 
  # クラス内のメソッド外で宣言/代入
  @@count = 0

  def initialize(food)
    @food = food
    # 1つインスタンスが作成される毎に@@countには+1代入される
    @@count += 1
  end

  def get_count
    @@count
  end
end

# インスタンス作成
menu1 = Menu.new('そば')
menu2 = Menu.new('うどん')

print("作成されたメニューの数:", menu1.get_count)
#=> "作成されたメニューの数: 2"

グローバル変数

$で始まる変数を「グローバル変数」と呼ぶ。
*$で始まる特殊変数(いわゆる組込変数)の場合もあるので注意

有効範囲はプログラム全体。
どこからでも読み書きが可能 → 知らない間に変数が書き換わっている可能性があるため、扱いには注意が必要。

$food = "そば"

puts $food

定数

アルファベット大文字で始まる識別子
(例: Xxx, XXx XXX)
・メソッド内での定義ができない
・一度定義した定数に再び代入を行おうとすると警告メッセージが出る(更新はされる)

# 軽減税率8%を定数に代入
REDUCED_TAX_RATE = 1.08

def calculation(price)
  puts (price * REDUCED_TAX_RATE).floor
end

# 引数:1,000円の
calculation(1000)
#=> 1080

まとめ

・各変数の違いは記述方法と有効範囲(スコープ)
・インスタンス変数をクラス外で呼び出したい場合はゲッターメソッドを使う
・変数/定数を効果的に使うことで柔軟かつスッキリした見た目にできるが、変数名選びがすごく重要。

参考

・Rubyリファレンスマニュアル
https://docs.ruby-lang.org/ja/latest/doc/index.html

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

attr_readerについて

 以下のコードにつき、rubocop -aを実行したところ、修正を頂戴しました。

app/helpers/question_helper.rb
class AddQuestion

  def initialize(a,b)
    @text = "#{a} + #{b}" 
    @answer = a + b
  end

# rubocop -a 実行前 -------------------------------   
  def text # ゲッター
    @text
  end

  def answer # ゲッター
    @answer 
  end
# rubocop -a 実行前 -------------------------------

# rubocop -a 実行後 -------------------------------
  attr_reader :text, :answer
# rubocop -a 実行後 -------------------------------  

end

 attr_readerとはなんだろうかと思い調べてみました。

クラスに設定したインスタンス変数の値を、インスタンスから読み取って表示するためだけに定義するメソッドをゲッターといい、attr_readerを用いてこれに代えることができるとのこと。
 
 なお、ここでは登場しないが、あるインスタンスが持つインスタンス変数の値を更新するためだけのメソッドのことをセッターといい、これはattr_writerで記述することができる。
 さらには、attr_accessorは両者を兼ねる。

  
 rubocop実行前後を見比べると勉強になります。

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

【Rails】renderメソッドのcollectionオプションの使い方

環境

macOS: Big Sur Ver11.2.2
Rails: 6.0.0
Ruby: 2.6.5

エラーの内容

ビューファイルで以下のようにrenderメソッドを使って部分パーシャルを呼び出したのだが、なぜかエラーが出て表示されなかった。

<div class="main-contents">
  <h2 class="main-title">新規登録店舗</h2>
  <div class="contents-bar">
    <%= render partial: "static_pages/new_users", collection: @users %>
  </div>
</div>

解決策

通常なら上記の記述でパーシャルファイルでは「user」として変数を利用できるが、なぜか変数がうまく渡っていなかった模様。
試しに以下の記述を追記したら無事に表示された。

<div class="main-contents">
  <h2 class="main-title">新規登録店舗</h2>
  <div class="contents-bar">
    <%= render partial: "static_pages/new_users", collection: @users, :as => "user" %>
  </div>
</div>

「as」でパーシャルファイルで使う変数名を明確に指定しただけ。

とりあえず表示されて一安心です!

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

RubyでMySQLに接続し、大量のINSERT文を作成する

大量のINSER文を発行する必要があったので、スクリプトで書いてみた。
RubyとMySQLはインストールしてある前提

ディレクトリとファイルの作成

$ mkdir ruby_scripts && cd $_
$ touch test.rb
$ chmod 755 test.rb

test.rbの中身

#!/usr/bin/ruby

require 'mysql2'

connection = Mysql2::Client.new(host: "localhost", username: "root", password: 'pass', :encoding => 'utf8', database: 'database_name')
// 自分の環境に合わせる

selectSql = "SELECT id FROM table WHERE flag = 1;"
//こんな単純なSELECT文ならそもそもスクリプトを書く必要はないと思うが...

res = connection.query(selectSql)

res.each do |r|
  code = r["id"]
  //実行結果のINSERT文内の変数rにハッシュがそのまま入ってしまうので、値だけを取り出して新しい変数codeに代入

  puts "INSERT INTO table2 (id, code) VALUES (2, '#{code}');"
end

Gemfileの作成

$ bundle init

Gemfileの一番下に記述

gem "mysql2"

bundle install

$ bundle install

実行

bundle exec ruby test.rb

実行するとINSERT文がたくさん出力されるはず
コピーして使ってます

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

【Ruby on Rails】OmniAuthのGitHub認証にて近似エラーメッセージが出て一苦労

環境

MacOS 11.2.1
Ruby 3.0.0
Rails 6.1.0
devise 4.7.3
omniauth 1.9.1
omniauth-github 1.4.0
omniauth-oauth2 1.7.1

問題

OmniAuthの概ねの実装を行ったがGitHubの認証用APIにPOSTしている時点でコケてしまう。

結論

以下2パターンの間違いがほぼ同じエラーを出していた。エラーが似ているので、片方が間違えたまま、もう片方を修正しても動作確認でわからない。
- OAuth AppsとGitHub Appsを間違える(詳細は下記)
- token_params: { parse: :json }をDeviseのconfigに設定する(詳細は下記)

解決方法

本当はログをよくチェックするべきだったと思います。
自分の場合は、POSTのあと”Invalid Credential”と出ているので、Deviseの設定が怪しいと思って一つ一つ直しながらひたすら動作確認をしていました。

OAuth AppsとGitHub Appsを間違える、とは

developer settingsによく似た二つの項目がある。
GitHub AppsとOAuth Apps

image.png

image.png


OmniAuthでGitHub認証で必要なのはOAuthAppsで生成するIDとSECRET。
まちがえてGitHubAppsで生成するIDとSECRETを使うと以下のような現象が起こる。

1度目のみ認証画面になる

image.png

認証してもログインできず、2度目以降は認証画面は出ず、ログインに失敗しつづける

ログ
1回目

48826 Started POST "/users/auth/github" for ::1 at 2021-03-05 10:17:35 +0900
48827 Started GET "/users/auth/github/callback?code=xxx&state=xxx" for ::1 at 2021-03-05 10:20:24 +0900
48828 Processing by Users::OmniauthCallbacksController#failure as HTML
48829   Parameters: {"code"=>"xxx", "state"=>"xxx"}
48830 Redirected to http://localhost:3000/
48831 Completed 302 Found in 3ms (ActiveRecord: 0.0ms | Allocations: 334)

2回目以降

48876 Started POST "/users/auth/github" for ::1 at 2021-03-05 10:30:39 +0900
48877 Started GET "/users/auth/github/callback?code=xxx&state=xxx" for ::1 at 2021-03-05 10:30:39 +0900
48878 Processing by Users::OmniauthCallbacksController#failure as HTML
48879   Parameters: {"code"=>"xxx", "state"=>"xxx"}
48880 Redirected to http://localhost:3000/
48881 Completed 302 Found in 1ms (ActiveRecord: 0.0ms | Allocations: 205)

コンソール

Started POST "/users/auth/github" for ::1 at 2021-03-05 10:30:39 +0900
I, [2021-03-05T10:30:39.445975 #78131]  INFO -- omniauth: (github) Request phase initiated.
Started GET "/users/auth/github/callback?code=xxx&state=xxx" for ::1 at 2021-03-05 10:30:39 +0900
I, [2021-03-05T10:30:39.860370 #78131]  INFO -- omniauth: (github) Callback phase initiated.
E, [2021-03-05T10:30:40.842629 #78131] ERROR -- omniauth: (github) Authentication failure! invalid_credentials: OAuth2::Error, : 
{"message":"Resource not accessible by integration","documentation_url":"https://docs.github.com/rest/reference/users#list-email-addresses-for-the-authenticated-user"}
Processing by Users::OmniauthCallbacksController#failure as HTML
  Parameters: {"code"=>xxx, "state"=>xxx}
Redirected to http://localhost:3000/
Completed 302 Found in 1ms (ActiveRecord: 0.0ms | Allocations: 205)

コンソールの方のログを見るとAuthentication failure! invalid_credentialsとなっている

token_params: { parse: :json }をDeviseのconfigに設定する、とは

Facebook認証をする場合、あるバージョン以降、レスポンスフォーマットがJSONに変わっているので、それをパースする処理を加える必要があるそうな。
https://qiita.com/anoworl/items/ea04d941d5d2bdea0e66

config/initializers/devise.rb

config.omniauth :github, ENV["GITHUB_ID"], ENV["GITHUB_SECRET"], token_params: { parse: :json }

token_params: { parse: :json }の部分を加えるとJSONをパースしてくれる

GitHub認証には必要ない設定で、入れるとエラーになってしまう。

入れた場合、POST直後に認証失敗してログインできない。

エラーログ

49561 Started POST "/users/auth/github" for ::1 at 2021-03-05 10:46:03 +0900
49562 Started GET "/users/auth/github/callback?code=xxx&state=xxx" for ::1 at 2021-03-05 10:46:04 +0900
49563 Processing by Users::OmniauthCallbacksController#failure as HTML
49564   Parameters: {"code"=>"xxx", "state"=>"xxx"}
49565 Redirected to http://localhost:3000/
49566 Completed 302 Found in 1ms (ActiveRecord: 0.0ms | Allocations: 207)

コンソール

Started POST "/users/auth/github" for ::1 at 2021-03-05 10:46:03 +0900
I, [2021-03-05T10:46:03.756773 #78764]  INFO -- omniauth: (github) Request phase initiated.
Started GET "/users/auth/github/callback?code=xxx&state=xxx" for ::1 at 2021-03-05 10:46:04 +0900
I, [2021-03-05T10:46:04.210471 #78764]  INFO -- omniauth: (github) Callback phase initiated.
E, [2021-03-05T10:46:04.593857 #78764] ERROR -- omniauth: (github) Authentication failure! invalid_credentials: OAuth2::Error, access_token=xxx&scope=user%3Aemail&token_type=bearer
Processing by Users::OmniauthCallbacksController#failure as HTML
  Parameters: {"code"=>"xxx", "state"=>"xxx"}
Redirected to http://localhost:3000/
Completed 302 Found in 1ms (ActiveRecord: 0.0ms | Allocations: 207)

コンソールの方のログを見るとAuthentication failure! invalid_credentialsとなっている
二つの現象で非常によく似たエラーが出るので原因追求が難しかった。
しかしよくみると、GitHub APPに取り違えた方のエラーメッセージには{"message":"Resource not accessible by integration","documentation_url":"https://docs.github.com/rest/reference/users#list-email-addresses-for-the-authenticated-user”}という情報が書いてある。この部分に気づければもっと早く解決していたかもしれない。

ちなみに単純にパスワードを間違えると

以下のログでPOSTしたまま以下の画面になるので動作確認ですぐに気づける

48807 Started POST "/users/auth/github" for ::1 at 2021-03-05 09:48:08 +0900

image.png

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

【Ruby on Rails】OmniAuthのGitHub認証、APIにPOST時点でのエラー

環境

MacOS 11.2.1
Ruby 3.0.0
Rails 6.1.0
devise 4.7.3
omniauth 1.9.1
omniauth-github 1.4.0
omniauth-oauth2 1.7.1

過程

deviseでユーザー認証機能を導入した後、下記のサイトにのっとってGitHub認証を導入する。
https://github.com/heartcombo/devise/wiki/OmniAuth:-Overview

問題

概ねの実装を行ったがAPIにPOSTしている時点でコケてしまう。

結論

以下2パターンの間違いがほぼ同じエラーを出していた。エラーが似ているので、片方が間違えたまま、もう片方を修正しても動作確認でわからない。
- OAuth AppsとGitHub Appsを間違える(詳細は下記)
- token_params: { parse: :json }をDeviseのconfigに設定する(詳細は下記)

解決方法

本当はログをよくチェックするべきだったと思います。
自分の場合は、POSTのあと”Invalid Credential”と出ているので、Deviseの設定が怪しいと思って一つ一つ直しながらひたすら動作確認をしていました。

OAuth AppsとGitHub Appsを間違える、とは

developer settingsによく似た二つの項目がある。
GitHub AppsとOAuth Apps

image.png

image.png


OmniAuthでGitHub認証で必要なのはOAuthAppsで生成するIDとSECRET。
まちがえてGitHubAppsで生成するIDとSECRETを使うと以下のような現象が起こる。

1度目のみ認証画面になる

image.png

認証してもログインできず、2度目以降は認証画面は出ず、ログインに失敗しつづける

ログ
1回目

48826 Started POST "/users/auth/github" for ::1 at 2021-03-05 10:17:35 +0900
48827 Started GET "/users/auth/github/callback?code=xxx&state=xxx" for ::1 at 2021-03-05 10:20:24 +0900
48828 Processing by Users::OmniauthCallbacksController#failure as HTML
48829   Parameters: {"code"=>"xxx", "state"=>"xxx"}
48830 Redirected to http://localhost:3000/
48831 Completed 302 Found in 3ms (ActiveRecord: 0.0ms | Allocations: 334)

2回目以降

48876 Started POST "/users/auth/github" for ::1 at 2021-03-05 10:30:39 +0900
48877 Started GET "/users/auth/github/callback?code=xxx&state=xxx" for ::1 at 2021-03-05 10:30:39 +0900
48878 Processing by Users::OmniauthCallbacksController#failure as HTML
48879   Parameters: {"code"=>"xxx", "state"=>"xxx"}
48880 Redirected to http://localhost:3000/
48881 Completed 302 Found in 1ms (ActiveRecord: 0.0ms | Allocations: 205)

コンソール

Started POST "/users/auth/github" for ::1 at 2021-03-05 10:30:39 +0900
I, [2021-03-05T10:30:39.445975 #78131]  INFO -- omniauth: (github) Request phase initiated.
Started GET "/users/auth/github/callback?code=xxx&state=xxx" for ::1 at 2021-03-05 10:30:39 +0900
I, [2021-03-05T10:30:39.860370 #78131]  INFO -- omniauth: (github) Callback phase initiated.
E, [2021-03-05T10:30:40.842629 #78131] ERROR -- omniauth: (github) Authentication failure! invalid_credentials: OAuth2::Error, : 
{"message":"Resource not accessible by integration","documentation_url":"https://docs.github.com/rest/reference/users#list-email-addresses-for-the-authenticated-user"}
Processing by Users::OmniauthCallbacksController#failure as HTML
  Parameters: {"code"=>xxx, "state"=>xxx}
Redirected to http://localhost:3000/
Completed 302 Found in 1ms (ActiveRecord: 0.0ms | Allocations: 205)

コンソールの方のログを見るとAuthentication failure! invalid_credentialsとなっている

token_params: { parse: :json }をDeviseのconfigに設定する、とは

Facebook認証をする場合、あるバージョン以降、レスポンスフォーマットがJSONに変わっているので、それをパースする処理を加える必要があるそうな。
https://qiita.com/anoworl/items/ea04d941d5d2bdea0e66

config/initializers/devise.rb

config.omniauth :github, ENV["GITHUB_ID"], ENV["GITHUB_SECRET"], token_params: { parse: :json }

token_params: { parse: :json }の部分を加えるとJSONをパースしてくれる

GitHub認証には必要ない設定で、入れるとエラーになってしまう。

入れた場合、POST直後に認証失敗してログインできない。

エラーログ

49561 Started POST "/users/auth/github" for ::1 at 2021-03-05 10:46:03 +0900
49562 Started GET "/users/auth/github/callback?code=xxx&state=xxx" for ::1 at 2021-03-05 10:46:04 +0900
49563 Processing by Users::OmniauthCallbacksController#failure as HTML
49564   Parameters: {"code"=>"xxx", "state"=>"xxx"}
49565 Redirected to http://localhost:3000/
49566 Completed 302 Found in 1ms (ActiveRecord: 0.0ms | Allocations: 207)

コンソール

Started POST "/users/auth/github" for ::1 at 2021-03-05 10:46:03 +0900
I, [2021-03-05T10:46:03.756773 #78764]  INFO -- omniauth: (github) Request phase initiated.
Started GET "/users/auth/github/callback?code=xxx&state=xxx" for ::1 at 2021-03-05 10:46:04 +0900
I, [2021-03-05T10:46:04.210471 #78764]  INFO -- omniauth: (github) Callback phase initiated.
E, [2021-03-05T10:46:04.593857 #78764] ERROR -- omniauth: (github) Authentication failure! invalid_credentials: OAuth2::Error, access_token=xxx&scope=user%3Aemail&token_type=bearer
Processing by Users::OmniauthCallbacksController#failure as HTML
  Parameters: {"code"=>"xxx", "state"=>"xxx"}
Redirected to http://localhost:3000/
Completed 302 Found in 1ms (ActiveRecord: 0.0ms | Allocations: 207)

コンソールの方のログを見るとAuthentication failure! invalid_credentialsとなっている
二つの現象で非常によく似たエラーが出るので原因追求が難しかった。
しかしよくみると、GitHub APPに取り違えた方のエラーメッセージには{"message":"Resource not accessible by integration","documentation_url":"https://docs.github.com/rest/reference/users#list-email-addresses-for-the-authenticated-user”}という情報が書いてある。この部分に気づければもっと早く解決していたかもしれない。

ちなみに単純にパスワードを間違えると

以下のログでPOSTしたまま以下の画面になるので動作確認ですぐに気づける

48807 Started POST "/users/auth/github" for ::1 at 2021-03-05 09:48:08 +0900

image.png

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

Railsポートフォリオ作成 #6 基本機能フロントエンド開発

こんにちは:smiley:
今回は基本機能のフロントエンド開発を行いました。
(前回記事(#5 基本機能バックエンド開発))

私は、前職(ホテルの料飲部)における、コミュニケーションの課題を解決するアプリを作っています。
具体的には、「レストランで使うものの数を管理するアプリ」です。

今回は、基本機能のフロントエンド開発を行いました

フロントエンドは経験値が低いので、なんとか"見れる見た目"にするので精一杯でした。
ここから、ポートフォリオとして恥ずかしくない見た目にする自信が正直ないです。
正直、途中で挫折するかも、、、
とか思ってしまいます、、、

他の方のポートフォリオを拝見したのですが、レベルが高すぎて言葉を失いました。

前回仕組みで解決したいと書いたのですが、まだ完全にはうまくいっていません。
まだまだ改善が必要です。

感じたこと

  • 知識は必要な時に身につけるべき
    以前時間があった時に、後からいるからと思ってHTML・CSSの復習をしていたのですが、結局また少し復習することになってしまい、二度手間になってしまいました。
    ちなみに、これをTwitterで呟いたところ、今までで一番いいね等をゲットしたツイートになりました。

  • レスポンシブにしないと、、、
    パソコンで作っているので、パソコンで合うようになっていて、スマホで見た際に見づらくなっていないかと、スマホでもチェックしながらやらないといけないと思いました。

とりあえず、なんとか見れるようにはなったので、次に進もうと思います。

次はDockerです

「開発環境でDockerとdocker-composeを導入してみる」
ということを目標に、取り組んでいきたいと思います。



フロントエンドが終わり、第一段階が終了したので、第二段階に進みたいと思います。
まずはDockerの導入をしていきたいと思います:fist:
勉強するところからなので、時間がかかると思いますが、少しずつやっていきたいと思います。

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

scssの導入の仕方

まずscssを使うにはrubyをインストールする必要があります。
rubyをまだ導入していない場合はまずはそちらから導入していきましょう!
導入が終わったという体で進めていきます?

scssフォルダを作りましょう!

私はVSコードを使っているのでそちらを使って進めていきます?

①saccフォルダを作る

vsコードをダウンロード終わったら、フォルダを作成していきます。
作成が終わったら、index.htmlファイルを作り、cssフォルダ、scssフォルダを作ればとりあえず終わりです?

②ターミナル

次にターミナルを使っていきます。

% cd Documents
% ls
% cd Sass

この状態にしておきましょう。(scssフォルダの中にいる感じ)

③cssファイルの中に記載して行きます!

style.scss
main {
  width: 90%;
  p {
    font-size: 14px;
  }
}

前回の記事でも説明したように、index.html の親要素と子要素の関係のようにそれに伴って、入れ子のように記述していきます。
ちなみに拡張子はstyle.scssです。

④再びターミナル

ではではターミナルをいじっていきます!前回のターミナルですでにsassファイルの中にいますのでそのまま進めていきます!!

% sass scss/main.scss:css/main.css #scssをcssに変換する
% less css/main.css #main.cssに展開されていく
% sass ---style expanted scss/main.scss:css/main.css  #構造がわかりにくい場合に使うようです。
% less css/main.css #再び展開

*less~を行うとターミナル上にend文字出てきてうち込みできなくなるので、[;qw]を押すと画面がまた入力状態に戻ります!!
ただこのやり方なかなかめんどくさいなと思ったかた、省略しちゃいましょうか?

% sass --style expanted --watch scss:css

これで完了です!
終了する場合はコントロール+cです!!?

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

Nuxt

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

【Ruby on Rails】コントローラーの単体テストコードについてまとめ(RSpec)

初学者です。
テストコードがなぜか大好きです。

今回はコントローラーの単体テストコードについてまとめます。
私はRSpecを利用しています。

コントローラーのテストコードを書く方針は
アクションにリクエストを送ったとき想定通りのレスポンスが返されるかどうかを確かめる
ことです。

ちなみにモデルの単体テストコードについてはこちらにまとめています。

前提条件

  • pry-railsを導入済みである
  • FactoryBotを導入済みである
  • RSpec導入済みである

上記については以下の記事にまとめています。

【Ruby on Rails】デバッグツール(pry-rails)
【Ruby on Rails】FactoryBotとFakerについてまとめ
【Ruby on Rails】モデルの単体テストコードについてまとめ(RSpec)

準備

下記コマンドでテストコード用のファイルを生成します。
成功すればspec/requests配下に該当のファイルが生成されます。

ターミナル
rails g rspec:request samples

テストコード

describeitで検証すべき項目を出していきます。

spec/requests/samples_spec.rb
require 'rails_helper'
describe SamplesController, type: :request do

  before do
    @sample = FactoryBot.create(:sample)
  end

  describe 'GET #index' do
    it 'indexアクションにリクエストすると正常にレスポンスが返ってくる' do 
    end
    it 'indexアクションにリクエストするとレスポンスに投稿済みのテキストが存在する' do 
    end
    it 'indexアクションにリクエストするとレスポンスに投稿済みの画像URLが存在する' do 
    end
    it 'indexアクションにリクエストするとレスポンスに投稿フォームが存在する' do 
    end
  end
end

FactoryBotはbuildではなくcreateにしています。
今回のテストではDBにデータが存在する必要があるのでcreateです。
テストする度にデータが作られ、終わると削除されます。便利!

ではindexアクションにリクエストすると正常にレスポンスが返ってくるのテストコードを書いていきます。

spec/requests/samples_spec.rb
it 'indexアクションにリクエストすると正常にレスポンスが返ってくる' do 

# 以下を追加
  get root_path
  binding.pry

end

解説します。
get ○○_pathでどのパスにリクエストを送りたいかを書きます。
rails routesで確認してそのパスを記述します。

この状態で下記コマンドでテストコードを実行します。

ターミナル
bundle exec rspec spec/requests/samples_spec.rb

binding.pryしてるので処理が途中で止まりターミナルに入力できるようになっていると思います。
下記のコマンドを入力します。

ターミナル
response.status

そうするとそのレスポンスのステータスコードが出力されます。
HTTP通信においてステータスコードは以下のようになっています。

ステータスコード 内容
100~ 処理継続中
200~ 処理成功
300~ リダイレクト
400~ クライアント側のエラー
500~ サーバーエラー

つまり今回の場合はresponse.status200がステータスコードで返ってくればOKということです。

正常に200が返ってきたらテストコードを編集します。

spec/requests/samples_spec.rb
it 'indexアクションにリクエストすると正常にレスポンスが返ってくる' do 
  get root_path

# 以下に編集
  expect(response.status).to eq 200

end

これでテストコードを実行して成功すればOKです。

次にindexアクションにリクエストするとレスポンスに投稿済みのテキストが存在するのテストコードを書いていきます。

spec/requests/samples_spec.rb
it 'indexアクションにリクエストするとレスポンスに投稿済みのテキストが存在する' do 

# 以下を追加
  get root_path
  expect(response.body).to include(@sample.text)

end

解説します。
response.bodyと記述してincludeで引数の内容(今回はテキスト)が存在するかを確認してます。bodyでブラウザに表示されるHTMLの情報を抜き出すことができます。

これでテストコードを実行して成功すればOKです。

次にindexアクションにリクエストするとレスポンスに投稿済みの画像URLが存在するのテストコードを書いていきます。ほぼ先ほどと同じです。

spec/requests/samples_spec.rb
it 'indexアクションにリクエストするとレスポンスに投稿済みの画像URLが存在する' do 
  get root_path
  expect(response.body).to include(@sample.image)
end

これでテストコードを実行して成功すればOKです。

次にindexアクションにリクエストするとレスポンスに投稿フォームが存在するのテストコードを書いていきます。
難しく考えずにその文言が存在するかを確認できればOKなので下記のようになります。

spec/requests/samples_spec.rb
it 'indexアクションにリクエストするとレスポンスに投稿フォームが存在する' do 
  get root_path
  expect(response.body).to include('投稿する')
end

これでテストコードを実行して成功すればOKです。

他のアクションについてもほぼ書き方は同じです!
コントローラーの単体テストコードは結合テストとかぶる部分もありますよねー。

以上です。

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

Cucumberのチュートリアルを日本語シナリオで試した

10 Minute Tutorialを日本語のシナリオで書き直してみたので記録。
言語はrubyです。

日本語のシナリオ

is_it_friday_yet_ja.feature
# language: ja
機能: 今日は金曜?
  皆が金曜かどうか知りたがっている

  シナリオアウトライン: 今日が金曜かどうか
    前提 今日が "<曜日>"
    もし 金曜と訪ねたら
    ならば  "<返答>"と返答する

  例:
    | 曜日            | 返答 |
    | 金曜            | 華金! |
    | 日曜           | ちがうよ |
    | それ以外の曜日  | ちがうよ |

日本語への設定

.featureファイルに# language: jaを追加すれば日本語でかける。
Gherkin Reference(Spoken Languages)

対応した識別子に変更

Given -> 前提
When -> もし
Then -> ならば

Localisation

参考

Cucumber
10 Minute Tutorial
Gherkin Reference(Spoken Languages)
Localisation

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

【Docker】Ruby2.6.5とRails6.0.0とmysql DockerComposeで環境構築

はじめに

Ruby2.6.5とRails6.0.0とmysqlでDockerComposeで環境構築をしたので記録として記事を書きます。
もし誰かのお役に立てたら幸いです。

Docker環境でアプリケーション開発する手順

1、RailsのDockerfileを作成してDockerをbuild
2、DockerCompose.ymlを作成しコンテナを作る
3、Rails のセットアップ
4、データベースを作成する

開発環境

Docker version 20.10.0
docker-compose version 1.27.4

1、RailsのDockerfile作成

新しいデレクトリを作成します。
今回はデレクトリ名をexamとしてます。

ターミナル
mkdir [新規デレクトリ名]
cd [新規デレクトリ名]

Dockerfile

新規で作ったデレクトリに「Dockerfile」をいう名前でDockerファイルを作成します。
VSコードをお使いの方はcode Dockerfileでターミナルから直接ファイルの作成&移動をしてくれます。
もちろんディレクトリを呼び込んでファイルを作成しても大丈夫です。

exam/Dockerfile
FROM ruby:2.6.5
RUN apt-get update && apt-get install -y \
    build-essential \
    libpq-dev \
    nodejs\
    yarn \
    vim 

WORKDIR /新規デレクトリ名
COPY Gemfile Gemfile.lock /新規デレクトリ名/
RUN bundle install

Gemファイルを作成する

ターミナル
touch Gemfile Gemfile.lock

Gemfileにファイルを持ってくるソースとrailsのバージョンを記述します。

Gemfile
source 'https://rubygems.org'
gem 'rails', '~>6'

Dockerを建てます。

ターミナル
docker build .
.
.
.
Installing rails 6.1.2.1
Bundle complete! 1 Gemfile dependency, 42 gems now installed.
Use `bundle info [gemname]` to see where a bundled gem is installed.
Removing intermediate container 06448279a57c
 ---> c21a3ec7e3a4
Successfully built c21a3ec7e3a4

#イメージが出来てるか調べる事も出来ます。
docker images 

#もし使っていないイメージがあれば下記のコマンドで削除できます。
docker rmi [IMAGE ID]

2、DockerCompose.ymlを作成しコンテナを作る

dockerc-compose.ymlファイルを作成し記述する

ターミナル
code docker-compose.yml

これで新しいdocker-compose.ymlが作成されます。

docker-compose.yml
version: '3'

services:
  web:
    build: .
    ports:
      - 3000:3000
    volumes:
      - '.:/[作成したディレクトリ名]'
    tty: true
    stdin_open: true

dockerc-ompose.ymlの確認をして実行します

#確認します
cat docker-compose.yml

#実行します
docker-compose up -d


#コンテナが動いてる事を確認します。
docker ps
docker-compose ps

#コンテナの中に入ります。
docker-compose exec web bash

3、Rails のセットアップ

Railsの環境でコンテナができのでその中でrails newをしてセットアップして行きます。

#新しいrailsを作ります
rails new . --force --database=mysql --skip-bundle

#一度コンテナから抜けます
exit

#今のコンテナとイメージを削除します
docker-compose down

#Downになってるか確認します
docker ps

#新しいイメージでコンテナを建てます
docker-compose up --build -d

#確認します
docker-compose ps

#コンテナに入ります
docker-compose exec web bash

#Railsを起動します
rails s -b 0.0.0.0 #現段階ではエラーが出ます

現段階ではデータベースの記述を Dockerfileに記述していないので、mysql2のエラーが出ると思います。
下記の対応を試して下さい。

【Docker】エラー Could not find gem 'mysql2 (~> 0.5)' in any of the gem sources listed in your Gemfile
https://qiita.com/AKI3/items/8009b5218be0ad67b6b7

エラーが解決したらrails s -b 0.0.0.0でサーバーが立ち上がります。
実際にlocalhost:3000でアクセスします。
しかしこのままではデータベースが無いのでエラー画面が表示されます。
スクリーンショット 2021-02-15 17.02.13.png

4、データベースを作成する。

ローカルであればrails db:createをするとデータベースを作れるのですが、コンテナ内では現状の設定では作れません。
Dockerではサービス(環境)ごとにコンテナを作る事が推奨されております。
今回であればRubyとmysqlのコンテナを別々に作り、それぞれのコンテナどうしを接続する必要があります。
その為、detabase.ymlの設定ファイルを編集して正しい指定をし、docker-compose.ymlの設定ファイルの編集します。

先ずdetabase.ymlを編集します。

config/detabase.yml
default: &default
  adapter: mysql2
  encoding: utf8
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  host: db

development:
  <<: *default
  database: 新規デレクトリ名_development
  username: root
  password:

省略

次にdocker-compose.ymlを編集します。

docker-compose.yml
version: '3'

volumes:
  db-data:

services:
  web:
    build: .
    ports:
      - 3000:3000
    volumes:
      - '.:/新規デレクトリ名'
    environment:
      - 'MYSQL_ROOT_PASSWORD=1'
    tty: true
    stdin_open: true
    depends_on:
      - db
    links:
      - db

  db:
    image: mysql:8
    volumes:
      - 'db-data:/var/lib/mysql'
    # このenvironmentはテスト環境でのみ使用可能
    environment:
      MYSQL_ALLOW_EMPTY_PASSWORD: 1

    # command: bundle exec rails s -p 3000 -b '0.0.0.0' #こちらはお好みで

docker-compose.ymlを編集したので新しくコンテナを作ります。
今回はweb(Raisl)とdb(mysql)2つのコンテナを作る事になります。

#再びコンテナを建てます
docker-compose up -d

#upになってるか確認します
docker-compose ps

#コンテナに入ります
docker-compose exec web bash

#データベースを作成します
rails db:create #現段階ではエラーが出ます

Rails側のコンテナ内で作業を進めていきます。
先程作ったRails側のコンテナとmysql側のコンテナがしっかり繋がっていればrails db:createのコマンドは通りますが、現段階では下記のエラーが発生します。

Mysql2::Error::ConnectionError: Plugin caching_sha2_password could not be loaded: /usr/lib/x86_64-linux-gnu/mariadb19/plugin/caching_sha2_password.so: cannot open shared object file: No such file or directory

これはwebコンテナが mysql 8.0 のcaching_sha2_passwordが認証方式に対応していないためだそうです。

詳しくは、こちらの記事で解決できます。
https://blog.toshimaru.net/rails-on-docker-compose/

コマンドだけこちらに記載します。

ターミナル
 #データベース側のコンテナに入る
docker-compose exec db bash

 #mysqlを操作する
mysql -u root

 #ユーザー一覧とその認証方式が閲覧
select User,Host,plugin from mysql.user;

 #root@% のユーザー設定を変更
ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY '';

 #再度ユーザー一覧とその認証方式が閲覧
select User,Host,plugin from mysql.user;

エラーが解決できたら最後サーバーを立ち上げます。

ターミナル
rails s -b 0.0.0.0

=> Booting Puma
=> Rails 6.1.2.1 application starting in development 
=> Run `bin/rails server --help` for more startup options
Puma starting in single mode...
* Puma version: 5.2.1 (ruby 2.6.5-p114) ("Fettisdagsbulle")
*  Min threads: 5
*  Max threads: 5
*  Environment: development
*          PID: 29
* Listening on http://0.0.0.0:3000
Use Ctrl-C to stop
.
.
.
省略

出来ました!
localhost3000にアクセスすると-Yay! You’re on Rails!-の画面が表示されます。
スクリーンショット 2021-02-17 17.16.29.png

最後に

手探りの対処療法でサーバー起動まで達成しましので、これからも継続学習が必要です。
なんとか環境構築まで至りましたが、Dockerについて完全に理解できておりません、万が一情報が間違っている場合ご指摘していただけると幸いです。

エンジニア初学者ですが、同じ様に悩んでる方々の助けになればと思い記事を投稿しております。
万が一情報が間違っている場合ご指摘していただけると幸いです。

参考

今回Udemyの教材とやっすんのエンジニア大学を主に参考にさせていただきました。
https://www.udemy.com/course/aidocker/
https://github.com/yassun-youtube/docker-compose-sample/blob/master/docker-compose.yml

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

macbookのrubyの環境構築

私が行なったrubyの開発に必要な環境構築についてまとめておきます。
今後自分も必要なことだと思うので。。

デフォルトをzshに設定

% chsh -s /bin/zsh
% xcode-select --install

コマンドラインツールをインストールします。

% /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"

ホームディレクトリにて、homebrewのインストールをします。

% brew -v
% brew update

homebrewのバージョンを確認、updeateを上記の記述で行う

Rubyのインストール

% brew install rbenv ruby-build
% echo 'eval "$(rbenv init -)"' >> ~/.zshrc

rubyの土台となるものをhomebrewを用いてinstallする。
したの記述でpc上どこからでも使用できるようにする。

% source ~/.zshrc

ここまででzshの変更を反映します。

% brew install readline
% brew link readline --force

readlineをインストールしてirb上での日本語入力を可能に設定します。

% RUBY_CONFIGURE_OPTS="--with-readline-dir=$(brew --prefix readline)"
% rbenv install 2.6.5
% rbenv global 2.6.5
% rbenv rehash
% ruby -v

上記を一つずつ実行します。
まずruby2.6.5のインストールをします。
インストールしたrubyを使用するためにバージョンを指定。
rbenvを読み込んで変更を反映。
最後の記述でインストールしたrubyのバージョンを確認する。

Mysqlをインストールしていきます

% brew install mysql@5.6
% mkdir ~/Library/LaunchAgents 
% ln -sfv /usr/local/opt/mysql\@5.6/*.plist ~/Library/LaunchAgents
% launchctl load ~/Library/LaunchAgents/homebrew.mxcl.mysql\@5.6.plist 

一つずつ実行します。
pc再起動のたびに起動し直さないように自動で起動するようにinstall以下の記述で設定します。

% echo 'export PATH="/usr/local/opt/mysql@5.6/bin:$PATH"' >> ~/.zshrc 
% source ~/.zshrc 
% which mysql 
% mysql.server status

以上の記述でどこからでも操作できるように設定します。
最後の記述でsqlの状態を確認できます。

railsのインストール

% gem install bundler --version='2.1.4'
% gem install rails --version='6.0.0'
% rbenv rehash
% rails -v

gemを管理するために必要なbundlerをインストールする。
rails6.0.0をインストールする
変更を反映させて正しく導入できているのかを確認。

nodeのインストール

% brew install node@14
% echo 'export PATH="/usr/local/opt/node@14/bin:$PATH"' >> ~/.zshrc
% source ~/.zshrc
% node -v

railsを動かすのに必要なnode.jsのインストールをする。

yarn

% brew install yarn
% yarn -v

主にJavaScriptで開発されたプログラム部品(モジュール)を管理するためのパッケージ管理システムの一つです。
以上が2020年3月現在私が環境構築で行なっている作業でした。

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

【Rubyエンジニア】就職までの完全ロードマップ

1ヶ月間ロードマップ

※Twitterでの発信は同時進行(内容は以下)
学習記録
備忘録
キータ記事

①Ruby学習

→HTML、CSS(テックアカデミーの無料動画)
→プロゲート(Ruby、Railsコース)

※プロゲートの内容が身についたら
→書籍(ここで同時進行ポートフォリオ作成)

ポートフォリオ作成(Docker、AWS)

→Git、GitHub学習(1時間)
チーム開発のしやすくするので、現場で即戦力になるため。
コードを一括管理してくれる。

ーーー

就職応募
※最低10社


Twitter
Wantedly
IT、WEB専門エージェント
(GEEKLY、ポテパン、レバテックキャリア)

ーーー

面接対策


なぜエンジニアになりたいのですか?
なぜエンジニアを目指すのか
エンジニアとして何をしたいのか

現在これをもとに就職活動をしています。大前提としてRubyの開発スキルは求められるので、開発環境やツールも追加していくつもりです、しかし、全てやる必要はなく、現場に出てもひたむきに学習を継続できるスキルを強調するために学習をすすめるといいと思っています。

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

Formオブジェクトの概要

Formオブジェクトとは

Formオブジェクトとは、1つのフォームからのデータ送信で複数のモデル操作、テーブルに保存しない情報にバリデーションを設定したい場合に使います。

モデルに似た機能を持ったクラスを作り、バリデーションやデータを保存する処理を記述して実装します。
実装手順はこんな感じです。

1.modelsディレクトリ直下にファイル作成、クラスを定義
2.include ActiveModel::Modelの設定
3.attr_accessorで保存したい複数のテーブルのカラム名を属性値として扱えるように記述
4.バリデーションを記述
5.データをテーブルに保存する処理を記述
6.コントローラーのnew、createアクションなどでFormオブジェクトのインスタンスを生成
7.フォーム作成の部分をFormオブジェクトのインスタンスを引数として渡す形に変更

以下はコードの一例と内容についてです。

qiita.rb
class OrderPurchase  #OrderモデルとPurchaseモデルの処理
  include ActiveModel::Model
  attr_accessor

   #ここにバリデーションなどの記述をする

  def save
   #ここにデータを保存する記述をする
  end
end

①include ActiveModel::Model
ActiveModel::Modelをincludeすると、バリデーションなどの機能が使えるようになります。
Railsガイドにも記載がありました。
Railsガイド

②attr_accesor
attr_accesorでは、モデルに対応するテーブルに設定したカラム名以外の属性を扱う時に使用します。
ゲッターとセッター(データの取得と更新)をこの記述だけでできるようになります。

①でモデルの機能が使えるようしているので、②でバリデーションを設定したい属性を指定できるのだと思います。

おわりに

プログラミング初心者が備忘録としてまとめたので、間違い等あるかもしれません。
新たにわかった事や、間違いがあれば随時更新します。

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

Ruby

Ruby

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

【Rails】Railsサーバーが起動してもlocalhost:3000で表示されなかった症状が、解決した件について【Ruby】

症状

rails sでサーバーを起動し、コンソール上では起動してそうな感じだが、locakhost:3000にアクセスしても全く反応しない事象が発生しました。

以下はターミナル

ubuntu:~/environment/hello_app (master) $ rails s
=> Booting Puma
=> Rails 6.0.3 application starting in development 
=> Run `rails server --help` for more startup options
Puma starting in single mode...
* Version 4.3.6 (ruby 2.6.3-p62), codename: Mysterious Traveller
* Min threads: 5, max threads: 5
* Environment: development
* Listening on tcp://127.0.0.1:8080
* Listening on tcp://[::1]:8080
Use Ctrl-C to stop

実施したが解決しなかった対策
・rails server起動しなおし
・adBlockerなどは無効化
・ブラウザの開き直し
・bundle install→updateのやり直し
・rails s -b 0.0.0.0→rails s -b $IP -p $PORT

解決方法

1.「preview」→「previewrunningapplication」で表示させた画面を閉じる
2.再度「previewrunningapplication」開きなおす
3.サーバーを起動下記画像の「Browser」の右側の■を押下

→別タブで「Yay! You’re on Rails!」の画面が開けるようになりました。
image.png
image.png

以下は成功時のターミナル

ubuntu:~/environment/hello_app (master) $ rails s
=> Booting Puma
=> Rails 6.0.3 application starting in development 
=> Run `rails server --help` for more startup options
Puma starting in single mode...
* Version 4.3.6 (ruby 2.6.3-p62), codename: Mysterious Traveller
* Min threads: 5, max threads: 5
* Environment: development
* Listening on tcp://127.0.0.1:8080
* Listening on tcp://[::1]:8080
Use Ctrl-C to stop
Started GET "/" for 61.215.149.134 at 2021-03-04 14:18:46 +0000
Cannot render console from 61.215.149.134! Allowed networks: 127.0.0.0/127.255.255.255, ::1
   (2.7ms)  SELECT sqlite_version(*)
Processing by Rails::WelcomeController#index as HTML
  Rendering /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/railties-6.0.3/lib/rails/templates/rails/welcome/index.html.erb
  Rendered /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/railties-6.0.3/lib/rails/templates/rails/welcome/index.html.erb (Duration: 13.0ms | Allocations: 479)
Completed 200 OK in 64ms (Views: 27.3ms | ActiveRecord: 0.0ms | Allocations: 2758)


Started GET "/" for 61.215.149.134 at 2021-03-04 14:18:58 +0000
Cannot render console from 61.215.149.134! Allowed networks: 127.0.0.0/127.255.255.255, ::1
Processing by Rails::WelcomeController#index as HTML
  Rendering /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/railties-6.0.3/lib/rails/templates/rails/welcome/index.html.erb
  Rendered /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/railties-6.0.3/lib/rails/templates/rails/welcome/index.html.erb (Duration: 7.9ms | Allocations: 192)
Completed 200 OK in 12ms (Views: 10.8ms | ActiveRecord: 0.0ms | Allocations: 1165)
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む