20200316のRailsに関する記事は28件です。

【MySQL】プログラミング初心者が今まで遭遇したエラーとその解決方法のメモ

こんばんは!スージーです!
なかなか技術ブログが書けずにモヤモヤしていたので、ちょうど良いネタがあり備忘録も兼ねて。

MySQLに接続できないエラー

私は度々、MySQLに接続できずに四苦八苦しています。pidファイルないよーとかsocketないよーとか、その度に過去のメモや参考記事をあちこち探しているのでまとめてみようと思います。

参考

【遭遇率第1位】

Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)

原因:
ざっくり言うとmysql.sockファイルが存在しないから作ってね
解決策:
/tmp直下にmysql.sockを作る

mysql.sockファイルがあるか確認
~ $cd /tmp
tmp $ ls
mysql.sockがない

tmp $ sudo touch mysql.sock
tmp $ cd
~ $ sudo mysql.server start
ERROR!~~~

startできずエラー発生したら
権限の書き換え(chownでファイルやディレクトリの所有者と所属グループを変更する)
~ $ sudo chown username /tmp/mysql.sock
もしくは権限付与
~ $ sudo chmod 777 /tmp/mysql.sock

もう一度mysql起動
~ $ sudo mysql.server start
...SUCCESS!

mysql.sockファイルの作り方は色々あると思いますが、私はこのエラーが起きた時はtouchコマンドで/tmp/ファイル直下にmysql.sockファイルを直接作ってしまいます。socketファイル作成しても権限がないと怒られる事もあるのでその時はchownコマンドかchmodコマンドで権限の書き換えか権限付与してあげて下さい。

【遭遇率第2位】

Can't connect to local MySQL server through socket '/tmp/mysql.sock' (38)

原因:
ざっくり言うとpidファイルが存在しないから作ってね
解決策:
/usr/local/var/mysql/直下にlocal.pidファイルを作る


~ $ sudo mysql.server start
Starting MySQL
… ERROR! server quit updating PID file(/usr/local/var/mysql/usernoMacBook-ea.local.pid)

pidファイルがあるか確認してみる
~ $ cd /usr/local/var/mysql
mysql $ ls
usernoMacBook-ea.local.pidがない

mysql $ sudo touch usernoMacBook-ea.local.pid
mysql $ cd
~ $ sudo mysql.server start
...ERROR!~~/usr/local/var/mysql/username.local.err: Permission denied
権限ないよと怒られたら先ほどのエラーと同様に権限の書き換え(chownでファイルやディレクトリの所有者と所属グループを変更する)
~ $ sudo chown /usr/local/var/mysql/usernoMacBook-ea.local.pid
もしくは権限付与
~ $ sudo chmod 777 /usr/local/var/mysql/usernoMacBook-ea.local.pid

もう一度起動してみる
~ $ sudo mysql.server start
...SUCCESS!

先ほどと同様にやり方は色々あると思いますが、pidファイルもtouchコマンドで作ってあげましょう。mysql.sockのエラーと同様に権限ないよって怒られたら権限の書き換えか権限付与してあげましょう。

ここまでのまとめ

ここまで紹介したmysql.sockないよ、~.local.pidないよ、権限ないよ、がMySQL関連エラーの大半を占めていると思います。「/tmpディレクトリってどこ!?」とか「/usrディレクトリなんて知らないよ」って最初は思いましたが、まずはファイルが無い事を確認する為にcdコマンドで該当ディレクトリまで潜って見てみましょう。

【遭遇率第3位】

mysql立ち上がった!と思ったらsafeモードのプロセスが既に存在してますよっていうエラー

原因:
既にMySQLのプロセスが動いている
解決法:
processをkillする

~ $ sudo mysql.server start
Starting MySQL
 SUCCESS! 
~ $ 200315 13:51:58 mysqld_safe A mysqld process already exists

動いているMySQLプロセスを確認してみる
~ $ ps aux| grep mysqld
user       98762  0.0 0.0 4268296  672 s004 S+  2:00PM  0:00.01 grep mysqld
user       98633  0.0 5.4 4929884 450652  ?? S   1:51PM  0:00.46 /usr/local/opt/mysql@5.6/bin/mysqld --basedir=/usr/local/opt/mysql@5.6 --datadir=/usr/local/var/mysql --plugin-dir=/usr/local/opt/mysql@5.6/lib/plugin --log-error=usernoMacBook-ea.local.err --pid-file= usernoMacBook-ea.local.pid
user       98536  0.0 0.0 4281052  1128  ?? S   1:51PM  0:00.03 /bin/sh /usr/local/opt/mysql@5.6/bin/mysqld_safe --datadir=/usr/local/var/mysql ←注目
mysqld_safeプロセスが動いている模様

プロセスをkillする
~ $ sudo kill -9 98536
Password:

一度mysqlを停止する
~ $ mysql.server stop
Shutting down MySQL
.. SUCCESS! 

もう一度MySQLを起動してみる
~ $ mysql.server start
Starting MySQL
. SUCCESS!

これはこの前初めて遭遇したエラーです。頻出エラーより遭遇確率は低いと感じますが、grepしてmysql_safeのプロセスが動いているか確認しましょう。mysql_safe以外のプロセスをkillしてもエラー解消しなかったので悪さしているmysql_safeを見つけてあげましょう。

【番外編】

過去に一度でも5.7を起動してしまうと、同じデータを使って5.6を起動すると今までの方法では解決できない場合がある。

この状況は過去に一度dockerでMySQL@5.7で起動した後に開発環境のMySQL@5.6を起動した時に起きた事があります。

この状況になったらMySQLをアンインストールする方法があります。ただし、開発環境で大切なデータがDBに残っている場合は何らかの方法で退避させてあげて下さい(退避方法は割愛します。実践した事ないです)。私は幸いにも開発環境に貴重なデータはないので躊躇無くアンインストールしました。

mysqlをアンインストールします
~ $ brew remove mysql
~ $ brew cleanup
以下のディレクトリ下にはmysql関連ファイルが作成されているので念の為、綺麗に削除しておきます
~ $ sudo rm -rf /usr/local/mysql
~ $ sudo rm -rf /Library/StartupItems/MYSQL
~ $ sudo rm -rf /Library/PreferencePanes/MySQL.prefPane
~ $ sudo rm -rf /Library/Receipts/mysql-.pkg
~ $ sudo rm -rf /usr/local/Cellar/mysql*
~ $ sudo rm -rf /usr/local/bin/mysql*
~ $ sudo rm -rf /usr/local/var/mysql*
~ $ sudo rm -rf /usr/local/etc/my.cnf
~ $ sudo rm -rf /usr/local/share/mysql*
~ $ sudo rm -rf /usr/local/opt/mysql*

最後にver5.6をインストール
~ $ brew install mysql@5.6

インストールが完了したらパス通す
$ echo 'export PATH="/usr/local/opt/mysql@5.6/bin:$PATH"' >> ~/.bash_profile

.bash_profileの変更を反映
$ source ~/.bash_profile

MySQLを起動
~ $ sudo mysql.server start
. SUCCESS!

アンインストールしても過去のmysqlファイルがなぜか残っている場合があるので面倒ですけど rmコマンドで該当該当ファイルを削除してあげます。完全にクリーンになったMySQLならちゃんと起動してくれます。

【番外編2】

rails new project-name -d mysql→ Library not loaded: /usr/local/opt/mysql/lib/libmysqlclient.21.dylib (LoadError)

原因:
mysqlのライブラリーがロードできませんよ
対策:
mysql2をアンインストールしてbundle install

project-name $ bundle exec gem uninstall mysql2
project-name $ bundle install
.
..
...
Gem::Ext::BuildError: ERROR: Failed to build gem native extension.

    current directory: /Users/akito/git/media/vendor/bundle/gems/mysql2-0.4.4/ext/mysql2
/Users/akito/.rbenv/versions/2.3.1/bin/ruby -r ./siteconf20160929-55293-192vx35.rb extconf.rb
checking for ruby/thread.h... yes
checking for rb_thread_call_without_gvl() in ruby/thread.h... yes
checking for rb_thread_blocking_region()... no
checking for rb_wait_for_single_fd()... yes
checking for rb_hash_dup()... yes
checking for rb_intern3()... yes
-----
Using mysql_config at /usr/local/bin/mysql_config
-----
checking for mysql.h... yes
checking for errmsg.h... yes
checking for mysqld_error.h... yes
-----
Don't know how to set rpath on your system, if MySQL libraries are not in path mysql2 may not load
-----
-----
Setting libpath to /usr/local/Cellar/mysql/5.7.14/lib
-----
creating Makefile

To see why this extension failed to compile, please check the mkmf.log which can be found here:

  /Users/akito/git/media/vendor/bundle/extensions/x86_64-darwin-15/2.3.0-static/mysql2-0.4.4/mkmf.log

current directory: /Users/akito/git/media/vendor/bundle/gems/mysql2-0.4.4/ext/mysql2
make "DESTDIR=" clean

current directory: /Users/akito/git/media/vendor/bundle/gems/mysql2-0.4.4/ext/mysql2
make "DESTDIR="
compiling client.c
compiling infile.c
compiling mysql2_ext.c
compiling result.c
compiling statement.c
linking shared-object mysql2/mysql2.bundle
ld: library not found for -lssl
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [mysql2.bundle] Error 1

make failed, exit code 2

Gem files will remain installed in /Users/akito/git/media/vendor/bundle/gems/mysql2-0.4.4 for inspection.
Results logged to
/Users/akito/git/media/vendor/bundle/extensions/x86_64-darwin-15/2.3.0-static/mysql2-0.4.4/gem_make.out

An error occurred while installing mysql2 (0.4.4), and Bundler cannot continue.
Make sure that `gem install mysql2 -v '0.4.4'` succeeds before bundling.

盛大に怒られている...

以下の参考記事の通りにやってみます

RailsプロジェクトでMySQLがbundle installできなかった
https://qiita.com/akito19/items/e1dc54f907987e688cc0

project-name $ bundle config --local build.mysql2 "--with-ldflags=-L/usr/local/opt/openssl/lib --with-cppflags=-I/usr/local/opt/openssl/include"
project-name $ bundle install 
.
..
...
Bundle complete! 18 Gemfile dependencies, 78 gems now installed.
Use `bundle info [gemname]` to see where a bundled gem is installed.
     run bundle exec spring binstub --all
* bin/rake: Spring inserted
* bin/rails: Spring inserted
正常にbundle install完了したみたい

project-name $ rails db:create
Created database ‘project-name_development’
Created database ‘ project-name_test’
project-name $ rails db:migrate
project-name $ rails s
=> Booting Puma
=> Rails 5.2.4.1 application starting in development 
=> Run `rails server -h` for more startup options
Puma starting in single mode...
* Version 3.12.4 (ruby 2.5.1-p57), codename: Llamas in Pajamas
* Min threads: 5, max threads: 5
* Environment: development
* Listening on tcp://localhost:3000
Use Ctrl-C to stop
きたきたきたーーーー!!!!

localhost:3000にアクセスすればいつものrails初期画面が表示されます。MySQLエラーのドツボにハマってrails sでサーバ起動できた時は快感ですね。

【忘れがちなコマンド覚書き】

sudo mysql.server start

→MySQLを立ち上げます

sudo mysql.server stop

→MySQLを停止します

sudo mysql.server restart

→MySQLをstop&startします

sudo mysql.server status

→MySQLの状態を確認します

ps aux| grep mysqld

→MySQLのプロセスを探します

まとめ

以上、私が遭遇したMySQLエラーのまとめでした。自分で何度も遭遇して解決しているうちに遭遇するパターンが同じだったので一覧で見れるようにしておけば後から振り返る時に便利だなと思い久々にQiitaを書いてみました。今回は初めてipadでこの記事を全部書いてみましたが、以外と快適に書けたのでipadとsmart keybord買った甲斐がありました。

終わり

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

railsタグ検索機能(railsチュートリアル後の機能追加)

