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

Ruby日付クラスで暦を操作する(生成/切り替え)

前説

Rubyの 日付クラス の暦日操作をまとめます。
ユリウス暦/グレゴリオ暦を念頭に、暦日計算に必要な日付インスタンスの生成と、暦の切り替えを行います。

環境

念のためバージョンを記載します。

% ruby --version
ruby 2.6.2p47 (2019-03-13 revision 67232) [x86_64-darwin16]

ただし、これから触れるDateクラス/メソッドは 少なくとも Ruby1.8.7 から存在しており、バージョン非依存の挙動と考えられます。
また、以下の例文は全て irb で示します。

エラー

特定の過去日を指定して日付オブジェクトを生成した場合、以下のようなエラーが発生します。

% irb
irb(main):001:0> require 'date'
=> true
irb(main):002:0> date = Date.new(1582, 10, 4)
=> #<Date: 1582-10-04 ((2299160j,0s,0n),+0s,2299161j)>
irb(main):003:0> date = Date.new(1582, 10, 5)
Traceback (most recent call last):
        6: from /Users/pldb/.rbenv/versions/2.6.2/bin/irb:23:in `<main>'
        5: from /Users/pldb/.rbenv/versions/2.6.2/bin/irb:23:in `load'
        4: from /Users/pldb/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/irb-1.0.0/exe/irb:11:in `<top (required)>'
        3: from (irb):3
        2: from (irb):3:in `new'
        1: from (irb):3:in `initialize'
ArgumentError (invalid date)
irb(main):004:0> date = Date.new(1582, 10, 15)
=> #<Date: 1582-10-15 ((2299161j,0s,0n),+0s,2299161j)>

1582-10-05 〜 1582-10-14 は ArgumentError (invalid date) です。

エラー原因

この日付は現実に存在しない日付です。ゆえに invalid date ですが、詳しくは以下の通りです。

まず、Ruby の 日付実装 のコメントを引用します。

* A Date object can be created with an optional argument,
* the day of calendar reform as a Julian day number, which
* should be 2298874 to 2426355 or negative/positive infinity.
* The default value is +Date::ITALY+ (2299161=1582-10-15).
* See also sample/cal.rb.
*
*     $ ruby sample/cal.rb -c it 10 1582
*         October 1582
*      S  M Tu  W Th  F  S
*         1  2  3  4 15 16
*     17 18 19 20 21 22 23
*     24 25 26 27 28 29 30
*     31

1582-10-04 まではユリウス暦、その次の日の 1582-10-15 はグレゴリオ暦です。
実際に判定してみますが、1582-10-04に対しては julian? は true で、翌日以降は false (つまり gregorian? がtrue)です。

 % irb
irb(main):001:0> require 'date'
=> true
irb(main):002:0> 
irb(main):003:0> date = Date.new(1582, 10, 4)
=> #<Date: 1582-10-04 ((2299160j,0s,0n),+0s,2299161j)>
irb(main):004:0> date.julian?
=> true
irb(main):005:0> date = Date.new(1582, 10, 15)
=> #<Date: 1582-10-15 ((2299161j,0s,0n),+0s,2299161j)>
irb(main):006:0> date.julian?
=> false
irb(main):007:0> date.gregorian?
=> true

ユリウス暦による過小に進んだズレをグレゴリオ暦で正した結果、上記のように日付がスキップされています。スキップ自体はインクリメントすることでも確かめられます。

 % irb
irb(main):001:0> require 'date'
=> true
irb(main):002:0> date = Date.new(1582, 10, 4)
=> #<Date: 1582-10-04 ((2299160j,0s,0n),+0s,2299161j)>
irb(main):003:0> date += 1
=> #<Date: 1582-10-15 ((2299161j,0s,0n),+0s,2299161j)>

歴史上の背景については wiki など別記事をご確認ください。
これが invalid date の理由です。ここからさらに理解を進めることにします。

引数 start

これまでの new は末尾の引数を省略しています。省略せずに書いた場合です。

irb(main):008:0> date = Date.new(1582, 10, 15, Date::ITALY)
=> #<Date: 1582-10-15 ((2299161j,0s,0n),+0s,2299161j)>

Date::ITALY は既定値です。 末尾の引数を省略された場合にデフォルトとして設定されます。
この設定可能な引数については ドキュメント に記載されています。

それぞれの値は先ほど引用したコメント 2298874 to 2426355 or negative/positive infinity に該当します。
これらを末尾の引数に設定できます。

new

[PARAM] start:
グレゴリオ暦をつかい始めた日をあらわすユリウス日

「つかい始めた日」というのがポイントで、 ITALYENGLAND はこの説明で理解しやすい定数値です。

 % irb
irb(main):001:0> require 'date'
=> true
irb(main):002:0> Date::ITALY
=> 2299161
irb(main):003:0> Date.jd(Date::ITALY)
=> #<Date: 1582-10-15 ((2299161j,0s,0n),+0s,2299161j)>
irb(main):004:0> 
irb(main):005:0> Date::ENGLAND
=> 2361222
irb(main):006:0> Date.jd(Date::ENGLAND)
=> #<Date: 1752-09-14 ((2361222j,0s,0n),+0s,2299161j)>
irb(main):007:0> 

jd にユリウス日を与えると対応するDateオブジェクトを返します。
日付はグレゴリオ暦の開始日です。

:last_quarter_moon_with_face:上記定数以外の値として、 should be 2298874 to 2426355 (1581-12-22 〜 1931-01-13) とありますが、範囲外の値を渡してもエラーにはなりませんでした。歴史的な文脈を無視すれば、開始日は自由に設定できるのかもしれません

まさに start と言うべきですが、 GREGORIANJULIAN についてはユリウス日ではありません。

 % irb
irb(main):001:0> require 'date'
=> true
irb(main):002:0> Date::JULIAN
=> Infinity
irb(main):003:0> Date::GREGORIAN
=> -Infinity

negative/positive infinity です。
Date::JULIAN (Infinity) は「改暦日は無限の未来にあると考えられます」とある通り、グレゴリオ暦を永遠に開始しません。
Date::GREGORIAN (-Infinity) は「改暦日は無限の過去にあると考えられます」とある通り、始まりからすでにグレゴリオ暦です。

個人的には start よりも暦の type とでも捉えた方が理解しやすいと感じるところです。

次にこれらの使い方を考えます。

使用方法

現実的には Date::ITALY で十分ですが、研究分野によっては暦の使い分けを避けたいケース、また、暦変換を行いたいケースがあると思われます。
そのようなケースに対応する例文を以下に示します。

生成

基本的にDateインスタンス生成するメソッドでは、この start を末尾に設定できるようです。
ユリウス暦日による日付インスタンス生成を例とします。

new

 % irb
irb(main):001:0> require 'date'
=> true
irb(main):002:0> date = Date.new(2020, 1, 1, Date::JULIAN)
=> #<Date: 2020-01-01 ((2458863j,0s,0n),+0s,Infj)>
irb(main):003:0> date.julian?
=> true

jd

 % irb
irb(main):001:0> require 'date'
=> true
irb(main):002:0> date = Date.jd(Date.new(2020, 1, 1, Date::JULIAN).jd, Date::JULIAN)
=> #<Date: 2020-01-01 ((2458863j,0s,0n),+0s,Infj)>
irb(main):003:0> date.julian?
=> true

前述のことではありますが、第一引数には引数なしの jd の戻り値(ユリウス日)を与えています

parse

 % irb
irb(main):001:0> require 'date'
=> true
irb(main):002:0> date = Date.parse('2020-1-1', Date::JULIAN)
=> #<Date: 2020-01-01 ((2458850j,0s,0n),+0s,2299161j)>
irb(main):003:0> date.julian?
=> false

その他

以下のメソッドでも同様です。末尾に start を設定できます。

切り替え

次に暦の切り替えです。

new_start

例文ではユリウス暦として日付インスタンスを生成、それをグレゴリオ暦に換算しています。

 % irb
irb(main):001:0> require 'date'
=> true
irb(main):002:0> date = Date.new(2020, 1, 1, Date::JULIAN)
=> #<Date: 2020-01-01 ((2458863j,0s,0n),+0s,Infj)>
irb(main):003:0> date.julian?
=> true
irb(main):004:0> date = date.new_start(Date::GREGORIAN)
=> #<Date: 2020-01-14 ((2458863j,0s,0n),+0s,-Infj)>
irb(main):005:0> date.julian?
=> false

julian

リンク先の通り、 new_start(Date::JULIAN) と等価です。

 % irb
irb(main):001:0> require 'date'
=> true
irb(main):002:0> date = Date.new(2020, 1, 1, Date::GREGORIAN)
=> #<Date: 2020-01-01 ((2458850j,0s,0n),+0s,-Infj)>
irb(main):003:0> date.julian?
=> false
irb(main):004:0> date = date.julian
=> #<Date: 2019-12-19 ((2458850j,0s,0n),+0s,Infj)>
irb(main):005:0> date.julian?
=> true

gregorian

リンク先の通り、 new_start(Date::GREGORIAN) と等価です。

 % irb
irb(main):001:0> require 'date'
=> true
irb(main):002:0> date = Date.new(2020, 1, 1, Date::JULIAN)
=> #<Date: 2020-01-01 ((2458863j,0s,0n),+0s,Infj)>
irb(main):003:0> date.julian?
=> true
irb(main):004:0> date = date.gregorian
=> #<Date: 2020-01-14 ((2458863j,0s,0n),+0s,-Infj)>
irb(main):005:0> date.julian?
=> false

まとめ

  • Dateインスタンスはユリウス暦/グレゴリオ暦を指定できる
  • デフォルトでは Date::ITALY1582-10-15 がグレゴリオ暦の開始日で、それまではユリウス暦となる
  • いつからグレゴリオ暦に切り替えられるかは、ユリウス日で指定できる
  • 日付インスタンスを生成するメソッドには、このグレゴリオ暦の開始日を末尾の引数に指定できる
  • 一度指定した開始日は再設定できる(ユリウス暦 <=> グレゴリオ暦 を換算できる)

参考リンク

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

Ruby 超基礎をようやくわかった私のメモ書き

 ハッシュの襲来

ハッシュってなんやねん。ハッシュドポテトか?と、さらに勉強しても意味わからんし、ラディッツ並の絶望が押し寄せました。
悟飯の様にキレてやろうかと思いました。「お父さんをいじめるなー!!」って、そんで「あっ!悟飯と仲良くなれそう!」って唐突に思ったんですが、ビーデルというスペックの高い奥さんをもらい、さらには頭の良さと運動神経が圧倒的に違うので仲良くはなれませんね。嫉妬しかないです。

先生に見られたら怒られそうなのでハッシュにいきます。
ざっくりですが私のイメージは、
『たくさんコード書くの超めんどくさいから空箱の中にそれぞれ名前のつけたキーと値をつけて保存して、必要な時に取り出しちゃおうぜ!』ってことだと思います。
イメージはポイポイカプセルですね。
書き方なんですが、
post = {} でハッシュの生成で {}これが保存先、つまりポイポイカプセル
その次に何を入れるかを決めます
例エヴァ
post[:name] = "仙豆" postの部分がハッシュ名、ちなみ可読性のある名前をつけましょう。基本的には自由です。そしてnameがキーです。仙豆が値です。ちなみに:はルールという認識です [:name]と書かないとハッシュだと思ってくれません。

これは仙豆です。と出力したければ
puts "これは#{[:name]です}
とすればいいわけです。 

ちなみに自分の中のイメージで書いてるんで勘違いしてたら魔貫光殺砲で貫いてください。。よろしくお願いします。

ハッシュはまだまだあるんですが、この土日で基礎を叩き込まないと本当にヤバイのでこの辺で終わります。初記事で、しかも時間がない中書いてるんできっと闇歴史になるとおもます。
なのでしばらく精神と時の部屋に入ります。戦闘力が5の私がどうやって神の神殿に行くのかって?筋斗雲に乗っていきます。資本主義万歳です。

来月あたりにはスーパーサイヤ人状態がデフォルトになってるか、ヤムチャに転生してるかのどっちかです。狼牙風風拳よりかめはめ波の方が好きなので打てる様に頑張ります。プログラミングに元気玉をぶちかましたいです。

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

【Rails】Active Jobについてゼロから理解する

概要

RailsのActive Jobについてゼロから理解する為に調べたことをまとめます。

  • 本格的なアプリでは往々にして時間のかかる処理が発生する
    • 大量のデータ集計、外部サービスとの連携、メール送信など
  • そしてこれらの処理はリアルタイムに完了してなくても良い場合もある
  • アプリから実行すべき処理(ジョブ)待ち行列(キュー)に登録して後から実行(非同期実行)することで、アプリのレスポンスを改善できる!

  • Active Jobとは、そのようなジョブの管理から実行までの管理する為のモジュール

    • Active Jobそのものは、基本的に、ジョブ操作の為のインタフェース(メソッド名などの決まりごと)を提供しているに過ぎない
    • 実際にジョブを実行するのはジョブ管理ライブラリの役割(Delayed JobSidekiq
  • アダプターを切り替えれば、アプリケーションをほとんど改修することなくバックエンドのジョブ管理ライブラリを自由に切り替えられる

やってみた

delayed_jobを利用する

delayed_jobをインストールする

  • Gemfileに追記
gem 'delayed_job_active_record'
  • bundle install
$ bundle install
  • delayed_jobび必要なファイルを生成
$ bundle exec rails generate delayed_job:active_record
      create  bin/delayed_job
       chmod  bin/delayed_job
      create  db/migrate/20200121063912_create_delayed_jobs.rb
  • マイグレを打ってdelayed_jobsテーブルを追加
    • 非同期で実行する処理を一時的に管理するテーブル
$ bundle exec rails db:migrate
== 20200121063912 CreateDelayedJobs: migrating ================================
-- create_table(:delayed_jobs, {:force=>true})
   -> 0.0292s
-- add_index(:delayed_jobs, [:priority, :run_at], {:name=>"delayed_jobs_priority"})
   -> 0.0226s
== 20200121063912 CreateDelayedJobs: migrated (0.0519s) =======================
  • Active Jobでdelayed_jobを有効にする(config/application.yaml)
    # using delayed_job
    config.active_job.queue_adapter = :delayed_jo

ジョブを動かしてみる

  • ジョブを作成する
$ bundle exec rails g job Sleep
      create  app/jobs/sleep_job.rb
  • 生成されたジョブを編集する
    • performメソッドがジョブの実処理を表す
    • メソッド配下に非同期実行する処理を記述する def perform() puts("start sleep") sleep 10 end
  • ジョブを登録してみる(rails consoleから)
    • ジョブを登録するにはクラス名.perform_later(...)とする
    • これでジョブをキューに登録しなさい、という意味になる
    • テストでジョブを即座に実行したい場合はperform_now()を利用する
irb(main):002:0> SleepJob.perform_later()
   (0.4ms)  SET NAMES utf8mb4,  @@SESSION.sql_mode = CONCAT(CONCAT(@@sql_mode, ',STRICT_ALL_TABLES'), ',NO_AUTO_VALUE_ON_ZERO'),  @@SESSION.sql_auto_is_null = 0, @@SESSION.wait_timeout = 2147483
   (0.2ms)  BEGIN
  Delayed::Backend::ActiveRecord::Job Create (0.9ms)  INSERT INTO `delayed_jobs` (`handler`, `run_at`, `queue`, `created_at`, `updated_at`) VALUES ('--- !ruby/object:ActiveJob::QueueAdapters::DelayedJobAdapter::JobWrapper\njob_data:\n  job_class: SleepJob\n  job_id: 6643be62-59fd-4ea3-81a1-c14fcd13aafb\n  provider_job_id: \n  queue_name: default\n  priority: \n  arguments: []\n  executions: 0\n  exception_executions: {}\n  locale: en\n  timezone: UTC\n  enqueued_at: \'2020-01-21T06:53:15Z\'\n', '2020-01-21 06:53:15', 'default', '2020-01-21 06:53:15.343196', '2020-01-21 06:53:15.343196')
   (0.4ms)  COMMIT
Enqueued SleepJob (Job ID: 6643be62-59fd-4ea3-81a1-c14fcd13aafb) to DelayedJob(default)
=> #<SleepJob:0x00007f9cf4c456d8 @arguments=[], @job_id="6643be62-59fd-4ea3-81a1-c14fcd13aafb", @queue_name="default", @priority=nil, @executions=0, @exception_executions={}, @provider_job_id=1>
  • delayed_jobを起動してキューに登録されたジョブを実行する
$ bundle exec bin/delayed_job start

ジョブ実行のカスタマイズ

delayed_jobの動作パラメータ

  • config/initializer配下にdelayed_job.rbのような初期化ファイルを作成
    • delay_jobs:ジョブの遅延実行を有効化するか
    • max_attemps:最大リトライ回数
    • max_run_time:最大実行回数
    • destroy_failed_jobs:失敗したジョブを破棄するか
    • read_ahead:一度に読み込むジョブの個数
    • sleep_delay:実行ジョブがない場合のsleep期間

キューの名前を設定する

  • キューを分けることで、特定のキューだけを優先して実行するなどの仕分けが可能になる
    • queue_asメソッドを利用する
    • queue_name_prefixパラメータでprefixを宣言する
    • setメソッドを利用する
irb(main):006:0> SleepJob.set(queue: :sleep).perform_later()

コールバック

ジョブを登録/実行するタイミングで実行されるメソッド、またはその仕組のこと

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

vscodeで"Ruby Solargraph"を使用可能にするまで

手順(Macbookを使用)

  1. rbenvをインストールする(gemインストールを有効にするため、PATHをrbenvで統一する)

    brew install rbenv ruby-build
    
  2. rbenvを使用して最新安定バージョンのrubyをインストールする(opensslのインストールに時間がかかるため、10分程度)

    rbenv install -l
    rbenv install x.x.x
    
  3. インストールされたことを確認する

    rbenv versions
    
  4. インストールしたrubyバージョンに切り替える

    rbenv global x.x.x
    
  5. rbenvの環境変数をzshrcに設定する

    vi ~/.zshrc
    # rbenvへのPATH
    [[ -d ~/.rbenv  ]] && \
    export PATH=${HOME}/.rbenv/bin:${PATH} && \
    eval "$(rbenv init -)"
    
    source ~/.zshrc
    
  6. rubyのPATHを確認する

    which ruby
    /Users/[ユーザ名]/.rbenv/shims/ruby
    
  7. gemのPATHを確認する

    which gem
    /Users/[ユーザ名]/.rbenv/shims/gem
    
  8. Solargraphをインストールする

    gem install solargraph
    
  9. rubocopをインストールする

    gem install rubocop
    
  10. Solargraphが使えることを確認する

    solargraph help          
    Commands:
    solargraph --version, -v            # Print the ve...
    solargraph available-cores          # List availab...
    solargraph bundle                   # Generate doc...
    solargraph clear                    # Delete the c...
    solargraph config [DIRECTORY]       # Create or ov...
    solargraph download-core [VERSION]  # Download cor...
    solargraph help [COMMAND]           # Describe ava...
    solargraph list-cores               # List the loc...
    solargraph rdoc GEM [VERSION]       # Use RDoc to ...
    solargraph reporters                # Get a list o...
    solargraph scan                     # Test the wor...
    solargraph socket                   # Run a Solarg...
    solargraph stdio                    # Run a Solarg...
    solargraph typecheck [FILE]         # Run the type...
    solargraph uncache GEM [...GEM]     # Delete cache...
    
  11. vscodeでRuby Solargraphをインストールする

  12. setting.jsonに以下を記入する

    "solargraph.commandPath": "solargraphのPATH"
    "ruby.intellisense": "rubyLocate"
    
  13. 左下の歯車 -> 設定をクリックし、設定の検索に以下を入力する

    solargraph
    
  14. Solargraph:Command PathにsolargraphのPATHが設定されていることを確認する

  15. Solargraph: Use Bundlerにチェックがはいっていないことを確認する

  16. vscodeを再起動し、右下にSolargraphに関するメッセージが表示されないことを確認する

以上

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

【Rails】simple_calendarを日本語表記にする方法

Railsでsample_calendarを導入したのですが、日本語表記にするのに少し手間取りました。

しかし、無事解決することができたので共有したいと思います。

Railsのバージョン 5.2.3
Rubyのバージョン 2.5.1

手順1

config/application.rb
config.i18n.default_locale = :ja

まずはこいつを追加します。

手順2

config/locales/ja.yml
ja:
  date:
    abbr_day_names:
      - 
      - 
      - 
      - 
      - 
      - 
      - 
    abbr_month_names:
      -
      - 1月
      - 2月
      - 3月
      - 4月
      - 5月
      - 6月
      - 7月
      - 8月
      - 9月
      - 10月
      - 11月
      - 12月
    day_names:
      - 日曜日
      - 月曜日
      - 火曜日
      - 水曜日
      - 木曜日
      - 金曜日
      - 土曜日
    formats:
      default: "%Y/%m/%d"
      long: "%Y年%m月%d日(%a)"
      short: "%m/%d"
    month_names:
      -
      - 1月
      - 2月
      - 3月
      - 4月
      - 5月
      - 6月
      - 7月
      - 8月
      - 9月
      - 10月
      - 11月
      - 12月

  time:
    am: 午前
    formats:
      default: "%Y年%m月%d日(%a) %H時%M分%S秒 %z"
      long: "%Y/%m/%d %H:%M"
      short: "%m/%d %H:%M"
    pm: 午後

次に上記記述を追加してください。ネストには気をつけてくださいね。

すると

スクリーンショット 2020-02-15 20.15.27.png

完璧ですね。

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

Ubuntuにてrails6.0の環境構築(備忘録)

Ruby on Rails 6.0を、以下記事を参考にさせていただきながら、環境構築をしました。(厳密にいうとまだできてませんが)
備忘録として残す&誰かのお役に立てれば&なぜ最後だけできないのか誰か教えてほしい、ということで書きます。

参考記事はこちら

やったこと

上記記事どおりに環境構築。

git clone https://github.com/sstephenson/rbenv.git ~/.rbenv

上記実施時に

fatal: destination path 'パス名' already exists and is not an empty directory.

って出て困惑しましたが、すでにあるから置けないよってことらしいので気にせず実施。

未解決の部分

すべて実施し、よっしゃあ最後だ!終わった!と思って起動しようとしたところ、

:~/dev/sample$ rails s -b 0.0.0.0
/パス名/versions/2.6.2/lib/ruby/gems/2.6.0/gems/railties-6.0.2.1/lib/rails/app_loader.rb:53: warning: Insecure world writable dir /パス名/versions/2.6.2 in PATH, mode 040777
=> Booting Puma
=> Rails 6.0.2.1 application starting in development
=> Run `rails server --help` for more startup options
Puma starting in single mode...
* Version 3.12.2 (ruby 2.6.2-p47), codename: Llamas in Pajamas
* Min threads: 5, max threads: 5
* Environment: development
* Listening on tcp://0.0.0.0:3000
Use Ctrl-C to stop

との表示。やったか!?

無題.png

はい。ポートが開いてないのかと思ってufwのコマンドも試してみたが弾かれ。iptablesは更新したんだけども。。。

:~/dev/sample$ sudo ufw allow 3000/tcp
WARN: initcaps
[Errno 2] iptables v1.6.1: can't initialize iptables table `filter': Table does not exist (do you need to insmod?)
Perhaps iptables or your kernel needs to be upgraded.

初心者で本当にわからないのでわかる人いたらご教示願います。。。

2020/02/06 追記

いけました。rails sで起動して、localhostに繋げばいいだけやった。あほすぎて恥ずかしい。

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

Ruby / Rails資料

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

【Rails】リロードしないとJavaScriptが動かない!【簡単に解決】

はじめに

以前jQueryを使ってタブメニューの切り替えを実装したときに、
ビューを開いた初回は非同期で切り替わるのに、
別のページに移動したり
「戻る」ボタンを押したあと再びタブメニュー画面に戻ると、、、、

動かない、、、!なぜだ、、!

なんて経験をして1日無駄にしたことがあります。
jQueryやビュー画面のコードは間違ってないはず!なぜ!って人向けの記事です。

解決方法①

link_toごとにturbolinksとやらを無効にすればOKです。簡単です。

<%= link_to "ホーム", root_path, data: {"turbolinks" => false} %>

data: {“turbolinks" => false}は遷移先ページのみturbolinksを切ることが出来ます。

turbolinksとは、ページ遷移をAjaxに置き換え、JavaScriptCSSのパース(解析・変換)を省略することで高速化するgemで、Rails4からはデフォルトで使用されています。↓

gem 'turbolinks', '~> 5'

解決方法②

jsファイルに"turbolinks:load"を記述すればOKです。簡単です。

document.addEventListener("turbolinks:load", function() {
  // ...
})

まとめ

turbolinksを無効化する方法として、gemファイルから直接削除する方法もあるようですが、
元々turbolinksはページの読み込みを高速化するgemです。

ボタンを押すたびに画面が初期化され、
一旦真っさらになった後、再度jsやらcssを読み直す。。。待ってられません。

その辺の処理をTurbolinks5が全部やってくれているんです。

なるべく
①個別のページ(link_toごと)に無効にするか、
②jsファイルにコードを加えるだけにしましょう。

参考
https://qiita.com/suzy1031/items/d3a8e96fe4d31111d22e

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

クラスとインスタンスについて

クラスは属性、メソッドを定義する場所
インスタンスはクラスに基づいた実態を作成する

流れ
クラスの生成

class クラス名(頭文字は大文字)
end

クラスメソッドを定義する
定義

class クラス名(頭文字は大文字)
 def self.メソッド名
 end
end

呼び出し

クラス名(頭文字は大文字).メソッド名(引数)

インスタンスの生成 newメソッドをつかう

変数 = クラス名(頭文字は大文字).new

インスタンスメソッドの生成
※インスタンス定義のクラス内で生成する必要

def メソッド名
end

呼び出し
インスタンス.メソッド名

クラス変数
クラス内であればどこでも使用できる変数。クラスメソッド、インスタンスメソッドどちらでも使用できる
定義
クラスの定義内で定義する

class クラス名
    @@クラス変数
  end

インスタンス変数
インスタンス内で使用できる変数。インスタンスメソッドの中でのインスタンス変数(@が付いた変数)の値は、そのインスタンスメソッドを利用したインスタンスが持つインスタンス変数の値になる
定義

def インスタンス名
  @インスタンス変数 = gets.chomp
end

クラス変数はクラスで共通の変数となる
インスタンス変数はインスタンス内で共通の変数となる

initializeメソッド
インスタンスメソッドが生成されたと同時に実行されるインスタンスメソッド

def initialize
  変数の定義など
end
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

新規Railsプロジェクト作成手順(Rails 6)

目的

Ruby on Rails 6,MySQL,RSpecを用いた環境を構築し,サーバーを起動してエラーなく最初のページが表示されるようにする.

開発環境

MacOS High Sierra 10.13.6
Ruby 2.7.0
Ruby on Rails 6.0.2.1

前提

  1. rbenv,Rubyのインストール
  2. MySQLのダウンロード
  3. rbenvへのbundleインストール(下記)
$ rbenv exec gem install bundler
$ rbenv rehash

手順

  1. プロジェクトを作成したいディレクトリに移動
  2. Railsインストール
  3. 上記のRailsを元にrails new
  4. Railsプロジェクトのセットアップ

1. プロジェクトを作成したいディレクトリに移動

$ mkdir projects
$ cd projects

2. Railsインストール

  1. Gemfile作成
  2. Gemfile書き換え(もちろんvimをはじめとしたエディタで編集してもおk)
  3. Railsインストール
$ bundle init
$ cat << EOS > Gemfile
source "http://rubygems.org"
gem "rails", "6.0.2.1"
EOS
$ bundle install
#指定したバージョンのRailsがインストールされていることを確認
$ bundle list

bundle install--path vendor/bundleをつけるかどうか論議が発生しますが,基本的には付けなくて大丈夫とのこと.
またBundler2.1においては--pathオプションをつけると警告が出ます.それを回避するためには以下のようにしてbundlerの設定を変更する方がベターですが,この設定を行わなくても基本的にはおkです.

$ bundle config set --local path 'vendor/bundle'

ちなみに自分は以前pathを指定しておりその名残でvendor/bundleにbundle_pathが通っているため,以下ではbundle execを頭につけてrailsコマンドを実行しますが,そうでない方は単純にrailsコマンドを入力していただければいいかと.

3. 上記のRailsを元にrails new

# alias設定
$ alias be='bundle exec'
$ be rails new app_name -B -d mysql --skip-test

rails newの際にオプションをつけることでMySQLおよびRSpecのためのプロジェクトであることを示しています.
-B--skip-bundleと同義であり,先のbundle installにおいてvendor/bundleへのパス指定を行わなかった場合は必要ないと思われます.

4. Railsプロジェクトのセットアップ

残念ながらこれだとRails6で標準のwebpackerがインストールされていないため,サーバーを起動してもエラーが起こります.なのでこれを解決するために以下.

$ brew install yarn
$ be rails webpacker:install

yarnは一度インストールしておけば問題ないですが,webpackerは(be) rails newしてプロジェクトを新規作成するたびにする必要があります.

次にRSpecをgemに追加.もちろんプロジェクト内のGemfileに対して.

group :development, :test do
  (省略)
  gem 'rspec-rails'
end

毎度おなじみbundle install.

$ bundle install

bundle installが作成したプロジェクト内のvendor/bundleに対して行われた場合には,そのディレクトリをgitで扱わないようにするために以下を追加します.

$ echo '/vendor/bundle' >> .gitignore

そして最後にデータベースを生成し,サーバーを起動します.

$ be rails db:create
$ be rails s

これでエラーなくサーバーが起動されるはず.

※ ローカルにRailsをインストールした場合

2でローカルのvendor/bundleにbundle installした場合,Gemfileやvendor/bundleを消すのがいいかと.
新しいプロジェクト作成するたびに溜まっていってしまうので.

$ rm -f Gemfile
$ rm -f Gemfile.lock
$ rm -rf .bundle
$ rm -rf vendor/bundle

最後に

ようやく環境が整ったのでゴリゴリポートフォリオ作っていきたいと思います.

追記

Rails 6で環境整えたはいいものの,やはりまだ情報が出回ってないということで初心者のうちはRails5でポートフォリオ作ることにします.
現場の環境としてもまだまだ5系が多いというお話もお聞きしますし.

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

Ubuntu で最新版の Ruby をインストール

今さらながら、自分が分かりやすいように最新版の Ruby をインストールする方法をまとめたいと思います。
Windows Subsystem for Linux の Ubuntu 16.04 上で動作確認しました。

1. 既に apt でインストールされている場合は一度アンインストール

本記事では apt 以外の手段でインストールするため、既に apt でインストールされている場合は一度アンインストールします。

アンインストール
sudo apt purge ruby rbenv ruby-build
rm -rf ~/.rbenv

2. インストール

Ruby のインストールは色々と罠がありますが、rbenvruby-buildgit clone して rbenv install するのが一番良さそうです (apt は使わずに) 。
ちなみに、Ruby のインストールはかなり時間がかかります。

インストール
git clone https://github.com/rbenv/rbenv.git ~/.rbenv
git clone https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build

# .bashrc や .bash_profile などに以下の記述を追加
# 
# export PATH="$HOME/.rbenv/bin:$PATH"
# eval "$(rbenv init -)"
# 
# source などで再読み込み

# インストール可能な Ruby のバージョンを確認
rbenv install -l

# ここではバージョン 2.7.0
# インストールにかなり時間がかかりますが、待ちます
CONFIGURE_OPTS='--disable-install-rdoc' rbenv install 2.7.0

# バージョン切り替え
# ここではバージョン 2.7.0
rbenv global 2.7.0

参考「GitHub - rbenv/rbenv: Groom your app’s Ruby environment
参考「GitHub - rbenv/ruby-build: Compile and install Ruby

3. 説明

3.1. sudo apt install を使わない

sudo apt install すると最新版の Ruby にできず、また、/user/bin 以下にインストールされるため、gem などを使用する際も毎回 sudo が必要になります。
sudo なしで Ruby を使用し、かつ Ruby を最新版にしたいなら、sudo apt install は使えません。

3.2. git clone する

rbenvruby-build に関しても sudo apt install は使えないため、直接 git clone します。

3.3. rbenv install

多少インストール時間を短縮するために CONFIGURE_OPTS='--disable-install-rdoc' を指定します。

参考「Ruby-2.7.0

rbenv install でなく直接 Ruby のソースコードをダウンロードして make した方がかなり速い」という情報がありますが、実際には tar.bz2 の展開に時間がかかりますので、おそらく合計時間はあまり変わらないと思います (未検証) 。

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

rails環境構築その3【terraform】

はじめに

terraformをつかってAWS(EC2,RDS)を作成します。

全体の流れ

  1. terraformインストール
  2. AWSでIAMユーザー作成
  3. AWS CLI導入
    1. AWS CLIにIAMユーザーの登録
  4. terraformとは
  5. terraform導入
    1. プロバイダーの設定
    2. VPC作成
    3. サブネット作成
    4. インターネットゲートウェイ作成
    5. ルートテーブル作成
    6. EC2作成
    7. Security Groupの作成
    8. RDS作成

参考
* 10分で理解するTerraform

terraformインストール

$ brew update
$ brew install terraform

AWSでIAMユーザー作成

参考
* Identity and Access Management へようこそ
* Terraformで構築するAWS

AdministratorAccessポリシー(管理者権限)を選択してください。

権限が足りないと
Error creating VPC: UnauthorizedOperation: You are not authorized to perform this operation.
とエラーが出ます。

AWS CLI インストール

参考
* AWS CLI のインストールと設定
順番にやればいいですが、私の場合はpythonのパスや環境でハマりました
エラー解決↓
* MacOSとHomebrewとpyenvで快適python環境を。
* Python・Python3のインストール先、パス等確認
* Python2.7からPython3.6をデフォルトにする話
* Python3インストール(Mac編)

上記のリンクを参考にすればイケルと思います。

ターミナル
curl "https://bootstrap.pypa.io/get-pip.py" -o "get-pip.py"
sudo python get-pip.py
sudo pip install awscli

エラーなくインストルされバージョンが出れば成功です

ターミナル
pip --version
aws --version

AWS CLIにIAMユーザーの登録

ターミナル(ホームディレクトリ)
aws configure
または、
aws configure --profile ユーザー名

順番に記入します

ターミナル
AWS Access Key ID [None]: 
AWS Secret Access Key [None]: 
Default region name [None]: 
Default output format [None]: json
# Asia Pacific (Tokyo) ap-northeast-1

terraformとは

インフラのコード化であります。GUIを通さずにインフラに変更を加えられコードの共有と再利用ができます。
参考
* インフラの構成管理を自動化するTerraform入門
* Terraformを使ってAWSのVPCを作成してEC2を起動した
ファイル形式は主に.tf.tfvarsを使います。
ファイル分割はあとにして全てmain.tfに書きます。

主なコマンド

terraformがあるディレクトリに移動して実行する
# 初期化 Terraformで新しく設定を記述した場合、初期化を行う必要があります。
terraform init
# 確認(所謂dry-run)
terraform plan
# 適用 コードの状態をAWS上へ適用
terraform apply
# すべて消去するコマンド
terraform destroy
# リソースの閲覧
terraform show

準備

mkdir terraform
cd terraform
touch main.tf
touch terraform.tfvars

プロバイダーの設定

最初にproviderという指定をする必要がある。
複数の環境に対応しているため、「どのプロバイダーを使うのか?」を宣言する

providerとは

  • その名と通りプロバイダでAWSの他にherokuやGCPもできるらしい
  • profileでaws configでprofileを指定した場合はその名前、していない場合は"default"
  • region = "ap-northeast-1"で指定したリージョン内にVPCなどを作っていく
main.tf
provider "aws" {
  profile = ユーザー名
  region  = "ap-northeast-1"
}

VPCを作成

使うリソースaws_vpc

main.tf
# VPC
resource "aws_vpc" "aws-tf-vpc" {
  cidr_block           = "10.1.0.0/16"
  instance_tenancy     = "default"

  tags = {
    Name = "aws-tf-vpc"
  }
}

実行

terraformがあるディレクトリに移動して実行する
terraform init
terraform plan
terraform apply

# リソースの閲覧
terraform show

実際に確かめてみる

aws-tf-vpcと書いてあるVPCがあれば成功です

resourceとは

resourceはVPCやEC2のような起動したいリソースを定義
リソースの種類は、プロバイダーがAWSの場合はaws_*という名前でTerraformで予め定義されています。VPCであればaws_vpc、EC2であればaws_instanceです。

resourceの構文

リソースはresourceブロックで設定します。resource "<リースの種類>" "<リソース名>" {}という構文です。

resourceの定義と命名

resource "aws_vpc" "this" {

ここでは 「"aws_vpc"というリソースを"this"という名前」 で作成しています。
resource "aws_vpc" まではAWSのVPCを作成するという意味で、 "this" はTerraformで定義する他のリソースから参照する際に使用します。

他リソースの属性の参照

Terraformにはテンプレート内の他リソースの属性を参照する方法があります。
具体的には、<リソースの種類>.<リソース名>.<属性名>で他リソースの属性を参照することができます。

その他の知識は下のリンクで
* AWSでTerraformに入門

vscodeをterraform v0.12対応させる

下記のようなメッセージが出た人向け
For Terraform 0.12 support try enabling the experimental language server with the 'Terraform: Enable/Disable Language Server' command

コマンドパレットを開く(ctl/cmd+shift+p)
terraform: install/update language server -> 現在最新の v0.0.9 を選択
terraform: Enable/Disable Language Server を実行
一度vscodeを閉じたらHCL2記法の.tfファイルでもエラーが出なくなりました。

.gitignoreに上げて行けないファイルの追加

下記のファイルはgithubに上げてはいけないとので追加します。
* Terraform.gitignore

.gitignore
#  Local .terraform directories
**/.terraform/*

# .tfstate files
*.tfstate
*.tfstate.*

# .tfvars files
*.tfvars

サブネット作成

使うリソースaws_subnet

main.tf
# サブネット2つ作成(publicとprivate)
resource "aws_subnet" "aws-tf-public-subnet-1a" {
  vpc_id            = aws_vpc.aws-tf-vpc.id
  cidr_block        = "10.1.1.0/24"
  availability_zone = "ap-northeast-1a"
  tags = {
    Name = "aws-tf-public-subnet-1a"
  }
}

resource "aws_subnet" "aws-tf-private-subnet-1a" {
  vpc_id            = aws_vpc.aws-tf-vpc.id
  cidr_block        = "10.1.20.0/24"
  availability_zone = "ap-northeast-1a"
  tags = {
    Name = "aws-tf-private-subnet-1a"
  }
}

インターネットゲートウェイの作成

使うリソースaws_internet_gateway

main.tf
resource "aws_internet_gateway" "aws-tf-igw" {
  vpc_id = aws_vpc.aws-tf-vpc.id
  tags = {
    Name = "aws-tf-igw"
  }
}

ルートテーブルの作成

使うリソースaws_route_table

main.tf
resource "aws_route_table" "aws-tf-public-route" {
  vpc_id = aws_vpc.aws-tf-vpc.id
  route {
    cidr_block = "0.0.0.0/0"
    gateway_id = aws_internet_gateway.aws-tf-igw.id
  }
  tags = {
    Name = "aws-tf-public-route"
  }
}

サブネットの関連付けでルートテーブルをパブリックサブネットに紐付け

使うリソースaws_route_table_association

main.tf
resource "aws_route_table_association" "aws-tf-public-subnet-association" {
  subnet_id      = aws_subnet.aws-tf-public-subnet-1a.id
  route_table_id = aws_route_table.aws-tf-public-route.id
}

EC2作成(public側に作る)

使うリソースaws_instanceaws_key_pair

main.tf
resource "aws_instance" "aws-tf-web" {
  ami                     = "ami-011facbea5ec0363b"
  instance_type           = "t2.micro"
  disable_api_termination = false
  key_name = aws_key_pair.auth.key_name
  vpc_security_group_ids  = [aws_security_group.aws-tf-web.id]
  subnet_id               = aws_subnet.aws-tf-public-subnet-1a.id

  tags = {
    Name = "aws-tf-web"
  }
}

# amiとはAmazon Linux 2 AMIです。今回は実際のamiの値を直接入れてますが、いつも最新版にできます。

variable "public_key_path" {}

resource "aws_key_pair" "auth" {
    key_name = "terraform-aws"
    public_key = file(var.public_key_path)
}
terraform.tfvars
# ローカルに鍵がある場所を指定
public_key_path = "~/.ssh/terraform-aws.pub"

amiを常に最新版にする

インスタンスのkey_nameについて 

GUIで作るときはインスタンス作成時にsshキーを新規作成や既存のキーを使いAWSにアクセスしますが、
terraformで作成する場合は.tfvarsファイルから参照して公開鍵をインスタンスのkey_nameに貼り付けます。
私はterraform-awsという名前で鍵を作成しました。

ターミナル
$ cd .ssh
$ ssh-keygen -t rsa
terraform-aws 今回の場合の名前
ここでエンターキーを2連打
$ ls
ここでterraform-aws  terraform-aws.pubができていることを確認

参考
* Resource: aws_key_pair
* Terraform でキーペア登録し起動した EC2 に SSH接続

Terraform 変数について

Terraform の変数はvariableブロックで定義
var.<変数名>という書式で参照
外部ファイルに値を定義した場合、terraform.tfvarsなら自動的に読み込まれて変数に代入されます。
また.tfvarsはgithubに挙げないとこが大事です。
参考
* 【Terraform 再入門】EC2 + RDS によるミニマム構成な AWS 環境をコマンドライン一発で構築してみよう

Security Groupの作成

使うリソースaws_security_groupaws_security_group_rule

main.tf
resource "aws_security_group" "aws-tf-web" {
  name        = "aws-tf-web"
  description = "aws-tf-web_sg"
  vpc_id      = aws_vpc.aws-tf-vpc.id
  tags = {
    Name = "aws-tf-web"
  }
}

# 80番ポート許可のインバウンドルール
resource "aws_security_group_rule" "inbound_http" {
  type      = "ingress"
  from_port = 80
  to_port   = 80
  protocol  = "tcp"
  cidr_blocks = [
    "0.0.0.0/0",
  ]

  # ここでweb_serverセキュリティグループに紐付け
  security_group_id = aws_security_group.aws-tf-web.id
}

# 22番ポート許可のインバウンドルール
resource "aws_security_group_rule" "inbound_ssh" {
  type      = "ingress"
  from_port = 22
  to_port   = 22
  protocol  = "tcp"
  cidr_blocks = [
    "0.0.0.0/0",
  ]

  # ここでweb_serverセキュリティグループに紐付け
  security_group_id = aws_security_group.aws-tf-web.id
}

# アウトバウンドルール
resource "aws_security_group_rule" "outbound_all" {
  type      = "egress"
  from_port = 0
  to_port   = 0
  protocol  = -1
  cidr_blocks = [
    "0.0.0.0/0",
  ]

  # ここでweb_serverセキュリティグループに紐付け
  security_group_id = aws_security_group.aws-tf-web.id
}

Security Group詳細

ElasticIP作成

使うリソースaws_eip

main.tf
resource "aws_eip" "aws-tf-eip" {
  instance = aws_instance.aws-tf-web.id
  vpc      = true
}
output "example-public-ip" {
    value = "${aws_eip.aws-tf-eip.public_ip}"
}

outputについて

ElasticIPなどはGUIから確認できますが、outputブロックで記述するとterraform apply実行時に下記のように出力されます。

Apply complete! 

Outputs:

example-public-ip = ElasticIP

RDSの作成

RDSは2つのサブネットが必要なのであと一つ違うアベイラビリティゾーンから作成します。
使うリソースaws_subnetaws_db_subnet_group

main.tf
# RDS用のサブネットを作成
resource "aws_subnet" "aws-tf-private-subnet-1c" {
  vpc_id = aws_vpc.aws-tf-vpc.id
  cidr_block = "10.1.3.0/24"
  availability_zone = "ap-northeast-1c"
  tags = {
    Name = "aws-tf-private-subnet-1c"
  }
}
# 使用する2つを指定します。
resource "aws_db_subnet_group" "rdb-tf-db" {
    name        = "rdb-tf-db-subnet"
    description = "It is a DB subnet group on tf_vpc."
    subnet_ids  = [aws_subnet.aws-tf-private-subnet-1a.id,aws_subnet.aws-tf-private-subnet-1c.id]
    tags = {
        Name = "rdb-tf-db"
    }
}

DB用のセキュリティーを作成

WebサーバーからのみDBサーバーにアクセスできるようにするためにセキュリティを作ります。
使うリソースaws_security_groupaws_security_group_rule

main.tf
# Security Group
resource "aws_security_group" "aws-tf-db" {
    name        = "aws-tf-db"
    description = "aws-tf-db-sg"
    vpc_id      = aws_vpc.aws-tf-vpc.id
    tags = {
      Name = "aws-tf-db"
    }
}

resource "aws_security_group_rule" "db" {
    type                     = "ingress"
    from_port                = 5432
    to_port                  = 5432
    protocol                 = "tcp"
    source_security_group_id = aws_security_group.aws-tf-web.id
    security_group_id        = aws_security_group.aws-tf-db.id
}

# source_security_group_idとはアクセスを許可するセキュリティグループIDつまりWeb側のセキュリティグループを指します。

RDSインスタンスの作成

使うリソースaws_db_instance

main.tf

variable "aws-td-db-username" {}
variable "aws-td-db-password" {}

resource "aws_db_instance" "aws-td-db" {
  identifier              = "aws-td-db"
  allocated_storage       = 20
  name = "db11"
  engine                  = "postgres"
  engine_version          = "11.5"
  instance_class          = "db.t2.micro"
  storage_type            = "gp2"
  username                = var.aws-td-db-username
  password                = var.aws-td-db-password
  vpc_security_group_ids  = [aws_security_group.aws-tf-db.id]
  db_subnet_group_name    = aws_db_subnet_group.rdb-tf-db.name
}

terraform.tfvars
public_key_path = "~/.ssh/terraform-aws.pub"
aws-td-db-username = ※※※※※※※※※※
aws-td-db-password = ※※※※※※※※※
それぞれ指定してください。

実行

terraform plan
terraform apply
# 確認
terrafom show

RDSインスタンス作成時にハマったエラーについて

その1
DBName must begin with a letter and contain only alphanumeric characters

これはRDSインスタンスのnameについてのエラーです。私の場合は`name = "db11"`と書きましたが、文字で初めて英数字両方を書かないといけないらしいです。

参考
* AWS aws_db_instance DBName issue

その2
Error creating DB Instance: InvalidParameterValue: Invalid DB engine

これはRDSインスタンスの`engine`の名前の書き方でエラーが出ました。今回は`engine = "postgres"`と書きました。

参考
* "Invalid DB engine" when creating AWS/RDS Postgresql instance
* Engineのセクションを見てください

内容一式

main.tf
provider "aws" {
  profile = プロフィール名
  region  = "ap-northeast-1"
}

# VPC作成
resource "aws_vpc" "aws-tf-vpc" {
  cidr_block           = "10.1.0.0/16"
  instance_tenancy     = "default"
  enable_dns_support   = "true"
  enable_dns_hostnames = "true"
  tags = {
    Name = "aws-tf-vpc"
  }
}

# サブネット2つ作成(publicとprivate)
resource "aws_subnet" "aws-tf-public-subnet-1a" {
  vpc_id            = aws_vpc.aws-tf-vpc.id
  cidr_block        = "10.1.1.0/24"
  availability_zone = "ap-northeast-1a"
  tags = {
    Name = "aws-tf-public-subnet-1a"
  }
}

resource "aws_subnet" "aws-tf-private-subnet-1a" {
  vpc_id            = aws_vpc.aws-tf-vpc.id
  cidr_block        = "10.1.20.0/24"
  availability_zone = "ap-northeast-1a"
  tags = {
    Name = "aws-tf-private-subnet-1a"
  }
}

# インターネットゲートウェイの作成
resource "aws_internet_gateway" "aws-tf-igw" {
  vpc_id = aws_vpc.aws-tf-vpc.id
  tags = {
    Name = "aws-tf-igw"
  }
}

# ルートテーブルの作成
resource "aws_route_table" "aws-tf-public-route" {
  vpc_id = aws_vpc.aws-tf-vpc.id
  route {
    cidr_block = "0.0.0.0/0"
    gateway_id = aws_internet_gateway.aws-tf-igw.id
  }
  tags = {
    Name = "aws-tf-public-route"
  }
}

# サブネットの関連付けでルートテーブルをパブリックサブネットに紐付け
resource "aws_route_table_association" "aws-tf-public-subnet-association" {
  subnet_id      = aws_subnet.aws-tf-public-subnet-1a.id
  route_table_id = aws_route_table.aws-tf-public-route.id
}

# EC2作成(public側)
resource "aws_instance" "aws-tf-web" {
  ami                     = "ami-011facbea5ec0363b"
  instance_type           = "t2.micro"
  disable_api_termination = false
  key_name = aws_key_pair.auth.key_name
  vpc_security_group_ids  = [aws_security_group.aws-tf-web.id]
  subnet_id               = aws_subnet.aws-tf-public-subnet-1a.id

  tags = {
    Name = "aws-tf-web"
  }
}
variable "public_key_path" {}

resource "aws_key_pair" "auth" {
    key_name = "terraform-aws"
    public_key = file(var.public_key_path)
}
# Security Group
resource "aws_security_group" "aws-tf-web" {
  name        = "aws-tf-web"
  description = "aws-tf-web_sg"
  vpc_id      = aws_vpc.aws-tf-vpc.id
  tags = {
    Name = "aws-tf-web"
  }
}

# 80番ポート許可のインバウンドルール
resource "aws_security_group_rule" "inbound_http" {
  type      = "ingress"
  from_port = 80
  to_port   = 80
  protocol  = "tcp"
  cidr_blocks = [
    "0.0.0.0/0",
  ]

  # ここでweb_serverセキュリティグループに紐付け
  security_group_id = aws_security_group.aws-tf-web.id
}

# 22番ポート許可のインバウンドルール
resource "aws_security_group_rule" "inbound_ssh" {
  type      = "ingress"
  from_port = 22
  to_port   = 22
  protocol  = "tcp"
  cidr_blocks = [
    "0.0.0.0/0",
  ]

  # ここでweb_serverセキュリティグループに紐付け
  security_group_id = aws_security_group.aws-tf-web.id
}

# アウトバウンドルール
resource "aws_security_group_rule" "outbound_all" {
  type      = "egress"
  from_port = 0
  to_port   = 0
  protocol  = -1
  cidr_blocks = [
    "0.0.0.0/0",
  ]

  # ここでweb_serverセキュリティグループに紐付け
  security_group_id = aws_security_group.aws-tf-web.id
}

# ElasticIP
resource "aws_eip" "aws-tf-eip" {
  instance = aws_instance.aws-tf-web.id
  vpc      = true
}
output "example-public-ip" {
    value = aws_eip.aws-tf-eip.public_ip
}

####RDSの作成
# RDS用のサブネットを作成
resource "aws_subnet" "aws-tf-private-subnet-1c" {
  vpc_id = aws_vpc.aws-tf-vpc.id
  cidr_block = "10.1.3.0/24"
  availability_zone = "ap-northeast-1c"
  tags = {
    Name = "aws-tf-private-subnet-1c"
  }
}
# DB用のセキュリティーを作成
# Security Group
resource "aws_security_group" "aws-tf-db" {
    name        = "aws-tf-db"
    description = "aws-tf-db-sg"
    vpc_id      = aws_vpc.aws-tf-vpc.id
    tags = {
      Name = "aws-tf-db"
    }
}

resource "aws_security_group_rule" "db" {
    type                     = "ingress"
    from_port                = 5432
    to_port                  = 5432
    protocol                 = "tcp"
    source_security_group_id = aws_security_group.aws-tf-web.id
    security_group_id        = aws_security_group.aws-tf-db.id
}

resource "aws_db_subnet_group" "rdb-tf-db" {
    name        = "rdb-tf-db-subnet"
    description = "It is a DB subnet group on tf_vpc."
    subnet_ids  = [aws_subnet.aws-tf-private-subnet-1a.id,aws_subnet.aws-tf-private-subnet-1c.id]
    tags = {
        Name = "rdb-tf-db"
    }
}

variable "aws-td-db-username" {}
variable "aws-td-db-password" {}

resource "aws_db_instance" "aws-td-db" {
  identifier              = "aws-td-db"
  allocated_storage       = 20
  name = "db11"
  engine                  = "postgres"
  engine_version          = "11.5"
  instance_class          = "db.t2.micro"
  storage_type            = "gp2"
  username                = var.aws-td-db-username
  password                = var.aws-td-db-password

  vpc_security_group_ids  = [aws_security_group.aws-tf-db.id]
  db_subnet_group_name    = aws_db_subnet_group.rdb-tf-db.name
}

terraform.tfvars
public_key_path = "~/.ssh/terraform-aws.pub"
aws-td-db-username = ※※※※※※※※※※
aws-td-db-password = ※※※※※※※※※

おしまい。
何かありましたらコメント欄で

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

Dockerコンテナでの設定ファイル生成にテンプレートとしてERBを使う

Dockerコンテナを起動する際に、環境変数で渡したパラメーターを使って設定ファイルを作りたいことがある。
例えばsambaにアクセスするとき、ユーザー名が foo なら許可、それ以外は不許可としたければ設定ファイルは以下のようにする。

[global]
        log file = /var/log/samba/%m

[share]
        path = /mount
        guest ok = no
        valid users = foo # ユーザー foo ならアクセスを許可する

このユーザー名を可変にしたいとしよう。Docker で docker run -e USER=foo -e PASSWORD=pass ... のようにしたいなら、以下のようになる。

Dockerfile

FROM ubuntu:latest

RUN apt update \
    && apt install -y \
    samba

COPY samba.sh /root/

EXPOSE 139 445

CMD ["/root/samba.sh"]

samba.sh

#!/bin/sh

# /etc/samba/smb.conf を生成する
cat <<SMBCONF >> /etc/samba/smb.conf
[global]
        log file = /var/log/samba/%m

[share]
        path = /mount
        guest ok = no
        valid users = $USER
SMBCONF

# システムに foo ユーザーを追加し、foo ユーザーとしてアクセスできるようにする
useradd $USER
cat <<PASSWORD | passwd $USER
$PASSWORD
$PASSWORD
PASSWORD
cat <<PASSWORD | smbpasswd -a -s $USER
$PASSWORD
$PASSWORD
PASSWORD

# samba サーバーを起動する
/usr/sbin/smbd -F -S --no-process-group

しかしこのファイル生成方法は、smb.conf のテンプレートがスクリプト中にあって気持ちが悪い。
こんなとき Ruby なら ERB が使えるのだが、インストールすると依存する複数のパッケージも入ってしまうし、テンプレートを使いたいだけなのにちょっと大げさだ。

# Ubuntu 19.10 の場合
$ root@f86b2af49215:/# apt install ruby
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following additional packages will be installed:
  ca-certificates fonts-lato javascript-common libgdbm-compat4 libgdbm6 libjs-jquery libruby2.5 libyaml-0-2
  openssl rake ruby-did-you-mean ruby-minitest ruby-net-telnet ruby-power-assert ruby-test-unit ruby-xmlrpc
  ruby2.5 rubygems-integration unzip zip
Suggested packages:
  apache2 | lighttpd | httpd gdbm-l10n ri ruby-dev bundler
The following NEW packages will be installed:
  ca-certificates fonts-lato javascript-common libgdbm-compat4 libgdbm6 libjs-jquery libruby2.5 libyaml-0-2
  openssl rake ruby ruby-did-you-mean ruby-minitest ruby-net-telnet ruby-power-assert ruby-test-unit
  ruby-xmlrpc ruby2.5 rubygems-integration unzip zip
0 upgraded, 21 newly installed, 0 to remove and 23 not upgraded.
Need to get 7568 kB of archives.
After this operation, 31.9 MB of additional disk space will be used.
Do you want to continue? [Y/n]

Ruby には軽量版の mruby がある。
素の mruby のバイナリは Ubuntu 19.10 なら apt install mruby でインストールできるが、これには ERB がバンドルされておらず利用できないので、代わりに mitamae を使うことにする。
プロビジョニングツールであり ERB を使ってテンプレートから設定ファイルを生成し配置する機能をもともと備えているし、シングルバイナリで 2.28MB (v1.10.5の場合)とコンパクトなので、インストールも手間がかからない。

Dockerfile

FROM ubuntu:latest

RUN apt update \
    && apt install -y \
    samba

# mitamae の latest の URL を指定する。
# 最新版のバイナリへのリダイレクトを伴うためか、変更がなくとも docker build の度に毎回ダウンロードが走るので、気になる場合は指定バージョンの URL を使う。
ADD https://github.com/itamae-kitchen/mitamae/releases/latest/download/mitamae-x86_64-linux /root/mitamae
RUN chmod +x /root/mitamae

COPY samba.sh mitamae /root/

EXPOSE 139 445

CMD ["/root/samba.sh"]

samba.sh

#!/bin/sh

(cd /root && mitamae local setup.rb)
# mitamae にはユーザー追加機能も任意のコマンド実行機能もあるので、`passwd` `smbpasswd` も `setup.rb` に切り出してしまう。

# samba サーバーを起動する
/usr/sbin/smbd -F -S --no-process-group

setup.rb

# /etc/samba/smb.conf 生成
template "/etc/samba/smb.conf" do
  variables(user: ENV["USER"])
end

# ユーザー追加
user ENV["USER"] do
  password ENV["password"]
end

execute "Add a samba user" do
  command <<-COMMAND.gsub(/^ */, "")
    cat <<PASSWORD | smbpasswd -a -s #{ENV["USER"]}
    #{ENV["PASSWORD"]}
    #{ENV["PASSWORD"]}
    PASSWORD
  COMMAND
end

mitamae/templates/etc/samba/smb.conf.erb

[global]
        log file = /var/log/samba/%m

[share]
        path = /mount
        guest ok = no
        valid users = <%= @user %>

テンプレート部を別ファイルに切り出せた。

また mitamae 化の他の利点として、実行時にシステムへの変更がわかりやすく差分表示されることを記しておきたい。

パラメーターを JSON にしてみる

mitamae は JSON をパースできる。パラメーターを JSON で渡すことを考えてみる。

param = JSON.parse(ENV["SMB_PARAM"])
user = param["user"]

template "/etc/samba/smb.conf" do
  variables(user: user["name"])
end

user user["name"] do
  password user["password"]
end

execute "Add a samba user" do
  command <<-COMMAND.gsub(/^ */, "")
    cat <<PASSWORD | smbpasswd -a -s #{user["name"]}
    #{user["password"]}
    #{user["password"]}
    PASSWORD
  COMMAND
end
$ smb_param=$(cat <<PARAM
{
  "user": {
    "name": "foo",
    "password": "pass"
  }
}
PARAM

$ sudo docker run --rm -p 139:139 -p 445:445 -e SMB_PARAM="$smb_param"

コード量をそれほど変えることなく JSON に対応することができた。
これにより

  • パラメーターを階層化でき、追加や削除、環境変数の名前空間管理が楽 (プレフィックス付きの長い環境変数名にしなくていい)
  • 配列が扱える (上記の例だとユーザーを複数にするとき USER1, USER2, ... などとせず "user": [...] とできる)
  • 環境ごとにパラメーターをまとめて管理できる (それぞれの JSON ファイルを作ればいい)

などの利便性を得られる。

なお実装は nowlinuxing/docker-samba においてあるので、気になる方は参照されたし。

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

Ruby コーティング規約について コレクション編 2

はじめに

コレクション編 1 はこちらをクリック願います。
命名規則編 2 はこちらをクリック願います。
レイアウト編 3 はこちらをクリック願います。過去記事リンクあり。
構文編 2 はこちらをクリック願います。過去記事リンクあり。
Rubyの基礎を学習中の方に向けて記載致します。
私自身これからチーム開発を行う上で大事にしたい。知っておきたいことをOutputします。

① ハッシュ記法とロケット記法を同じハッシュリテラル内で混在させてはいけない。

※ シンボルでないキーがある場合は、ロケット記法を使う。

qiita.rb
# 悪い例
{ a: 1, 'b' => 2 }

# 良い例
{ :a => 1, 'b' => 2 }

② ハッシュのキーがシンボルの時は、ハッシュリテラル記法を用いる。

qiita.rb
# 悪い例
hash = { :one => 1, :two => 2, :three => 3 }

# 良い例
hash = { one: 1, two: 2, three: 3 }

さいごに

毎日更新します。
皆様の復習等にご活用頂けますと幸いです。

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

instance_evalについて

instance_evalの役割・特徴

  • instance_evalにブロックを渡すor文字列を引数で渡して、特異クラスを定義
  • ローカル変数は引き継ぐ
  • 文字列を渡した場合は特異クラスにネスト
class C
  CONST = "CONST in C"
end
hoge = "hoge"
CONST = "CONST in main"

c1 = C.new
c1.instance_eval(<<-EOS)
  CONST = "CONST in singleton_c1"
  p hoge
  p Module.nesting
  p CONST
EOS

c2 = C.new
c2.instance_eval do
  CONST = "CONST in singleton_c2"
  p hoge
  p Module.nesting
  p CONST
end

文字列実行結果

ネストが特異クラスになるのでCONSTは特異クラスで初めて定義される

"hoge"
[#<Class:#<C:0x000000000500fb18>>]
"CONST in singleton_c1"

ブロック実行結果

ネストが特異クラスの外になるのでCONSTは外側のものを上書きすることになる

rex.rb:17: warning: already initialized constant CONST
rex.rb:5: warning: previous definition of CONST was here
"hoge"
[]
"CONST in singleton_c2"
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Could not find nokogiri-1.10.7 in any of the sources (Bundler::GemNotFound) が出た時の対処法

rails generateを実行したら以下のエラーが出た。

$ rails generate controller Welcome index
Traceback (most recent call last):
        22: from /Library/Ruby/Gems/2.6.0/gems/spring-2.1.0/bin/spring:49:in `<main>'
        21: from /Library/Ruby/Gems/2.6.0/gems/spring-2.1.0/lib/spring/client.rb:30:in `run'
        20: from /Library/Ruby/Gems/2.6.0/gems/spring-2.1.0/lib/spring/client/command.rb:7:in `call'
        19: from /Library/Ruby/Gems/2.6.0/gems/spring-2.1.0/lib/spring/client/server.rb:9:in `call'
        18: from /Users/maiamea/.rbenv/versions/2.6.3/lib/ruby/2.6.0/rubygems/core_ext/kernel_require.rb:54:in `require'
        17: from /Users/maiamea/.rbenv/versions/2.6.3/lib/ruby/2.6.0/rubygems/core_ext/kernel_require.rb:54:in `require'
        16: from /Library/Ruby/Gems/2.6.0/gems/spring-2.1.0/lib/spring/server.rb:9:in `<top (required)>'
        15: from /Users/maiamea/.rbenv/versions/2.6.3/lib/ruby/2.6.0/rubygems/core_ext/kernel_require.rb:54:in `require'
        14: from /Users/maiamea/.rbenv/versions/2.6.3/lib/ruby/2.6.0/rubygems/core_ext/kernel_require.rb:54:in `require'
        13: from /Library/Ruby/Gems/2.6.0/gems/spring-2.1.0/lib/spring/commands.rb:4:in `<top (required)>'
        12: from /Library/Ruby/Gems/2.6.0/gems/spring-2.1.0/lib/spring/commands.rb:33:in `<module:Spring>'
        11: from /Users/maiamea/.rbenv/versions/2.6.3/lib/ruby/2.6.0/rubygems/core_ext/kernel_require.rb:54:in `require'
        10: from /Users/maiamea/.rbenv/versions/2.6.3/lib/ruby/2.6.0/rubygems/core_ext/kernel_require.rb:54:in `require'
         9: from /Users/maiamea/.rbenv/versions/2.6.3/lib/ruby/2.6.0/bundler/setup.rb:20:in `<top (required)>'
         8: from /Users/maiamea/.rbenv/versions/2.6.3/lib/ruby/2.6.0/bundler.rb:107:in `setup'
         7: from /Users/maiamea/.rbenv/versions/2.6.3/lib/ruby/2.6.0/bundler/runtime.rb:20:in `setup'
         6: from /Users/maiamea/.rbenv/versions/2.6.3/lib/ruby/2.6.0/bundler/runtime.rb:108:in `block in definition_method'
         5: from /Users/maiamea/.rbenv/versions/2.6.3/lib/ruby/2.6.0/bundler/definition.rb:226:in `requested_specs'
         4: from /Users/maiamea/.rbenv/versions/2.6.3/lib/ruby/2.6.0/bundler/definition.rb:237:in `specs_for'
         3: from /Users/maiamea/.rbenv/versions/2.6.3/lib/ruby/2.6.0/bundler/definition.rb:170:in `specs'
         2: from /Users/maiamea/.rbenv/versions/2.6.3/lib/ruby/2.6.0/bundler/spec_set.rb:85:in `materialize'
         1: from /Users/maiamea/.rbenv/versions/2.6.3/lib/ruby/2.6.0/bundler/spec_set.rb:85:in `map!'
/Users/maiamea/.rbenv/versions/2.6.3/lib/ruby/2.6.0/bundler/spec_set.rb:91:in `block in materialize': Could not find nokogiri-1.10.7 in any of the sources (Bundler::GemNotFound)

現在使っているRubyのバージョンを確認

$ ruby -v
ruby 2.6.3p62 (2019-04-16 revision 67580) [x86_64-darwin19]
$ rbenv versions
  system
  2.4.1
* 2.6.3 (set by /Users/maiamea/Documents/prog/rails/todo/.ruby-version)
  2.6.5

rbenvでインストールしたRubyと、もともとMacにデフォルトで入っていたRubyのライブラリ(Gem)が混在していたためエラーになっていた。

以下のコマンドで直った。

# Rubyのライブラリ(Gem)のインストール
$ bundle install

# インストールしたRubyライブラリのコマンドをrbenvで使えるようにする
$ rbenv rehash

対処後

$ rails generate controller Welcome index
Running via Spring preloader in process 80856
      create  app/controllers/welcome_controller.rb
       route  get 'welcome/index'
      invoke  erb
      create    app/views/welcome
      create    app/views/welcome/index.html.erb
      invoke  test_unit
      create    test/controllers/welcome_controller_test.rb
      invoke  helper
      create    app/helpers/welcome_helper.rb
      invoke    test_unit
      invoke  assets
      invoke    scss
      create      app/assets/stylesheets/welcome.scss

無事rails generateに成功した。

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

[font-awsomeのエラー]NoMethodError in Creditcard#indexの一例

1.エラーの内容

スクリーンショット 2020-02-15 4.16.35.png

fontawsome利用の記述をしたところそのようなメソッドないというエラーが出ています

2.エラーの原因

公式の記載方法に則っていましたが、gemfileにgem "font-awesome-sass"が抜けているからno methodエラーとなっていました

3.エラーの解決方法

gemfileにgem "font-awesome-sass"を記載し、bundle installをすることで正しく読み込まれます

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

ActionController::UnknownFormat in CreditcardController#indexの解決方法

1.エラーの内容

<エラー文の例>
スクリーンショット 2020-02-15 3.04.40.png

題名部分の英語を読むと"creditcard_controllerに定義したindexアクションはありません"というエラー文となっています

2.エラーの原因

1.viewファイルを作っていない
rails g controller xxxによってファイルを生成した直後はapp/view/xxxフォルダまでしかできておらず、viewファイルは手動で作成する必要があります

2.app/controllers/xxx_controller.rbの中の def 〇〇 に連動したファイル名としていない
railsの機能によりcontroller.rbファイルのdef 〇〇をrequire './view/xxx'という機能により見えないところで呼び出しを行なっています。(xxxフォルダを読み込む(実行されるのは〇〇ファイル)コマンド機能となっています)なので、その命名規則に則っていないとこのエラーとなります。

3.連動したファイル名としているがファイル(フォルダ)名を間違っている
2.と同様の理屈により、スペルミスがあったり、複数形のsをつけ忘れたりすると、呼び出し時にエラーを吐いてしまいます。

4.erbファイルではなく、hamlファイルで記載しようとした時に、gemfileの中にgem 'haml-rails'の記述を忘れている
hamlファイルというのは独自の追加機能で、読み込むにはgemファイルが必要であり、その記載を忘れているとファイル名があっていてもファイルそのものを読み込むことができず、エラーを吐いてしまいます

3.エラーの解決法

1.app/view/xxx/〇〇.html.erb この位置にファイルをつくる
2.app/view の中のフォルダ名(xxx)とファイル名(〇〇)がコントローラ名と対応しているか確認する
3.対象ファイルが2.の命名規則に従いつつ誤字脱字や複数形のミスをしていないか確認する
4.(hamlファイルを使用する場合、)gemfileの中にgem 'haml-rails'の記述を行い、bundle installコマンドを打つ

これで題名のエラーについて大抵のものは解決できるかと思います。

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

[Rails]ActionController::UnknownFormat in UsersController#indexの解決方法

1.エラーの内容

<エラー文の例>
スクリーンショット 2020-02-15 4.03.58.png

題名部分の英語を読むと"creditcard_controllerに定義したindexアクションはありません"というエラー文となっています

2.エラーの原因

1.viewファイルを作っていない
rails g controller xxxによってファイルを生成した直後はapp/view/xxxフォルダまでしかできておらず、viewファイルは手動で作成する必要があります

2.app/controllers/xxx_controller.rbの中の def 〇〇 に連動したファイル名としていない
railsの機能によりcontroller.rbファイルのdef 〇〇をrequire './view/xxx'という機能により見えないところで呼び出しを行なっています。(xxxフォルダを読み込む(実行されるのは〇〇ファイル)コマンド機能となっています)なので、その命名規則に則っていないとこのエラーとなります。

3.連動したファイル名としているがファイル(フォルダ)名を間違っている
2.と同様の理屈により、スペルミスがあったり、複数形のsをつけ忘れたりすると、呼び出し時にエラーを吐いてしまいます。

4.erbファイルではなく、hamlファイルで記載しようとした時に、gemfileの中にgem 'haml-rails'の記述を忘れている
hamlファイルというのは独自の追加機能で、読み込むにはgemファイルが必要であり、その記載を忘れているとファイル名があっていてもファイルそのものを読み込むことができず、エラーを吐いてしまいます

3.エラーの解決法

1.app/view/xxx/〇〇.html.erb この位置にファイルをつくる
2.app/view の中のフォルダ名(xxx)とファイル名(〇〇)がコントローラ名と対応しているか確認する
3.対象ファイルが2.の命名規則に従いつつ誤字脱字や複数形のミスをしていないか確認する
4.(hamlファイルを使用する場合)gemfileの中にgem 'haml-rails'の記述を行い、bundle installコマンドを打つ

これで題名のエラーについて大抵のものは解決できるかと思います。

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

モジュールを特異メソッドとして取り込む

特異メソッドで宣言してもincludeでは取り込めない

module M
  def self.class_m
    "M.class_m"
  end
end

class C
  include M
end

p C.methods.include? :class_m #false

特異メソッドとしてクラスに取り込むには下記のようにする

module M
  def class_m
    "M.class_m"
  end
end

class C
  extend M
end

p C.methods.include? :class_m # true
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Refinementでクラスメソッドを再定義する

方法1

singleton_classを使う

class MyClass
  def self.my_method
    'MyClass.my_method'
  end
end

module MyModule
  refine MyClass.singleton_class do
    def my_method
      'Myclass.my_method in MyModule'
    end
  end
end

using MyModule

puts MyClass.my_method # Myclass.my_method in MyModule

方法2

selfを使わずクラスメソッドを定義

class MyClass
  def self.my_method
    'MyClass.my_method'
  end
end

module MyModule
  refine MyClass do
    def MyClass.my_method
      'Myclass.my_method in MyModule'
    end
  end
end

using MyModule

puts MyClass.my_method # Myclass.my_method in MyModule

もしくは

class MyClass
  def self.my_method
    'MyClass.my_method'
  end
end

module MyModule
  refine MyClass do
    class << MyClass
      def my_method
        'Myclass.my_method in MyModule'
      end
    end
  end
end

using MyModule

puts MyClass.my_method # Myclass.my_method in MyModule

selfの場合

うまく呼び出すことができない

class MyClass
  def self.my_method
    'MyClass.my_method'
  end
end

module MyModule
  refine MyClass do
    def self.my_method
      'Myclass.my_method in MyModule'
    end
  end
end

using MyModule

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

Ruby on Railsを触ってみる〜環境構築編〜

はじめに

最近転職サイトを見ていると、最近のイケイケの企業の使用言語としてRubyが多く見受けられます。またその中のほとんどの企業がRuby on Railsを使っているため、私も触ってみようと思います。
Railsの情報はネット上にあふれているためこの記事では特に新しいことは書いておらず先駆者の記事を参考にしておこなった自分の作業の備忘録となります。

Ruby on Railsの環境構築

macOSで環境構築をして行きます。
ほとんどの手順を以下の記事を参考にさせていただきました。
Ruby初学者のRuby On Rails 環境構築【Mac】

ターミナルを開く(mac初心者向け)

「command」+「space」でSpotlightを開いて「ターミナル」と入力。
ターミナルを選んで起動します。
今回のコマンドは全てこのターミナルから行います。

Homebrewのインストール

Homebrewのサイトに記載されている以下のコマンドを実行し、Homebrewをインストールします。

$ /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

Homebrewとは?
homebrewとは何者か。仕組みについて調べてみた

rbenvのインストール

こいつをいれるとRubyのバージョン管理ができるようになるらしい

$ brew install rbenv ruby-build

pathを通す

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

rbenvの設定をローカルに反映

$ echo 'eval "$(rbenv init -)"' >> ~/.bash_profile

.bash_profileの適用

$ source ~/.bash_profile

Rubyのインストール

{version}箇所は任意。まあ新しめのバージョンがいいと思います。
私は2.7.0をインストールしました。

$ rbenv install {version}

対象のバージョンをglobalで使えるようにする。
globalで基本となるバージョンを指定して、プロジェクトによってバージョンを変えたい場合は都度localで設定するのが良き。

$ rbenv global 2.7.0

最後にバージョンを確認

$ ruby -v

Bandlerのインストール

$ gem install bundler
$ bundler -v

Railsのインストール

インストールするディレクトリ作成

$ mkdir ~/rails_workspace

作ったディレクトリに移動

$ cd ~/rails_workspace

Gemfileを作成する

$ bundle init

Gemfileを編集する

$ vi Gemfile

「i」キーを押してINSERTモードに変更。
「# gem "rails"」となっている行を「gem "rails"」に変更

「esc」キーを押して「:wq」を入力し、編集終了。

Railsをインストール

$ bundle install --path=vendor/bundle

確認

$ bundle exec rails -v

プロジェクトを作成

$ bundle exec rails new test

作成したプロジェクトディレクトリに移動

$ cd test

railsの起動

$ rails server

だがしかしここで問題!

Node.js not installed. Please download and install Node.js

どうやらNode.jsが必要見たいなので、nodebrewを使ってインストールを行います。

nodebrewをインストール

$ brew install nodebrew

バージョンの確認

$ nodebrew -v

Node.jsをインストール

stable:安定版をインストール

$ nodebrew install-binary stable

上記コマンドでエラーが出た際は以下のコマンドを実施が再度コマンド実行

$ mkdir -p ~/.nodebrew/src

nodeのバージョン確認

$ nodebrew ls

v12.16.0
current: none

nodeの有効化
バージョン番号は合わせてください。

$ nodebrew use v12.16.0

pathを通す

$ echo 'export PATH=$HOME/.nodebrew/current/bin:$PATH' >> ~/.bash_profile

適用

$ source ~/.bash_profile

nodeのバージョン確認

$ node -v

-bash: node: command not found

はい???

インストールもpathも問題ないはずなのにnodeコマンドが実行できない。。
少し調べたらこのような記事が見つかりました。
HomebrewでインストールしたnodebrewではNode.jsやnpmが使えない

他の記事ではnodeが使えるようなので、バージョンや環境差異など何かが影響しているのかも。
ひとまずリンク先にある手順でnodeを再インストール

まずはアンインストール

$ nodebrew uninstall v12.16.0
$ nodebrew clear v12.16.0
$ brew uninstall nodebrew

CURLコマンドでnodebrewをインストール

$ curl -L git.io/nodebrew | perl - setup

nodeの確認

$ node -v
v12.16.0

できた!!!

railsの起動のため、プロジェクトディレクトリに移動

$ cd ~/rails_workspace/test

rails起動

$ rails server

~~
/webpacker.yml. Please run rails webpacker:install Error: No such file or directory 
~~

nodeではない別のエラーが。。。
「Please run rails webpacker:install」とおっしゃっているので以下のコマンドを実行してみる。

$ rails webpacker:install

するとまた別のエラーが。

Yarn not installed. Please download and install Yarn from https://yarnpkg.com/lang/en/docs/install/

yarnが必要とのことなのでこちらもインストール

$ brew install yarn

再度webpakerのインストールを行う

$ rails webpacker:install

うまくいきました。
次こそrailsを起動

$ rails server

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

無事起動しました。
この状態のままブラウザを使ってlocalhost:3000にアクセスします。
以下の画面が表示されれば成功です。

スクリーンショット 2020-02-14 20.10.16.png

最後に

ちょこちょこ詰まるところもありましたが、先駆者たちのおかげで比較的簡単に環境構築できました。次回はRailsをはじめようをやってみてrailsやMVCに対する理解を深めていきます。

bundlerやgemに関する理解が甘いため後ほどちゃんと確認をします。

その他参考にさせて頂いたQiita記事

【Mac】node.jsインストール方法
MacにNode.jsをインストール
Rails6 Webpackerでエラーが出た

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