はじめに

今回は前回追加した、タグ付機能を利用してタグ検索機能を追加します。
前回の記事(タグ付機能)
https://qiita.com/E6YOteYPzmFGfOD/items/bfffe8c3b31555acd51d

作るもの

マイクロポストタグ付機能を利用したタグ検索機能。(題材は自分のポートフォリオです。)

対象読者

railsチュートリアルに機能を追加したい等自分と同じ位のレベルの人を対象としています。

作成の流れ

1.検索フォームの作成
2.コントローラーのアクション作成
3.動作確認

1.検索フォームの作成

今回は検索フォームをroot_path上に設けます。(自分のポートフォリオがマイクロポストの一覧をroot_path(static_pages/home)に設けているため)

app/views/static_pages/home
<%= form_with url: root_path, method: :get, class: '自由に' do %>
  <%= select_tag :tag_id,
    options_from_collection_for_select(Tag.all, :id, :name, params[:tag_id]),
    {
      prompt: 'タグで絞り込み',
      class: ,'自由に'
      onchange: 'submit(this.form);'
    }%>
<% end %>

fomr_withを使って検索フォームを作ります。各指定している値を自分なりに説明します。

url: 検索した後に移動するページ。(getメソッド後の移動するページ)
method::get  検索時はゲットメソッドを使用する。(root_urlにゲットアクションを起こすのでstatic_page_contorollerのhomeアクションに飛びます。

select_tag: フォームの中でセレクトタグを表示するためのメゾット
select_tag:オブジェクト名(tag_id)URLのクエリ(検索するとURLの?以降に表示されてます)
options_from_collection_for_select(
第1引数:オブジェクトのリスト(Tag.all全件表示)
第2,3引数:取得したリストの表示。順番が大切でid,nameの順にすることによりタグnameを表示する。(idを基準に表示する。逆の順番にするとidの数字だけが表示される。)
第4引数:検索後に表示する値。params[:tag_id]とすることによりURLのクエリからidを取得して検索後もフォームにタグ名を表示します。(第2、第3の引数の値が重要です。)

{promt:は何も選択していないときに表示される値です。
onchange:submit(this.form)はJavaScriptを実行できるものでセレクトボックスが選択されたときにこの検索がスタートするようにしています。
}

続いてコントローラーです。

app/controllers/static_pages_controller.rb
@microposts = params[:tag_id].present? ? Tag.find(params[:tag_id]).microposts : Micropost.all
※ページネーション等に渡してください

タグ検索が実行されるとparamsでURLのクエリ(tag_id)を取得してfindでテーブルの中を探し関連付けしているのでmicropostsで関連するマイクロポストを取得します。検索されていない場合は全てのマイクロポストを取得するようにしています。

おまけ

URLのクエリとはURL上に表示されている?以降のやつです。
なんちゃら.com/?utf8=✓&tag_id=1
paramsメゾットではgetメゾット時にURLのクエリを取得できます!
※ログを見るとこんな記述もあります。
Parameters: {"utf8"=>"✓", "tag_id"=>"2"}

以上でタグ検索機能は完成となります。最後までお読みいただきありがとうございました。
アドバイス等いただけるととても喜びます。次はマイクロポストの検索機能を記事にしたいと思います。
ありがとうございました。

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

Rails + jQuery + AjaxでCRUDのサンプルプロジェクト [Hello World]

React + JQuery(+Vanilla JS) + AjaxによるCRUD(作成/読み込み/更新/削除)のサンプルプロジェクトです。 ※Vanilla JSは純粋のJavaScriptです。
jquery_crud_1.png

動作確認はChrome、FireFox、Microsoft Edge、IE11です。恐らくマックさんのブラウザでも動作するはずです。

DEMO

https://www.petitmonte.com/rails-demo/jquery_crud

ソース一式

https://github.com/TakeshiOkamoto/mpp_jquery_crud

※学習用の為、ライセンスはパブリックドメイン

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

二次元配列の格納方法

こんちは!
今日はrails上で二次元配列の格納方法を記載します。

理由

この内容が容易に見当たらなかったため、他の方の助けになればと思います。

一次元配列の格納方法

イメージとしては、[1,2,3,4,5,6]
という風に格納したい場合、railsではコントローラーに以下のように記載するとできます。

tests_contoroller.rb
def idex
  @test = [] #配列の宣言

  6.times do |i = 0| #6回読み込ませる、そしてiには0を格納している。iは初期化式
    @test[i] = i + 1 #初期化式で宣言したiに1足した数字を各配列に代入している。
    i += 1 #iに1を足してはじめに戻る。何もしないままはじめに戻ると同じ配列[0]を六回繰り返すだけだから
  end
  # 配列[i]になぜ1を足さないかは、配列の初期値は[0]だから

二次元配列の格納方法

次は二次元配列です。
イメージとしては[[1,1],[2,1],[3,1]]
と格納したい場合は以下の通りになります。

tests_contoroller.rb
def idex
  @test = [] #配列の宣言

  3.times do |i = 0| #3回読み込ませる、そしてiには0を格納している。iは初期化式
    @test[i] = [i + 1,1] 
    i += 1 
  end

@test[i] ←の部分は、一緒です。
その配列の中に、さらに配列を入れるイメージです。
|1|1|
|2|1|
|3|1|

これを使った応用で、以下のようなコードが表示が実現できます。

<select name="exp_year" id="exp_year"><option value="">--</option>
<option value="2020">20</option>
<option value="2021">21</option>
<option value="2022">22</option>
<option value="2023">23</option>
<option value="2024">24</option>
<option value="2025">25</option>
<option value="2026">26</option>
<option value="2027">27</option>
<option value="2028">28</option>
<option value="2029">29</option>
<option value="2030">30</option></select>

HTML上表示したいものは、1つめの配列に格納されています。
valueの値は、2つめに格納したものがです。

格納例としては、以下の通り
|20|2020|
|21|2021|
|22|2022|
|23|2023|

これらは以下のコードをコントローラー側に入力すると、vew側で表示でます。

tests_controller.rb
  def index
    year = 2020
    @year = []
    11.times do |i = 0|
      @year[i] = [year - 2000,year]
      year += 1
      i += 1
    end
  end

vewには以下の一文追加してね。

tests/test.html.haml
= select_tag 'exp_year',options_for_select((@year),class: "exp_year"),prompt: "--"

追加したら以下のように見れるはずです。(CSSは適当に付けてみるとよいでしょう)
Screenshot from Gyazo

以上です!
またこう言った、見当たらなかったものをあり次第、アップしていきます!

ほなねー。

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

【Rails】flashメソッド

flashメソッド

ユーザーの登録成功や失敗をメッセージ形式で知らせてくれるメソッド。

実行例

controllers/users_controller.rb
  def create
    @user = User.new(user_params)
    if @user.save
      flash[:success] = "Welcome to the Sample App!"
      redirect_to @user
    else
      render 'new'
    end
  end

上記ではユーザーの登録に成功した時に、flash[:success] = "Welcome to the Sample App!"が実行され成功メッセージが表示されるようになっています。
しかしビューの方でも設定を行わないと表示されるようにはなりません。

app/views/layouts/application.html.erb
<省略>

  <body>
    <%= render 'layouts/header' %>
    <div class="container">
      <% flash.each do |message_type, message| %>
        <div class="alert alert-<%= message_type %>"><%= message %></div>
      <% end %>
      <%= yield %>
      <%= render 'layouts/footer' %>
      <%= debug(params) if Rails.env.development? %>
    </div>

<省略>

<% flash.each do |message_type, message| %>でflashの数だけメッセージが表示されるようになっております。

bootstrapを使用していると<div class="alert alert-<%= message_type %>">でメッセージの表示を変更されることができます。
image.png
bootstrapには上記の性質があり、今回のコードで登録に成功するとflash[:success]が実行され<div class="alert alert-<%= message_type %>"><%= message_type %>successに変わり緑色のメッセージが表示されます。

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

【Rails】assert_differenceメソッド

assert_differenceメソッド

処理実行時の値の変化を検証するメソッド。

実行例

assert_difference 'User.count', -1 do
  delete user_path(@non_admin)
end

assert_differenceの第一引数として与えられているUser.countが、ブロック内で変更されているかを検証しています。
第二引数には第一引数の変更される値を示しています。何も指定しないと+1になります。

assert_no_differenceメソッド

assert_no_difference 'User.count' do
  delete user_path(@user)
end

これもassert_differenceメソッドと似たメソッドで、
違いは第一引数であるUser.countがブロック内の処理によって値が変化していないことを検証しています。

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

Twitterログイン機能を搭載したRailsアプリを作る

Twitterログイン機能について学習するため、簡素なテストアプリを作成してみることにしたので、その一連の流れを記しておきます。

大きな流れとしては以下のようになります。

  • アプリを作成する
  • gem「Devise」を導入
  • Twitterにアプリを登録し、key情報を取得
  • gem「dotenv-rails」を導入して、セキュリティ強化
  • Twitterログイン機能の実装

それでは順番に解説していきます!

アプリを作成する

まずはrails newでアプリを作成します。

$ rails new twitter-login-app

作成したアプリのディレクトリへ移動します。

$ cd twitter-login-app

「Devise」を追加

ログイン機能を使用するため、Deviseというgemを使用します。

Gemfile
gem 'devise'
$ bundle install

Deviseをインストールします。

$ rails g devise:install
Running via Spring preloader in process 807
      create  config/initializers/devise.rb
      create  config/locales/devise.en.yml

Deviseで使用するViewファイルを作成します。

$ rails g devise:views
Running via Spring preloader in process 843
      invoke  Devise::Generators::SharedViewsGenerator
      create    app/views/devise/shared
      create    app/views/devise/shared/_error_messages.html.erb
      create    app/views/devise/shared/_links.html.erb
      invoke  form_for
      create    app/views/devise/confirmations
      create    app/views/devise/confirmations/new.html.erb
      create    app/views/devise/passwords
      create    app/views/devise/passwords/edit.html.erb
      create    app/views/devise/passwords/new.html.erb
      create    app/views/devise/registrations
      create    app/views/devise/registrations/edit.html.erb
      create    app/views/devise/registrations/new.html.erb
      create    app/views/devise/sessions
      create    app/views/devise/sessions/new.html.erb
      create    app/views/devise/unlocks
      create    app/views/devise/unlocks/new.html.erb
      invoke  erb
      create    app/views/devise/mailer
      create    app/views/devise/mailer/confirmation_instructions.html.erb
      create    app/views/devise/mailer/email_changed.html.erb
      create    app/views/devise/mailer/password_change.html.erb
      create    app/views/devise/mailer/reset_password_instructions.html.erb
      create    app/views/devise/mailer/unlock_instructions.html.erb

Deviseを使用するモデルを作成します。

$ rails g devise user
Running via Spring preloader in process 886
      invoke  active_record
      create    db/migrate/20200316050323_devise_create_users.rb
      create    app/models/user.rb
      invoke    test_unit
      create      test/models/user_test.rb
      create      test/fixtures/users.yml
      insert    app/models/user.rb
       route  devise_for :users

$ rails db:migrate

これでDeviseに対応したuserモデルが作成されました!

Twitterにアプリを登録し、key情報を取得

Twitterログインを実装するため、Twitter Developersへアプリケーション情報を登録します。
未承認の方は申請の手続きからになります。

以下の記事が参考になるかと思います。

Twitter API 登録 (アカウント申請方法) から承認されるまでの手順まとめ ※2019年8月時点の情報

登録の際、webサイトURLを指定する箇所を「localhost:3000」などローカル環境のアドレスにするとエラーが表示され登録することができないので、適当なアドレスを入力しておきます。

callback urlには、http://localhost:3000/users/auth/twitter/callback と追加し、「Allow this application to be used to Sign in with Twitter」のチェックボックスにチェックを入れておきます。

スクショ.png

アプリケーション作成後、API keyとAPI secret keyの情報を取得しておきます。

「dotenv」を導入して、セキュリティ強化

Twitetrから取得したAPI keyやAPI secret keyの情報をGitなどに公開してしまうと、悪意のある第三者に利用され、損害が発生してしまうリスクがあります。

そのためこうした知られたくない情報は、非公開な情報として扱う必要があります。

そうした時に便利なのが、「dotenv」というgemです。

Gemfile
gem 'dotenv-rails'
$bundle install

その後、Gemfileと同じ位置に「.env」を作成し、先ほどのkey情報を記述します。

.env
# Using Twitter API
TWITTER_API_KEY=API key
TWITTER_SECRET_KEY=API secret key

続いて「.gitignore」を編集します。
ここにファイル名を追加することで、特定のファイルをGitの管理対象から除外することができます。

.gitignore
# See https://help.github.com/articles/ignoring-files for more about ignoring files.
#
# If you find yourself ignoring temporary files generated by your text editor
# or operating system, you probably want to add a global ignore instead:
#   git config --global core.excludesfile '~/.gitignore_global'

# Ignore bundler config.
/.bundle

# Ignore the default SQLite database.
/db/*.sqlite3
/db/*.sqlite3-journal

# Ignore all logfiles and tempfiles.
/log/*
/tmp/*
!/log/.keep
!/tmp/.keep

# Ignore uploaded files in development
/storage/*
!/storage/.keep

/node_modules
/yarn-error.log

/public/assets
.byebug_history

# Ignore master key for decrypting credentials and more.
/config/master.key
.env  #ここを追記

Twitterログインの実装

Twitterログインは「Oauth」という認証機能を使用します。

まずは必要なgemをインストールします!

Gemfile
gem 'omniauth'
gem 'omniauth-twitter'

gemをインストールします。

$ bundle install

先ほど追加したuserモデルにカラムを追加します。

$ rails g migration AddColumnsToUsers uid:string provider:string
Running via Spring preloader in process 91573
      invoke  active_record
      create    db/migrate/20200316073244_add_columns_to_users.rb

$ rails db:migrate

config/initializers/devise.rbを編集します。

config/initializers/devise.rb
Devise.setup do |config|

  #<省略>

  # ==> OmniAuth
  # Add a new OmniAuth provider. Check the wiki for more information on setting
  # up on your models and hooks.
  # config.omniauth :github, 'APP_ID', 'APP_SECRET', scope: 'user,public_repo'

  config.omniauth :twitter, ENV['TWITTER_API_KEY'], ENV['TWITTER_SECRET_KEY']

 #<省略>
end

userモデルに:omniauthableを追加します。

user.rb
class User < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable, :omniauthable
end

続けて以下のメソッドを追加します。
ログインしたアカウントを確認し、初めてログインする場合は新しくアカウントを作成するメソッドになります。

user.rb
class User < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable, :omniauthable

  def self.find_for_oauth(auth)
    user = User.where(uid: auth.uid, provider: auth.provider).first

    unless user
      user = User.create(
        uid:      auth.uid,
        provider: auth.provider,
        email:    User.dummy_email(auth),
        password: Devise.friendly_token[0, 20]
      )
      user.save!
    end

    current_user = user
  end

    private

      def self.dummy_email(auth)
        "#{auth.uid}-#{auth.provider}@example.com"
      end
end

コールバック処理を行うため、app/controllers/users/omniauth_callbacks_controller.rbというコントローラーを作成します。

app/controllers/users/omniauth_callbacks_controller.rb
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController

  def twitter
    callback_from :twitter
  end

  private

  def callback_from(provider)
    provider = provider.to_s

    @user = User.find_for_oauth(request.env['omniauth.auth'])

    if @user.persisted?
      flash[:notice] = I18n.t('devise.omniauth_callbacks.success', kind: provider.capitalize)
      sign_in_and_redirect @user, event: :authentication
    else
      session["devise.#{provider}_data"] = request.env['omniauth.auth']
      redirect_to new_user_registration_url
    end
  end
end

ルーティングを追加します。

config/routes.rb
Rails.application.routes.draw do
  devise_for :users, controllers: { omniauth_callbacks: 'users/omniauth_callbacks' }
end

ログインページ作成

Twitterログイン元のページを作成します。

$rails g controller login index

app/views/login/index.html.erbに、Twitterログインのリンクなどを追加します。

ログイン時はログアウトのリンクを、ログアウト時はログインのリンクを表示できるようにするため、sessionコントローラーを作成します。

$rails g controller session destroy

sessionコントローラーを以下のように変更します。
ログイン時に保存されるsession情報を削除し、rootにリダイレクトする処理です。

sessions_controller.rb
class SessionsController < ApplicationController
  def destroy
    reset_session
    redirect_to root_path
  end
end

ログイン成功時は「Hello,world!」の文字が表示されるようにします。

views/login/index.html.erb
<% if user_signed_in? %>
  <%= link_to 'Twitter Logout', sessions_destroy_path %>
<% else %>
  <%= link_to 'Twitter Login', user_twitter_omniauth_authorize_path %>
<% end %>

<% if user_signed_in? %>
  Hello, world!
<% end %>

ルーティングを追加します。

config/routes.rb
Rails.application.routes.draw do
  root 'login#index'
  get 'sessions/destroy'

  devise_for :users, controllers: { omniauth_callbacks: 'users/omniauth_callbacks' }
  # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
end

実際にログインしてみる

まずはサーバーを起動します。

$cd twitter-login-app
$rails s

localhost:3000にアクセス・・・

スクリーンショット 2020-03-16 17.42.41.png

スクリーンショット 2020-03-16 17.43.01.png

無事ログインでき、リンク表示もログアウトになっています!

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

ここから始めます。目標をぶち上げる。

はじめに

えー、どうも、圧倒的初心者。NSパンダまんです。
今回はProgateにて基本的な勉強を終了した完全未経験くそごみの私が、今年の8月か9月までに本気でモダンなイケてるナウいポートフォリオを作り、それを引っさげて渋谷のWEB系自社開発企業に内定をもらうことを目標としたサクセスストーリーブログです。
あと、学んだ言語ですが、一応、、、

学習教材が多い
短い期間でアプリケーションが作れる。(らしい。実際作ってないから知らん。)
日本人が創り上げた由緒正しき言語である(日本語での問題解決のテキストも多い)
これらの点からファーストチョイスはRubyを選択しました。
Rubyで基礎を深め、そこから他の言語も学んでいこうって寸法です。

あと,,,もしこれをみている変わり者なあなた!!

もしあなたが現在プログラミングを学習していて私と同じようなナウい目標を掲げているのなら、、なんかコメントください。
なんでもいいんです。独学でやってるから寂しいんです。寂しがりやなんです。

ここでは私とおんなじような目標をたてて頑張っている方と共に目標に向かって頑張って行きたい。そんな願いも込めて書いているのです。

*なお初心者でありインターネットのイの字もわかっておりませんので訳のわからんことを書いていると思ったらばしばしと叩いていただければと思います。コメント欄にベギラゴン唱えても可です。

progateを一通り学び終え、さあ次なにするかとひたすら考えておりました。
progateをやっているうちはどんどんと湧き出てくる新しい知識をひたすらインプットするだけで良かったのでかなり思考停止していたと思います。

それが終わったとき、ふと考えてしまったのです。
「あれっこれ次どうすりゃいいの?」ってね。

部活の県大会とかで負けた高校生みたいなもんです。完全に方向性を失いました。

それで色々調べたんですけどなんか、、、よくわかんないんですけど
「RAILS チュートリアル」
ってのを発見したのです。

最初なんかの本なのかなって思ってAmazonで調べまくりました。でもなんかサイト?電子書籍?みたいな感じみたい。

んで必死の思いで探して。。。(ググったら一発ででました)
見てみたんですけど。。。。。

「えっなにこれくっそ読みづらくね??しかも今まで散々インプットしてきたのにまたインプット?お兄さん疲れちゃったよ。もう簡単なアプリ作りたいよ!!」

と正直思いました。やる気になりませんでしたね。あと、なんか外国の方が作っているのかな?それを翻訳した感じでなんか読みづらい。文系のくせに読解能力に疎い私は簡単に2,3分パラパラとページをみて諦めました。笑

とりあえずチュートリアルをすっ飛ばして簡単なアプリ作る方針に決めました。
そこでわからないことあったらまた戻ってインプットすりゃあええと。

というわけで次回は環境構築について書いていきたいと思います!!
それでは!!!!

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

【丁寧解説】Elastic Beanstalkを使ってRailsをサクッとEC2にデプロイしよう

初学者がAWSにデプロイする時、めちゃめちゃ設定あって挫けそうになりませんか?

ええ、わかります。。。
自分も大量のエラーと戦いながら、なんとかデプロイをした経験があります。

新しくアプリを作った時にCI/CDを使ってどうデプロイしようか?と
調べていた時にElastic Beanstalkを知りました。

実際に使ってみて、とても簡単にデプロイ出来たし、
なによりEC2へデプロイすることの全体像をサクッとつかめるなって思ったので
初学者向けに丁寧に解説しようと思って記事を書きました。

デプロイに挫けそうになった方は
ぜひElastic Beanstalktを使って試してみてください!

Elastic Beanstalkt とは?

AWS-Elastic-Beanstalk@4x.png

Elastic Beanstalk では、アプリケーションを実行しているインフラストラクチャについて学習することなく、AWS クラウドでアプリケーションをすばやくデプロイし、管理できます。Elastic Beanstalk は、選択肢を狭めたり制御を制限したりすることなく、管理の複雑さを軽減します。アプリケーションをアップロードするだけで、Elastic Beanstalk が自動的に容量のプロビジョニング、負荷分散、拡張、およびアプリケーションの状態のモニタリングといった詳細を処理します。
AWS Elastic Beanstalk とは

簡単に言えば、インフラ詳しくなくてもアプリをEC2にデプロイできて、
よくあるアプリのインフラ設計で勝手にチューニングしてくれるよってやつです。

aeb-architecture2.png

料金に関しても使ったAWSリソースのみ(今回の記事ではEC2とRDS、S3)なので、
無料枠内で全然試すことができます。

詳しい技術については丁寧に解説してくれている記事が
たくさんあると思うので、興味がある人はそちらをご覧ください。

この記事では0からデプロイができるようになることをフォーカスして解説していきます!

はじめに

前提

  • AWSアカウントを持っている
  • Railsアプリを作成できる
  • 簡単なコマンドがわかっている

大まかな流れ

  1. AWS CLIのインストール・セットアップ
  2. AWS EB CLIのインストール・セットアップ
  3. Railsアプリの用意・デプロイの事前準備
  4. RailsアプリをEC2にデプロイ

この記事のゴール

  • EC2にRailsアプリをデプロイできるようになる
  • ファイルを更新して、再度デプロイを行い、アプリを継続的に更新できること

AWS CLI のインストール・セットアップ

1. AWS CLI 用の IAM を作成

まずAWS CLI用のIAMを作成し、CLIから操作できるようにします。

AWS: IAMこちらからIAMのページに飛んでください。

サイドバーの ユーザーユーザーを追加 をクリックしてAWS CLI用のユーザーを追加します。
iam_001.jpg

ユーザー名はわかりやすいように aws-cli としておきます。

アクセスの種類はCLIからなので、プログラムによるアクセスにチェックを入れます。

次のステップに進みます。

iam_002.jpg

アクセス権限の付与は後ほどするので、そのまま次のステップへ。

iam_003.jpg

特にタグで管理をしていないので、そのまま次のステップへ。

iam_004.jpg

アクセス権限を飛ばしたのでWarningが出ていますが、後ほど追加するのでそのまま次のステップへ。

iam_005.jpg

これでユーザー作成が完了しました。

アクセスキーIDシークレットアクセスキー は後ほど使うので、コピーしておいてください。

iam_006.jpg

2. AWS CLI をインストール

Homebrewをつかって AWS CLI をインストールします。

$ brew install awscli

インストールが問題なくされたか確認します。

$ aws --version
aws-cli/2.0.0 Python/3.8.1 Darwin/19.3.0 botocore/2.0.0dev4

バージョンが表示されればokです。

3. AWS CLI のデフォルト設定を行う

続いてはAWSへのアクセス権限の付与とデフォルト情報を入力していきます。

aws configureを入力すると項目が4つ表示されるので、順に入力していきます。

$ aws configure
AWS Access Key ID [None]: *********
AWS Secret Access Key [None]: ******************
Default region name [None]: ap-northeast-1
Default output format [None]: json

AWS Access Key ID
先程作成したユーザーのアクセスキーID

AWS Secret Access Key
先程作成したユーザーのシークレットアクセスキー

Default region name
使用するリージョン名(東京: ap-northeast-1)

Default output format
アウトプットの表示形式(jsonやtextなど)

4. AWS CLI の設定を確認する

それぞれ設定ファイルをcatで確認します。

下記のような表示になれば問題ありません。

$ cat ~/.aws/credentials
[default]
aws_access_key_id = *********
aws_secret_access_key = ******************

$ cat ~/.aws/config
[default]
region = ap-northeast-1
output = json

変更する場合やユーザーを追加したい時は、上記ファイルに追記すれば可能です。

詳しくはAWS CLI の設定をご覧ください。

AWS EB CLIのインストール・セットアップ

AWS EB CLI をインストール

Elastic Beanstalk用のCLIをインストールします。

$ brew install awsebcli

正しくインストールされたか、確認しましょう。

$ eb --version
EB CLI 3.17.1 (Python 3.8.2)

バージョンが表示されたらインストール完了です。

EB のアクセス権限を付与する

CLI上からElastic Beanstalkを操作できるようにアクセス権限を付けていきましょう。

1. EBアクセス権限のグループを作成する

まずはElastic Beanstalkのアクセス権限をつけたグループを作っていきます。

AWS: IAM からグループ新しいグループの作成 をクリック。

iam_eb_001.jpg

グループ名に eb-cli を入力し、次のステップへ。

iam_eb_002.jpg

検索窓に elasticbeanstalk と入力すると関連のポリシーが出てきます。

FullAccess にチェックを入れて、次のステップへ。

iam_eb_003.jpg

ポリシーが追加されているか確認し、グループの作成をクリック。

iam_eb_004.jpg

これでElastic Beanstalkのアクセス権限があるグループが作成できました。

2. ユーザーをグループに追加する

続いては冒頭に作ったAWS CLI用ユーザーをグループに追加します。

サイドバーのユーザーaws-cli をクリック。

iam_eb_005.jpg

グループユーザーをグループに追加 をクリック。

iam_eb_006.jpg

先程作った eb-cli にチェックを入れ、グループに追加をクリック。

iam_eb_007.jpg

これでAWS CLI用ユーザーがグループに追加され、EB CLIからElastic Beanstalkにアクセスできるようになりました。

iam_eb_008.jpg

Railsアプリの用意・事前準備

Railsアプリを用意する

必要に応じてRailsのアプリを用意してください。

Rubyは2.6.5を使用してください。

EC2でのRubyのVersionが2.6.5のため、異なるとエラーが出ます。

自分の各種version
Ruby: 2.6.5
Rails: 5.2.4.1
Bundler: 2.1.4

自分はシンプルなscaffold構成で作成したものを用意しました。

5.2系統を普段使っているのでRailsのバージョン指定しています。ご自身の環境によって変更してください。

$ bundle exec rails _5.2.4.1_ new eb_sample_app -d postgresql
$ cd eb_sample_app
$ bundle exec rails g scaffold user name:string
$ bundle exec rails db:create
$ bundle exec rails db:migrate

サーバーを立ててみて問題なくアプリが作成できているか確認します。

$ bundle exec rails s

localhost:3000/users を開いて、下記のようなサイトが開けば問題ありません。

SS_ 2020-03-15 22.36.37.jpg

このままではトップページになにも表示されないので、routes.rb にrootを追加します。

Rails.application.routes.draw do
  root 'users#index' # << rootを追加
  resources :users
  # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
end

localhost:3000 を開いてusersと同じページが表示されれば設定完了です。

Rails Serverはこれ以上使わないので、落としておきます。

この時点でコミットしておきます。

~/eb_sample_app
$ git add .
$ git commit -m "first commit"

デプロイの準備をする

eb init で初期設定を行う

eb init を入力して初期設定をしていきます。

アプリのトップディレクトリで行ってください。

~/eb_sample_app
$ eb init

いつくかの項目を入力して設定します。

実行中に ERROR: NotAuthorizedError が出たら?

設定中に ERROR: NotAuthorizedError が出たらアクセス権限エラーになっています。

ERROR: NotAuthorizedError - Operation Denied.
User:arn:aws:iam::476091318231:user/aws-cli is not authorized to perform:elasticbeanstalk:CreateApplication on resource:
arn:aws:elasticbeanstalk:ap-northeast-1:476091318231:application/eb_sample_app

IAMの設定が有効になるには3~5分ほどかかるので、コーヒーブレイクでもはさみましょう。

10分くらいまってもエラーならIAMの設定が間違えているので、再度IAM設定を行ってください。

それでは入力を進めていきます。

使用するリージョンは東京リージョンを使うので、
9) ap-northeast-1 : Asia Pacific (Tokyo)9 を入力

Select a default region
1) us-east-1 : US East (N. Virginia)
2) us-west-1 : US West (N. California)
3) us-west-2 : US West (Oregon)
4) eu-west-1 : EU (Ireland)
5) eu-central-1 : EU (Frankfurt)
6) ap-south-1 : Asia Pacific (Mumbai)
7) ap-southeast-1 : Asia Pacific (Singapore)
8) ap-southeast-2 : Asia Pacific (Sydney)
9) ap-northeast-1 : Asia Pacific (Tokyo)
10) ap-northeast-2 : Asia Pacific (Seoul)
11) sa-east-1 : South America (Sao Paulo)
12) cn-north-1 : China (Beijing)
13) cn-northwest-1 : China (Ningxia)
14) us-east-2 : US East (Ohio)
15) ca-central-1 : Canada (Central)
16) eu-west-2 : EU (London)
17) eu-west-3 : EU (Paris)
18) eu-north-1 : EU (Stockholm)
19) ap-east-1 : Asia Pacific (Hong Kong)
20) me-south-1 : Middle East (Bahrain)
(default is 3): 9

使用するアプリケーションを選択します。

[ Create new Application ]を選択。

※ 初回作成だと[ Create new Application ]のみ

Select an application to use
1) rails-eb
2) [ Create new Application ]
(default is 2): 2

ElasticBeanstalkのコンソール上でのアプリ名です。

特に変更がなければ、なにも入力せず空でエンター。

Enter Application Name
(default is "eb_sample_app"): 

自動的にコードを解析して、使用する言語を提案してくれます。

Rubyで良いので、空でエンター。

It appears you are using Ruby. Is this correct?
(Y/n): 
  • 使用するプラットフォームとバージョンを選択

RailsのデフォルトであるPumaで構築したいので、2) Ruby 2.6 (Puma)2 を入力

※ Rubyのバージョンは使用しているものを選んでください。

Select a platform version.
1) Ruby 2.6 (Passenger Standalone)
2) Ruby 2.6 (Puma)
3) Ruby 2.5 (Passenger Standalone)
4) Ruby 2.5 (Puma)
5) Ruby 2.4 (Passenger Standalone)
6) Ruby 2.4 (Puma)
7) Ruby 2.3 (Passenger Standalone)
8) Ruby 2.3 (Puma)
9) Ruby 2.2 (Passenger Standalone)
10) Ruby 2.2 (Puma)
11) Ruby 2.1 (Passenger Standalone)
12) Ruby 2.1 (Puma)
13) Ruby 2.0 (Passenger Standalone)
14) Ruby 2.0 (Puma)
15) Ruby 1.9.3
(default is 1): 2
  • CodeCommit(AWSが提供してるGitHubのようなもの)を使うかどうか?

使わないので、そのまま空でエンター。

Do you wish to continue with CodeCommit? (y/N) (default is n): 
  • インスタンスにSSHで接続するかどうか?

接続するので、そのまま空でエンター。

Do you want to set up SSH for your instances?
(Y/n):
  • 使用するキーペアを設定します。

すでにキーペアを持っている人は、空のままエンター。

初めての人は[ Create new KeyPair ]のみなので、作成に進んでいきます。

# 作成済
Select a keypair.
1) ec2-keypair
2) [ Create new KeyPair ]
(default is 1): 

# 初めての人
Select a keypair.
1) [ Create new KeyPair ]
(default is 1): 

Create new KeyPairに進むとSSHで接続するキーペアを作成していきます。

キーペアの名前を付けていきます。

好きな名前を付けてください。

Type a keypair name.
(Default is aws-eb): aws-eb

公開鍵と秘密鍵が作成されました。

続いて、鍵にパスワードをつけていきます。
空で入力するとパスワードなしで発行されます。

Generating public/private rsa key pair.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:

下記のような表示になれば作成完了です。

The key fingerprint is:
SHA256:xxxxxxxxxx aws-eb
The key's randomart image is:
+---[RSA 2048]----+
|                 |
|                 |
|      .          |
|     . +         |
|    = * S        |
|   o B E .       |
|o.+ .   +   .    |
|O=   =o+.=.+     |
|X++      .oo.    |
+----[SHA256]-----+

もう一度パスワード入力を求められるので入力します。

Enter passphrase:
WARNING: Uploaded SSH public key for "aws-eb" into EC2 for region ap-northeast-1.

EC2へのSSH接続が確認されキーペアの連携ができました。

これで初期設定が完了です。

.elasticbeanstalk フォルダが作成され、中に config.yml という設定ファイルが作成されました。

eb_init_directory.jpg

config.yml の中身は以下のようになっています。

~/eb_sample_app/.elasticbeanstalk/config.yml
branch-defaults:
  master:
    environment: null
    group_suffix: null
global:
  application_name: eb_sample_app
  branch: null
  default_ec2_keyname: aws-eb
  default_platform: Ruby 2.6 (Puma)
  default_region: ap-northeast-1
  include_git_submodules: true
  instance_profile: null
  platform_name: null
  platform_version: null
  profile: null
  repository: null
  sc: git
  workspace_type: Application

eb createの前に各種問題への対処

続いてeb createをするのですが、そのまま実行すると3つのエラーが発生します。

それぞれどんなエラーが発生するのか解説し、事前に対応します。

1. bundlerが古い問題

そのまま実行すると自動で実行される bundle install でエラーがでます。

エラーの内容は指定されているBundlerが無いぞ!って言われてます。

ERROR   [Instance: i-02e2bc303363c3671] 
Command failed on instance. Return code: 1 Output: (TRUNCATED)...your system, 
run `bundle update --bundler`.
To install the missing version, run `gem install bundler:2.1.4`

これは初期に生成されるEC2環境のBundlerのバージョンが1.16.0のため、最新のBundleが無いんですね。

[ec2-user@ip-172-31-2-55]
$ bundle -v
Bundler version 1.16.0

SSHで接続してgem install bundler:2.1.4でインストールしてもいいのですが、それだと毎回設定が必要です。

しかもこのままではAuto Scalingで2台目が立ち上がったときも設定が必要で意味がありません。

ElasticBeanstalkには初回にコマンドを実行する設定があるので、そちらで必要となる処理を記載していきます。

gem install bundlerの実行設定をする

アプリのトップディレクトリに.ebextensionsというファイルを作成します。
.は必要なので気をつけてください!

このファイルに~.configというファイルを作成すると実行時に読み込んで実行してくれます。

~/eb_sample_app
$ mkdir .ebextensions
$ cd .ebextensions
$ touch gem_install_bundler.config

中身を下記の内容で作成します。

~/eb_sample_app/.ebextensions/gem_install_bundler.config
files:
  "/opt/elasticbeanstalk/hooks/appdeploy/pre/09_gem_install_bundler.sh" :
    mode: "000775"
    owner: root
    group: users
    content: |
      #!/usr/bin/env bash

      EB_SCRIPT_DIR=$(/opt/elasticbeanstalk/bin/get-config container -k script_dir)
      EB_APP_STAGING_DIR=$(/opt/elasticbeanstalk/bin/get-config container -k app_staging_dir)
      . $EB_SCRIPT_DIR/use-app-ruby.sh

      cd $EB_APP_STAGING_DIR
      gem update --system
      gem install bundler -v 2.1.4

内容は、自動で実行されるbundle installの前に
gem update --system
gem install bundler -v 2.1.4
を実行するコードになります。

gem install bundler -v 2.1.42.1.4はご自身のBundler versionを指定してください。

Gemfile.lockの一番下に書いてあるBUNDLED WITHに合わせないとエラーになります。

Gemfile.lock
BUNDLED WITH
   2.1.4

3. master.keyが無い問題

続いてはrails credentials:editが発生します。

ERROR   [Instance: i-012e1680a4956ac39] 
Command failed on instance. 
Return code: 1 
Output: (TRUNCATED)...tring with `rails credentials:edit`

ElasticBeanstalkにデプロイすると自動でproduction環境になります。

その際にconfig/master.keyもしくはRAILS_MASTER_KEYを参照しているのですが、
config/master.keyは秘密鍵なのでgitignoreでgitにcommitされないようになっています。
この情報がないためエラーになります。

詳しくはこの記事では触れないため、下記のサイトを参照してください。

Rails5.2から追加された credentials.yml.enc のキホン

Serverに環境変数であるRAILS_MASTER_KEYを設定しましょう。

まずはconfig/master.keyを開きます。

~/eb_sample_app/config/master.key
da7xxxxxxxxxxxxxxxxxdf1b1de

中に文字の羅列があるので、そちらをコピーしておいてください。

eb create時に--envvars のオプションをつけると環境変数を設定できます。

eb create実行する時に以下のコマンドを付ければ解決です。
※まだ実行しないでください。

eb create --envvars RAILS_MASTER_KEY=da7xxxxxxxxxxxxxxxxxdf1b1de

複数つける場合はカンマ区切りでつけることができます。

--envvars key=value,key2=value2,key3=value3

3. DBが無い問題

続いてのエラーはDBがなくて db:migrate が出来ないよ!っていうエラーです。

ERROR   [Instance: i-048e3c74bf17b2499] 

Command failed on instance. 
Return code: 1 Output: (TRUNCATED)...ly and accepting
connections on Unix domain socket "/var/run/postgresql/.s.PGSQL.5432"?
Tasks: TOP => db:migrate

ElasticBeanstalkでは、RDSの立ち上げはオプションなので eb create にDB作成するオプションを付けて自動で作成されるようにします。
※まだ実行しないでください。

eb create -db.engine postgres \
-db.user ebroot -db.pass testpassword

-db.engine postgres
DBのエンジンを決めます。mysql postgres など設定できます。

-db.user ebroot
DBのデフォルトユーザー名です。
お好きな名前を付けてください。デフォルトは ebroot です

-db.pass testpassword
DBのデフォルトユーザーのパスワードになります。
好きなパスワードを入れてください。

Elastic Beanstalkへデプロイ

eb createでアプリケーションを作成する

準備が整いました。eb createを実行しましょう。

以下のコマンドを丸々コピーして実行してください。
※オプションの値は適宜自分のものに変更してください。

~/eb_sample_app
eb create -db.engine postgres \
-db.user ebroot -db.pass testpassword \
--envvars RAILS_MASTER_KEY=da7xxxxxxxxxxxxxxxxxdf1b1de

実行すると4つの項目を聞かれます。

すべてデフォルトで良いので、空でエンターを4回押します。

Enter Environment Name
(default is eb-sample-app-dev): 

Enter DNS CNAME prefix
(default is eb-sample-app-dev): 

Select a load balancer type
1) classic
2) application
3) network
(default is 2): 

Would you like to enable Spot Fleet requests for this environment?
(y/N): 

するとなにやら実行されます。

EC2やらなんやら立ち上げていて、10分ほどかかるので2度目のコーヒーブレイクをお楽しみください。

Creating application version archive "app-f738-200316_020752".
Uploading eb_sample_app/app-f738-200316_020752.zip to S3. This may take a while.
Upload Complete.
An environment with that name already exists.
Enter Environment Name
(default is eb-sample-app-dev2): 
Environment details for: eb-sample-app-dev
  Application name: eb_sample_app
  Region: ap-northeast-1
  Deployed Version: app-f738-200316_020752
  Environment ID: 
  Platform: arn:aws:elasticbeanstalk:ap-northeast-1::platform/Puma with Ruby 2.6 running on 64bit Amazon Linux/2.11.3
  Tier: WebServer-Standard-1.0
  CNAME: 
  Updated: 2020-03-15 17:08:44.727000+00:00
Printing Status:
2020-03-15 17:08:42    INFO    createEnvironment is starting.
2020-03-15 17:08:44    INFO    Using elasticbeanstalk-ap-northeast-1-476091724641 as Amazon S3 storage bucket for environment data.
2020-03-15 17:09:06    INFO    Created target group named: arn:aws:elasticloadbalancing:ap-northeast-1:476091724641:targetgroup/awseb-AWSEB-1EYCMUPNKMX61/ccc7435548d76a87
2020-03-15 17:09:06    INFO    Created security group named: sg-09f51d827976f2e04
.
.
.

ログを見ると作成されてるのはこれらのようです。

  • Environment
  • Target Group
  • Security Group
  • Auto Scaling
  • RDS Database
  • Load Balancer
  • EC2 Instances
  • CloudWatch Alarm

時間がある方は、なにが作成されているのかチェックしてみてください。

時間がかかって ERROR: TimeoutError になった人は eb events -f を実行すれば再度確認できます。

ERROR: TimeoutError - The EB CLI timed out after 15 minute(s).
The operation might still be running. To keep viewing events,
run 'eb events -f'. To set timeout duration, use '--timeout MINUTES'.
$ eb events -f

Successfully が表示されれば完了です!

2020-03-15 17:14:00    INFO    Successfully launched environment: eb-sample-app-dev

デプロイしたアプリをひらく

eb open を実行すると作成したアプリを開くことができます。

実行してみましょう。

$ eb open

ブラウザでアプリが開けば成功です。

eb_product.jpg

実際にユーザーを作成して成功するか試してみましょう。

New Usernameを入力Create User

Successfullyと出れば成功です!

eb_product_user.jpg

トップに戻ると作成されていることが確認できます。

eb_product_users.jpg

AWS: ElasticBeanstalkを確認すると作成されたアプリケーションが確認できます。

緑色になっていると問題なく動作している状態です。
赤色などになっているとなにか問題が起きています。

作成したアプリケーションを開いてみましょう

eb_plat.jpg

作成したアプリケーションの情報が表示されます。

URLの部分が今回作成されたアプリケーションのURLです。

eb_plat2.jpg

サイドバーの設定を開くとインスタンスやロードバランサーの設定を確認することができます。

再度デプロイをする方法

ファイルを更新したら、commitしてeb deployをすれば
自動でファイルを転送されデプロイが完了します。

$ git add .
$ git commit -m "Add ..."
$ eb deploy

デプロイがこんなに簡単にできるなんて最高!!

SSH接続をする方法

EC2にSSH接続するには eb ssh を実行するとSSH接続できます。

$ eb ssh

Railsアプリは /var/app/current/ に入っているので、気になる人はチェックしてみてください。

[ec2-user@ip-172-31-1-95]
$ cd /var/app/current/
$ ls
Gemfile       Rakefile  config     lib           public   tmp
Gemfile.lock  app       config.ru  log           storage  vendor
README.md     bin       db         package.json  test

エラーで表示できなかった場合

エラーなどで表示できなかった方は、ログをチェックしてみてください。

$ eb logs

まとめ

今回はElastic Beanstalkを使って簡単にEC2にデプロイを試してみました。

VPC、RDSやオートスケール、ロードバランサーなど複雑な設定を知らなくても
スタンダードなインフラ設計で簡単につくれるElastic Beanstalkはとても良いと思いました。

ただ、VPCや中でなにを行われているのかわからないため、インフラを理解する観点として
同じ設計を手動で立てれるようになることも重要だと思います。

全体像を掴む方法として、まずはElastic Beanstalkを使ってみることをおすすめします!

次回の記事ではSSL化、RDSを独立させる方法、Dockerを使ったデプロイなどを解説していこうと思います。

参考にさせていただいたサイト

AWSのElastic Beanstalkでナウい構成のWebアプリを構築しよう! - Qiita
Rails5.2から追加された credentials.yml.enc のキホン - Qiita
Ruby on Railsの環境構築をElastic Beanstalkで行う - Qiita
RailsアプリケーションをElastic Beanstalkにデプロイするまで - Qiita
【2020年版】RailsアプリをElasticBeanstalkでデプロイするまでの手順 | ニートエンジニア
Elastic Beanstalk: can't find gem bundler (>= 0.a) - Stack Overflow
EB CLI コマンドリファレンス

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

MySQLが起動できない(動かなくなった) という地獄のエラー(ERROR! The server quit without updating PID file  と Fatal error: Can't open and lock privilege tables: Table 'mysql.user' doesn't exist)

背景

phpの学習中にmysqlをいじっていましたw
急にmysqlが起動できなくなり、エラー解消にほぼ半日躓いてしまったので、
その解決策と試したことを記事としてのせたいと思う!!

mysqlでのエラー文との遭遇

エラー内容一覧

mysqlを起動を確かめる

 mysql.server start
Starting MySQL
. ERROR! The server quit without updating PID file (/usr/local/var/mysql/ユーザーMBP.pid).

意味はpidファイルを更新せずに終わったよ!ってエラー?
すいません、、、意味がわかりません(涙)

pidファイルとは?

Pidファイルには、特定のプログラムのプロセスID(番号)が含まれています。たとえば、Apache HTTPDはメインプロセス番号をpidファイル(通常のテキストファイル、それ以上のもの)に書き込み、後でそこに含まれる情報を使用して停止します。 cat filename.pid | xargs killを使用して、その情報を使用して自分でプロセスを強制終了することもできるみたいです。

ググって試したこと!

①権限関係

権限確認すると「_mysql:_mysql」だったので、自分:adminに変更した。

chown -R [ユーザ名] /usr/local/var/mysql

うまくいかず。

②エラーログ確認しにいく

cd /usr/local/var/mysql
ls (lsコマンドでmysqlディレクトリの中身を確認する)
その中に
(ユーザー)MBP.err   というファイルがあるので
cat (ユーザー)MBP.err (catコマンドでファイルの中身を確認)

エラーログの中身に

2020-03-16 17:32:04 25993 [ERROR] Fatal error: Can't open and lock privilege tables: Table 'mysql.user' doesn't exist

調べてみると、インストール時に mysql_install_db が実行されるが、ディレクトリがわからない状態らしい。
インストール場所とユーザ名を指定して明示的に実行すると良さそうらしいですが、、

mysql_install_db --datadir=/var/lib/mysql --user=mysql

うまくいかず...
参考ページ
https://qiita.com/840_/items/06f32fecbe57c3fdf5ec

③最終手段 全てをアンイストール!!

よく見るとmysql、mysql@5.6、mysql@5.7やらいっぱいmysqlが存在してしまっていたので全てアンインストール!

の前に
*実行前に
そのまま解決手順を実行してしまうと、mysqlのデータが削除されてしまいます。
以下の手順を実行し、バックアップを行ってください!!

$ brew services stop mysql 
 mysqlを一旦停止
$ cp -pr /usr/local/Cellar/mysql /適当な場所/mysql_backup
  これで、mysqlのデータバックアップ。
brew uninstall mysql  
brew uninstall mysql@5.6 
brew uninstall mysql@5.7

まずはmysqlをアンインストール!

次にlocal配下のmysqlを全て削除する

$ rm -rf /usr/local/mysql
$ rm -rf /Library/StartupItems/MYSQL
$ rm -rf /Library/PreferencePanes/MySQL.prefPane
$ rm -rf /Library/Receipts/mysql-.pkg
$ rm -rf /usr/local/Cellar/mysql*
$ rm -rf /usr/local/bin/mysql*
$ rm -rf /usr/local/var/mysql*
$ rm -rf /usr/local/etc/my.cnf
$ rm -rf /usr/local/share/mysql*
$ rm -rf /usr/local/opt/mysql

ポイント!

brew uninstall mysqlでは削除できないファイル群を削除するのが大事!
残っているとアンインストールしても解消されないので、すっきり全て削除!

mysqlを再インストール

brew install mysql(@__使用するmysqlバージョンを指定)

mysqlコマンドをどこからでも実行できるようする

$ echo 'export PATH="/usr/local/opt/mysql/bin:$PATH"' >> ~/.bash_profile

 mysqlバージョンを指定している場合(mysql@5.6)
$ echo 'export PATH="/usr/local/opt/mysql@5.6/bin:$PATH"' >> ~/.bash_profile

$ source ~/.bash_profile 

  mysqlのコマンドが打てるか確認する
$ which mysql
  以下のように表示されれば成功
/usr/local/opt/mysql/bin/mysql

最後にmysqlを起動

 mysqlの状態を確認するコマンドです
$ mysql.server status

 以下のように表示されれば成功
 SUCCESS! MySQL running (29385)

他にもプロセスを確認

$ ps ax | grep mysql
29714 s001  S      0:00.03 /bin/sh /usr/local/Cellar/mysql/8.0.19/bin/mysqld_safe --datadir=/usr/local/var/mysql --pid-file=/usr/local/var/mysql/ユーザMBP.pid
29825 s001  S      0:05.17 /usr/local/Cellar/mysql/8.0.19/bin/mysqld --basedir=/usr/local/Cellar/mysql/8.0.19 --datadir=/usr/local/var/mysql --plugin-dir=/usr/local/Cellar/mysql/8.0.19/lib/plugin --log-error=ユーザMBP.err --pid-file=/usr/local/var/mysql/ユーザMBP.pid
29837 s001  S+     0:00.00 grep mysql

ok問題ないですね!

参考
https://teratail.com/questions/199085

これでようやく解決してくれました!

本当に強引な方法ではありますがうまくいきました!

最後に

本当によく躓くエラーなので反省をとこれからの課題として記事として残しておきます!!

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

【Rails】setupメソッド

setupメソッド

テストファイル上で記載するメソッドで、各テストが走る前に実行されるメソッド。
またsetupメソッドでインスタンス変数を定義すれば全てのテスト内で、そのインスタンス変数が使用可能になります。

実行例

test/models/user_test.rb
require 'test_helper'

class UserTest < ActiveSupport::TestCase

  def setup
    @user = User.new(name: "Example User", email: "user@example.com")
  end

  test "should be valid" do
    assert @user.valid?
  end
end

こうすることでテストであるshould be validが走る直前にset upが実行されるようになります。
assert @user.valid?@userset upから持ってきています。

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

Ruby on RailsとAlexaで、めちゃんこ操作しにくいゲーム作ってみた。

hero_img_Ruby_Ruby-on-Rails-1.jpg

初めに

スクリーンショット 2020-03-16 17.04.11.png

 この記事では、Ruby on Railsを使用して、Alexaによる音声認識で操作することができる3×3のスライドパズル作成についてかきました。
 Ruby on Railsや、今回サーバーの実装として利用したngrokの導入方法についての説明は省いておりますのでご了承ください。
 今回、技術的説明は極力省き、実装面のみの記事としているため、主な技術要件の参考記事は以下を参照ください。

  1. Alexaコンソールについて
     Alexaコンソール(Alexaスキル)では、どのような情報をサーバー(Ruby on Rails側)にPOSTするのか書き込みます。
    クリスマスプレゼントに、Amazon Echoはいかが?〜Alexaスキルを自作してみよう〜 - Qiita

  2. ActionCableについて
     ActionCableは、Railsに比較的新しく備え付けられた非同期処理を実装するための方法です。WebSocketとの連携を補助するツールと筆者は捉えています。
    最短で作るActionCableチャットアプリ - Qiita

  3. ngrokについて
     こんなの説明いらんやろ!と言われそうですが一応。。
    【3分で出来る】ngrokでデプロイをしてみよう! - Qiita

ngrokを利用するための下準備

#config/environments/development.rb
config.hosts << '.ngrok.io'

上記を追加し、ngrokによるホスティングを許可してあげればOK

ActionCableを利用するための下準備

これは簡単です。

bash
$ rails g channel talks

このコマンドで、WebSocketに関するファイルが生成されます。
今回はコントローラー名も一括してtalksにしています。

#app/channels/talks_channel.rb
class TalksChannel < ApplicationCable::Channel
  def subscribed
    stream_from "some_channel"
  end

  def unsubscribed
    # Any cleanup needed when channel is unsubscribed
  end

  def speak
  end
end

some_channelというケーブル名にしましょう。

Railsのルーティング設定

以下を記載します。

#config/routes.rb
Rails.application.routes.draw do
  root 'talks#index'
  resources :talks, only: [:create, :index]
end

 カレントディレクトリをプロジェクト内にし、以下のコマンドでルーティングを確認できます。

bash
$ rails routes
POST   /talks(.:format)

 Alexaに話しかけた内容は、エンドポイントで指定されたURLにPOSTで送られます。/talksをAlexaコンソール上でエンドポイントに設定します。

 続いて、コントローラーです。

#app/controllers/tasks_controller.rb
class TalksController < ApplicationController
  skip_before_action :verify_authenticity_token

  # POST /talks
  def create
    request = AlexaRubykit::build_request(params)
    #paramsはAlexaから送られるJSONデータ
    request_word = request.slots[:message][:value]

    response = AlexaRubykit::Response.new
    response.add_speech("#{request.slots[:message][:value]}に移動します.")

    message = @@board.slide(request_word)
    ActionCable.server.broadcast("some_channel",message)

    render json: response.build_response
  end

  def index
    @@board = Board.new
  end

end

#0は空白
class Board
  def initialize
    @@panels = [
      [1,3,6],
      [0,7,2],
      [5,8,4]
    ]
  end
  #入れ替える要素の番号を引数として配列で受け取る index → [j,i]
  def swap(index1,index2)
    tmp = @@panels[index1[0]][index1[1]]
    @@panels[index1[0]][index1[1]] = @@panels[index2[0]][index2[1]]
    @@panels[index2[0]][index2[1]] = tmp
  end
  def slide(dir)
    brank_index = Array.new(2)
    @@panels.each_with_index do |panel,j|
      i = panel.find_index { |value| value == 0}
      if i != nil
        brank_index = [j,i]
        break
      end
    end
    case dir
    when '上', 'ウェイ'
      if brank_index[0] != 2
        self.swap(brank_index,[brank_index[0]+1,brank_index[1]])
      end
    when '下'
      if brank_index[0] != 0
        self.swap(brank_index,[brank_index[0]-1,brank_index[1]])
      end
    when '左'
      if brank_index[1] != 2
        self.swap(brank_index,[brank_index[0],brank_index[1]+1])
      end
    when '右'
      if brank_index[1] != 0
        self.swap(brank_index,[brank_index[0],brank_index[1]-1])
      end
    end
    @@panels
  end
end
#Gemfileに以下を追加
gem 'alexa_rubykit', '1.3.1'

 一気に長いコードが出てきたので少し説明します。
 まず、Boardクラスは、初期化やAlexaからのメッセージによって盤面を移動させたりする関数(slide())から構成されています。

request = AlexaRubykit::build_request(params)
request_word = request.slots[:message][:value]

 この部分では、Alexaから送られたJSONがparamsに入っており、AlexaRubyKitで受け取り、目的とする単語(今回の場合はスライドパズルなので「上」や「下」)をrequest_wordに渡します。

response = AlexaRubykit::Response.new
    response = AlexaRubykit::Response.new
    response.add_speech("#{request.slots[:message][:value]}に移動します.")
~~
    render json: response.build_response

 この部分では、Alexaに応答させる言葉をadd_speechに持たせて、renderでAlexaに送っています。

message = @@board.slide(request_word)
ActionCable.server.broadcast("some_channel",message)

 Alexaから受け取った言葉をslide関数に渡して、盤面を更新していきます。そして更新された盤面をsome_channelというActionCableを使ってクライアント側にブチ飛ばしていますね。

クライアント側での処理

 先ほどブチ飛ばした内容は、talks_channel.jsで受け取ります。

#javascript/channels/talks_channel.js
import consumer from "./consumer"

consumer.subscriptions.create("TalksChannel", {
  connected() {
    // Called when the subscription is ready for use on the server
  },

  disconnected() {
    // Called when the subscription has been terminated by the server
  },

  received(data) {
    // Called when there's incoming data on the websocket for this channel
    let txt = '';
    data.forEach((value) => {
      txt += '<div class="line">';
      value.forEach((e) => {
        if (e == 0){
          txt += '<div class="empty-box" ></div>';
        }else{
          txt += '<div class="box" ><p>' + e + '</p></div>';
        };
      });
      txt += '</div>'
    });
    document.querySelector("#display").innerHTML = txt;
    console.log(txt);
  },

  speak: function() {
    return this.perform('speak');
  }
});

 こんな感じで、クライアント側のjsをいじると、画面を更新することなくスライドパズルが動くというわけです。
 あとはHTMLとCSSを適当にいじって完成です。
スクリーンショット 2020-03-06 16.13.48.png
 なんとも春らしい見た目。

最後に

 AlexaRubyKitってなかなか日本語のドキュメントもないしかなり苦戦したので、これからAlexaを使ってアプリケーションを作ろうとする方の手助けになればいいなと思います。
 ActionCableは筆者的に今熱いのでどんどんプロダクトに使って行きたいですね。
 これからも励んでいきますので、よろしくお願いします。:pig_nose:

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

部分テンプレートとは?

部分テンプレートってなんなの??

部分テンプレートとは・・・
複数のビューファイルの中で使われている部分を一つのビューファイルとして管理すること。

つまりどういうことかというと複数回使うビューをテンプレート化してしまうことで冗長な記述が必要なくなるというとっても便利かつ簡単なテクニックです。

部分テンプレートを作成する

部分テンプレートのビューを作成するときの注意点としてビューファイルのファイル名の先頭の部分に_ (アンダーバー)をつける必要があります。
例えば、呼び出したい部分テンプレートファイルがheader.html.erbだとすると、
_header.html.erbと書き換えましょう。

部分テンプレートの呼び出し方

当たり前ですが、実際に部分テンプレートを呼び出すためのメソッドがあります。それが
renderメソッド です.

_header.html.erb
render 'ファイル名'  #'ファイル名'で部分テンプレートの呼び出し

render partial: 'ファイル名' #partialはつけてもつけなくても可

このように記述していくことで部分テンプレートが使用できて、同じようなコード再度記述していく必要がなくなります!便利ですよね。

hamlで書くとどうなるのかというと

_header.html.haml
= render 'ファイル名' #=でくくってあげちゃうだけ

renderメソッドにはもっと活用できるオプションがあるみたいなので詳しく知りたい方は検索してみましょう(優秀なエンジニアに丸投げ)

以上です。至らない点があればコメントお願いします。

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

FontAwesomeとは

FontAwesome

アイコンを表示させることができます。
Gemfileの一番下に

gem 'font-awesome-sass'
bundle install
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Hamlとは

Haml

HTMLよりも簡単に書くためのビューテンプレートエンジンです。
Hamlを使用することで、「綺麗に」、「読みやすく」、「生産的に」ビューを作成することができます。

HamlのGem

Haml記法を可能にするhaml-railsというGemが提供されています。このGemをプロジェクトにインストールすることで簡単にHamlを導入することができます。また、既存のerbファイルをHaml記法に変換することもできます。
Gemfileの一番下に記述します。

gem "haml-rails"
bundle install

ターミナル

$ rails haml:erb2haml

でerbのファイルをhamlに変換します。

Hamlの記述(タグ)その1

【例】HTMLの場合

<form>
  <input type="submit">
  </input>
</form>

【例】Hamlの場合

%form
  %input{type: "submit"}

Hamlの記述(タグ)その2

【例】HTMLの場合

<% messages.each do |message| %>
  <%= @message.content %>
<% end %>

<%= link_to messages_path, class:"contents" do %>
  <%= @message.name %>
<% end %>

【例】Hamlの場合

- messages.each do |message|
  = message.content

= link_to messages_path, class:"contents" do
  = @message.name

Hamlの記述(クラス)

【例】HTMLの場合

<div class="top">
</div>

<div class="main center">
</div>

<form class="down">
</form>

【例】Hamlの場合

.top

.main.center

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

BEMとは

BEM

多くの開発者が取り入れているCSS設計(CSSを記述する時のルール)です。BEMは、厳格なクラスの命名規則が特徴です。BEMはBlock、Element、Modifierの頭文字を取ったもので、ページを構成する要素をBlock、Element、Modifierのどれかに当てはめてクラスを命名します。

クラスの命名が簡単になる

Block、Element、Modifierのみでクラスを命名することで、クラス名に悩むことがなくなります。

要素の再利用がしやすくなる

共通の要素を別の場所で再利用しようとしても、要素がHTMLに依存していると同じCSSを2つ書かなければなりませんでした。しかし、BEMを使用することで、クラスの命名がHTML構造に依存しなくなります。
HTML構造に依存しないことで、要素の再利用がしやすくなります。

Block

ある要素の大元となるブロック要素です。Blockの命名には名詞を使用します。ElementやModifierは、Blockを起点に命名されます。

Element

Blockに属する子要素です。1つ以上のElementによって、Blockは構成されています。Elementの命名には名詞を使用します。

Modifier

Blockまたは、Elementに特別な修飾をする要素です。Modifierの命名には形容詞を使用します。

命名規則

BlockとElementをつなぐ場合は、アンダースコア2つでつなぎます。
Modifierにつなぐ場合は、ハイフン2つでつなぎます。
【例】

XXXX.html
nav class='HeaderNav'>
  <ul class='Menu'>
    <li class='Menu__list'>TOP</li>
    <li class='Menu__list'>CONTACT</li>
    <li class='Menu__list Menu__list--backBlack'>ABUOT US</li>
    <li class='Menu__list'>SERVICE</li>
   </ul>
</nav>

navはヘッダーのナビゲーションメニューなので、クラス名をHeaderNavとしました。
このようにクラス名の単語数が2つ以上の場合はキャメルケースまたはスネークケースでつなぎます。
ulはheader-navの子要素ですが他のヘッダーメニュー以外の部分でも使用したいので、クラス名をMenuとしました。
liはMenuの子要素なので、クラス名をMenu_listとしました。
liのうちABOUT USだけは背景色を黒くしたいので、クラス名をMenu
_list--backBlackとしました。
Modifierはこのように特定の部品を修飾したい時に使用します。
上記に対したSass

XXXX.scss
.Menu {
  list-style: none;
  &__list {
    background-color: #3BD1EC;
    color: #FFF;
    float: left;
    font-size: 30px;
    padding: 2% 1%;
    text-align: center;
    width: 23%;
    &--backBlack {
      background-color: #000;
      color: #3BD1EC;
    }
  }
}

Modifierを使用した部分だけ背景色を黒くできました。

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

Sassのファイルとフォルダ

index.html

このファイルに書かれたものがブラウザに表示されます。

style.css

htmlファイルでstyle.cssファイルを読み込むことでスタイルを適用させます。
style.cssファイルを直接編集するのではなく、sassコマンドを実行することでstyle.cssファイルを作成・更新します。

stylesheetsフォルダ

すべてのscssファイルを管理するフォルダです。
scssファイルを追加する場合は、stylesheetsフォルダ内に作成します。

style.scss

このファイルですべてのscssファイルを@importで読み込むことで、一つのsassファイルに統合します。
【例】@importを使用してscssファイルを読み込みます

@import "reset";  /*_reset.scssを読み込む */
@import "./config/XXXX"; /* configフォルダの中の_XXXX.scssを読み込む */

_reset.scss

ブラウザによって初めからcssがそれぞれのhtmlに設定されています。
そのCSSによって、意図しないデザインになってしまうことがあります。
そのようなことを防ぐために、初めにブラウザごとのCSSをすべてリセットします。
HTML5 Doctor Reset CSS 2.0
sanitize.css
などがあります。

configフォルダ

プロジェクトの設定ファイルや、scssで使用する変数を定義するファイルなどを管理するフォルダです。

mixinフォルダ

scss内で使用するmixinファイルを管理するフォルダです。

modulesフォルダ

モジュールを管理するためのフォルダです。
モジュールとは、いくつかの要素をまとめた部品の集合という意味です。
ヘッダー、フッターのような用途ごとに分けることができます。
モジュールを使うことでまとまったCSSを独立したものとして管理することができます。

vendorフォルダ

ライブラリのファイルを管理するフォルダです。
ライブラリとはあらかじめCSSが書かれたファイルです。

overrideフォルダ

vendorフォルダに格納してある外部のライブラリを上書きするためのscssファイルを管理するフォルダです。

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

Sass

Sassとは

SassとはCSSの機能を拡張した言語です。Sassを使用することでCSSを効率的に書けるようになります。CSSを簡潔に書けるだけではなく、CSSの中で変数を使ったり、計算を行うことなどができます。

Sassファイル

Sassは通常のCSSファイルには記述することができません。反対にSassファイルにCSSを記述することはできます。Sassを扱うファイルの拡張子は.sassと.scssの2種類があります。どちらもSassのファイルとなりますが記法が大きく異なります。

.sass拡張子

Sassファイルでは最初に作られたSassの記法を扱うことが出来ます。Sassは波カッコの省略やセミコロンが不要などシンプルな記法です。
【例】Sass

.body p
  color: #333
  font-size: 10px
  font-weight: normal
  strong
    color: red
    font-weight: bold

.scss拡張子

.sassの後に作られたSassファイルが.scssの拡張子のファイルです。scssはCSSに非常に似た記法でSassの機能を使うことが出来ます.
【例】

.body p {
  color: #333;
  font-size: 10px;
  font-weight: normal;
  strong {
    color: red;
    font-weight: bold;
  }
}

記述の簡略化

例えば親子関係にあるセレクタを入れ子にして書くことができます。
CSSでは、親の要素から対象要素までのセレクタを何度も書く必要がありますが、Sassはネストさせることで、同じ親のセレクタをまとめることができます。
【例】例えばこんなhtmlがあるとします

<div class="block">
  <h1 class="title">XXXX</h1>
  <p class="text">YYYY <span>ZZZZ</span>
</div>

【例】CSSの場合

.block {
  background-color: #000;
}

.block .title {
  color: #FFF;
  font-size: 50px;
  text-align: center;
}

.block .text {
  font-size: 10px;
  color: #FFF;
}
.block .text span {
  color: red;
  font-size: 20px;
}

【例】sassの場合

.block {
   background-color: #000;
  .title {
    color: #FFF;
    font-size: 50px;
    text-align: center;
  }
  .text {
    font-size: 10px;
    color: #FFF;
    span {
      color: red;
      font-size: 20px;
    }
  }
}

SassではCSSをネスト(入れ子)して記述することができます。ネストして記述することで深い階層になっても親子関係がわかりやすくなり、親要素を複数記述しなくて済みます。

変数や条件分岐といったプログラムのような処理を記述できる

Sassでは、変数を使用することができます。例えばピクセル数やカラーコードなどの何度も使用する値を変数を定義することで、変数名で何度も使用することができます。変数を定義するには、$変数名: 値;のように記述します。
【例】

$section-color: rgb(30,30,30);
section {
  background-color: $section-color;
}

複数のCSSファイルを1つにまとめることができる

Sassではパーシャルという機能を使用することで、複数のSassファイルを1つのCSSファイルとしてまとめることができます。

パーシャル

分割したSassファイルのことです。ファイルを分割することで、機能や内容ごとに管理ができるようになります。一定のルールでファイルを分割して開発することで変更・修正がしやすくなります。
パーシャルファイルを作成するには、ファイル名を(アンダースコア)から始めます。パーシャルファイルを読み込むには、@importファイル名と記述します。
【例】
_reset.scssと_header.scssを読み込むとします

@import "reset";  /* _reset.scssを読み込む */
@import "header"; /* _header.scssを読み込む */

同じ値を使い回すことができる

CSSでは、複数の要素に同じスタイルを適用させる場合、何度も同じスタイルを記述します。しかし、Sassでは変数を使うことによって、同じ値を使い回すことができます。
変数を定義するには、$変数名: 値;で記述します。
【例】

$mainYellowColor: #FFEC00;  /* #FFEC00という色をmainYellowColorという変数名で定義する */

また、mixinという機能を使用することで、同じスタイルをまとめることもできます。

mixin

まとまったスタイルを定義することができる機能です。
変数は値を定義するものですが、mixinはスタイルを定義するものです。
mixinを利用することで、何度も同じスタイルを記述する必要がなくなります。
mixinを定義するには、@mixin mixin名() {}のように記述します。
【例】.clearfix(レイアウトが崩れてしまった際に役立つ機能)を使用します。以下のように_clearfix.scssファイルに定義します。

_clearfix.scss
@mixin clearfix() {
  &:after {
    content: '';
    display: block;
    clear: both;
  }
}

&(アンパサンド)は、擬似要素であるafterが適用されているセレクタを指します。以下の例では、&は.menuに相当します。
つまり、擬似要素afterは、.menuに対して適用されているということです。
このmixinの呼び出しは@includeを使用して以下のように記述します。

_XXXX.scss
.menu {
  @include clearfix();
  ...

  .menu__list {
    float: left;
    ...
  }
}

XXXX.scssの記述は以下のSassコードと同じです。

_clearfix.scss
.menu {
  &:after {
    content: '';
    display: block;
    clear: both;
  }

  .menu__list {
    float: left;
    ...
  }
}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

外部キー制約のついたカラムを削除したい

外部キー制約の付いたカラムを削除するのにプチハマりしたのでまとめます

参考

こちらの記事でマイグレーションについてかなり詳しくまとめられています
マイグレーションの操作をするときは、こちらの記事で該当箇所をざっと読んでから公式ドキュメントに目を通すのが良さそう
https://pikawaka.com/rails/migration

APIdoc
https://apidock.com/rails/ActiveRecord/ConnectionAdapters/SchemaStatements/remove_index

例)ベストアンサー機能

  • questionモデル内に、ベストアンサーに選ばれた回答を保存するためのbestカラムがある
  • bestカラムには外部キーが設定してある(answersテーブル)

という状況

db/schema.rb
create_table "questions", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t|
  t.bigint "best"
  t.index ["best"], name: "fk_rails_dd35f91b0c"
end

add_foreign_key "questions", "answers", column: "best"

実践

まずはカラム削除用のマイグレーションファイルを作成する

$rails g migration RemoveBestFromQuestions

マイグレーションファイルが生成

db/migrate/xxxx_remove_best_from_questions.rb
class RemoveBestFromQuestions < ActiveRecord::Migration[5.1]
  def change
  end
end

こちらにカラムを削除するための記述を追加していく
外部キーとインデックスを貼っているので、カラムを削除する記述だけではエラーが発生してしまう
それらを削除する記述も必要っぽい

db/migrate/xxxx_remove_best_from_questions.rb
class RemoveBestFromQuestions < ActiveRecord::Migration[5.1]
  def change
    remove_foreign_key :questions, :answers
    remove_index :questions, :best
    remove_column :questions, :best, :bigint
  end
end

これでrails db:migrateを実行すればOK

最後に

間違っている部分があれば遠慮なくご指摘ください

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

[Rails] Mechanizeがファイルディスクリプタを大量に消費してしまう

内容はタイトル通り。
Railsにて、Mysql2のConnectionError出てる場合とか
ファイルディスクリプタを異常に使いまくってる場合はもしかしたら関係あるかも。

経緯

お客様に提供しているサービス(Rails,puma)にて

Mysql2::Error::ConnectionError

が多発してサービスが利用できなくなる障害が発生しました。

詳しくログを追ってみると他にも

Errno::EMFILE (Too many open files @ rb_sysopen ...(略)

のようなエラーも発生している様子。

さらに、、、

# ファイルディスクリプタ上限確認
ulimit -n
# pumaプロセスのファイルディスクリプタ確認
for i in $(ps aux | grep "[p]uma" | awk '{print $2}'); do sudo ls /proc/$i/fd | wc -l; done

上記コマンドでプロセスの開いてるファイル数を確認してみたら
どうやらファイルディスクリプタがいっぱいになっているようだった。

原因

実は、ファイルを開いているわけではなくてアプリケーションで使用していた Mechanize というgemにて
外部からデータを取得する際にコネクションを作成していた様子。
(スクレイピングとかするときに使われてるgemらしい。)

ファイルディスクリプタでは、ファイルだけでなくコネクションもカウントされるようで
大量のコネクションが削除されずに作成され続けたことで問題が発生した。
(Mysqlも多分コネクション関係?? 詳しい人コメントお願いします。)

対応

単純に、コネクションが開いたままになっていることが問題。
閉じてあげる必要がある。

Mechanizeのコネクションは以下のメソッドを呼び出すと閉じてくれるらしいので
使用中のコネクションの最後の処理が終わったあたりで呼び出してあげる。

Mechanize.shutdown

あとは、サーバー再起動などで既存コネクションを消してあげましょう。

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

AWS EC2 でgit pull origin master ができない時の対処法

はじめに

ローカル環境からgithubにpushをし、EC2からpullをしたときにエラーが出たのでメモを残します。

以下の記事を参考にして対処しました。
本番環境でpullしたらコンフリクト?解決法3パターン!【Please commit your changes or stash them before you merge】

エラーの内容

$ git pull origin master
From https://github.com/user-name/app-name
     * branch      master       ->   FETCH_HEAD 
Updating e05c05f..050505
error: Your local changes to the following files would be overwritten by merge: 
         Gemfile.lock
         config/initializers/devise.rb
Please commit your changes or stash them before you merge.
Aborting

私が実践した対処法

terminal
$ git fetch origin master

$ git reset --hard origin/master

これで無事にgithubの内容がEC2上に反映されました。

終わりに

今回は少し強引なやり方をしてpullをしましたが、実際の開発現場ではもう少し慎重にgitを扱う必要があるのだと思います。
今後も、gitについて深く勉強していきます。

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

rspec-railsで使うコマンドを羅列する

使うコマンドを雑多にメモる。

導入

Gemfile
group :development, :test do
  gem 'rspec-rails', '~> 3.6.0'
  gem 'factory_bot_rails'
end
spec/support/factory_bot.rb
RSpec.configure do |config|
  config.include FactoryBot::Syntax::Methods
end
$ rails g rspec:install
.....
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

gemとbundlerまとめ

まえおき

PJで運用保守にあたる中でgemのメモリ効率改善アップデートを取り入れたく


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

テーブルのカラムに変更を加えたいです 【 rails 】

マイグレーションファイルとは

マイグレーションファイルとは、テーブルのカラムを追加したり消したり型を変更したりする役割があるファイル

また、何か、カラムに変更を加える場合、必ずマイグレーションファイルを記述する必要がある

初めに

あーーnameカラム邪魔だなーと、 おもたら削除しましょう?

テーブルのカラム削除方法

image.png

①ターミナルに下記のコマンドを記述して実行する

rails generate migration テーブル名 カラム名:データ型

helloland@hellolandnoAir freemarket_sample_65a % rails generate migration users name                                    

②マイグレーション ファイルが作られるのでそれに変更の内容を記述して

今回は削除したいので、remove_colum です

image.png

③ターミナルでrails db:migrate を実行する

rails db:migraet

④カラムが完全に消滅しました

image.png

追記

もしエラーが出た場合、あせらずに エラー文を翻訳して解くいていきましょう

また、エラー内容は一行にまとめられているので、そこだけを見ることをお勧めします

image.png

大体マイグレーションファイルの記述ミスの場合が大半の為、エラー内容にしたがって作成したマイグレーション ファイルを修正することをお勧めします

image.png

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

Railsのtravel_toについてまとめた

はじめに

日付関係のテストをしていたときに、travel_toを使うといいと教えてもらいました。
今回は、travel_toメソッドについてまとめていきます。

travel_toとは

ActiveSupport :: Testing :: TimeHelpersのメソッドの一つです。

変更したい日時を渡すと、Time.nowDate.todayDateTime.nowで返される日時を変更することができます。

コード例

travel_to doendで囲まれた部分の中だけ、時間が変更されています。
コメント文のとおりに出力されました。

it 'puts date and time' do
  travel_to Time.zone.local(2020, 03, 16) do
    pp Date.today   # -> Mon, 16 Mar 2020
    pp Time.now     # -> 2020-03-15 15:00:00 +0000
    pp DateTime.now # -> Mon, 16 Mar 2020 00:00:00 +0900
  end
end

SyntaxError

Time.zone.local08または09を渡すと、Invalid octal digitでエラーとなります。
そういうときは、下の例のように0をつけずに渡してあげればOKです。

travel_to Time.zone.local(2020, 8, 16) do

end

参考

ActiveSupport::Testing::TimeHelpers

ActiveSupport :: Testing :: TimeHelpersには他にもメソッドがあるので参考にしてみてください。

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

Railsの慣習まとめ

Railsの慣習まとめ

  1. Controllerの名前は複数形にする
    resources, resourceを使うときでも複数形にすることが推奨されています¹

  2. Modelの名前は名詞にする

    • 単数のクラスが作成される
    • table名は複数形のスネークケース
    • factoryは複数形のスネークケース
  3. Polomorphicの関連を作成する場合、columnには -able_type, -able_idにする²

  4. concerning は-ing系³

  5. concernは-ableになります

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

Railsポートフォリオ環境構築備忘メモ(参考にした記事とか)

※こちらは活動報告を兼ねた備忘メモです。参考にした記事はURLを記載していますが、本記事自体にはまとまったTIPS的な情報はないので開いてしまった方はお手数ですがスルーしてください。

Railsポートフォリオ環境構築備忘メモ

繁忙期深夜と休日を使い悶々としながら行っていた環境構築が一旦完了した。
環境構築で行った手順を忘れてしまいそうのでメモしておく。

前提条件(バージョン)
Ruby 2.7.0
Rails 5.2.4.1
MySQL 5.7
をDocker、docker-composeを使用して環境構築する。

参考にした記事:
丁寧すぎるDocker-composeによるrails5 + MySQL on Dockerの環境構築(Docker for Mac)
https://qiita.com/azul915/items/5b7063cbc80192343fc0
本当に丁寧。こちらを基本にしてRails.new前の各種ファイルを作成。バージョンと一部内容は変更した。
(自分なりに理解してやりたかったのだが、自分のにわか変更によりハマりまくった…)

仁科俊晴氏ブログの『ローカル開発環境の構築不要!Dockerを利用したRailsアプリ起動手順』
https://nishinatoshiharu.com/docker-rails-server/
こちらも参考にした。かなり分かりやすく入門Dokerや公式ガイドと合わせて理解の助けになったが、複数記事に渡っていてこちらのみを参考にしつつ構築したらハマった。(多分自分のコードが誤っているのだろう)

他の方があげているポートフォリオ

その他気をつけること:
・ymlのインデント周りでエラーを吐きやすい。
・bundle(gem)のバージョン周りでエラーが発生しがちのようだが適当なトラブルシューティングに辿り着けないとハマる。(対策を考えておく。)
・Dockerコンテナやイメージが散らかるので定期的に掃除しておく。

ハマりまくるのでブランチを分けて作業すればいいことに途中で気付く…
そして深夜にようやく「Yay! You're on Rails!」画面に…感動。

スクリーンショット 2020-03-14 1.37.35.png

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

Ruby, Rails たまに使うけどすぐ忘れるやつ

RailsとかRubyの過去に学んだものを適当に残しておく(最近はRailsもRubyも触ってない・・)
思い出したら随時追加する。

rakeタスクをrails consoleから実行する

require 'rake'
Rails.application.load_tasks
Rake::Task['hoge:huga'].execute
# 引数つけて実行
Rake::Task["hoge:huga"].execute({ hogege: 'hugaga' })

bundle でバージョン指定してインストール

# bundle installするときはGemfile.lockのバージョンを確認してから実行
bundle  _1.16.1_ install

rakeタスク内のメソッドはObjectクラス直下に作られちゃう

https://blog.freedom-man.com/rake-definemethod-namespace

namespace配下にメソッド書いていると思っていてもObjectクラス以下に作られるのでバグの原因になるかもね

SQLをrails consoleから実行

sql="SELECT * from hoge);"
result=ActiveRecord::Base.connection.select_all(sql).to_hash

rspecの書き方で参考になるページ

http://www.betterspecs.org/jp/

ruby引数処理

わかりやすい記事
キーワード引数をhashとして受け取る方法とか
https://qiita.com/metheglin/items/306e81c95f8a5cdea296

privateメソッドをrails consoleから呼び出す

# User.find_by(id: 1)は引数
# Hugaはクラス, hoge_private_methodはHugaクラス内のプライベートメソッド
Huga.send(:hoge_private_method, User.find_by(id: 1) )

CSV書き出し

使い捨てコード書くときによく使う

CSV.open('/tmp/hoge.csv','wb') do |csv|
   csv << [1,2]
end

テキスト読み込み

File.foreach("tmp/hoge.txt"){|f| s << f.chomp.to_i}

rakeタスクの確認

bundle exec rake -vT

rails consoleでexplainを実行

https://railsguides.jp/active_record_querying.html#explain%E3%82%92%E5%AE%9F%E8%A1%8C%E3%81%99%E3%82%8B

User.where(id: 1).joins(:articles).explain

ActiveSupportのString拡張(活用形)まとめ

https://qiita.com/hana-da/items/ec9ac3e1c8803f5fa1fc

"Invoice".tableize     # => "invoices"

メール送信

手元のメール送信確認はmailcacherを使ったことがある
https://qiita.com/pocari/items/de0436c39ffc65647cf0

ActionMailer::Base.mail(to: "to@example.com", from: "from@example.jp", subject: "題名", body: "本文").deliver_now

メソッドの定義場所を探す

https://docs.ruby-lang.org/ja/latest/method/Method/i/source_location.html

Hoge.method(:huga).source_location

sqlファイルをrails dbに食わせる

bundle exec rails db < my_db.sql

日付と時刻を扱う

https://qiita.com/prgseek/items/c0fc2ffc8e1736348486

t = Time.parse("2017/04/25 19:23:55"); p t  # 2017-04-25 19:23:55 +0900

クエリ高速化

わかりやすい, Rails6はあまり知らない
https://texta.pixta.jp/entry/2016/02/10/180244
https://qiita.com/leon-joel/items/f26556c9e56833983856

rails consoleの再読み込み

reload!

find_each

わかりやすかった
https://blog.toshimaru.net/rails-find_each/#order%E4%BB%98%E3%81%8D-find_each

スクリプト実行

Rails機能を使いつつ単独のスクリプトを実行する。

bundle exec rails runner hoge.rb 'huga'

pry

わかりやすい
https://qiita.com/k0kubun/items/b118e9ccaef8707c4d9f
https://www.slideshare.net/cuzic/pry-repl

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