ためすう

Ruby で map の &: を使ってみる

2019-07-13

やったこと

Ruby で map(&:) を使ってみます。

確認環境

$ ruby --version
ruby 2.6.3p62 (2019-04-16 revision 67580) [x86_64-darwin17]

調査

$ irb
irb(main):001:0> numbers = [1, 3, 5, 7]
=> [1, 3, 5, 7]
irb(main):002:0> numbers.map(&:to_s)
=> ["1", "3", "5", "7"]
irb(main):003:0> numbers.map {|i| i.to_s}
=> ["1", "3", "5", "7"]

map メソッドの &: を使うと簡潔に書くことができます。

参考

Rails の config で eager_load を設定してみる

2019-07-13

やったこと

Rails の config で eager_load を設定してみます。

確認環境

$ ruby --version
ruby 2.6.3p62 (2019-04-16 revision 67580) [x86_64-darwin17]

$ rails --version
Rails 5.2.3

調査

config.eager_load: trueにすると、config.eager_load_namespacesに登録された事前一括読み込み(eager loading)用の名前空間をすべて読み込みます。ここにはアプリケーション、エンジン、Railsフレームワークを含むあらゆる登録済み名前空間が含まれます。

共通で使う、下記のようなファイルを作成します。

app/models/hogehoge/abc.rb

module Hogehoge
  class Abc < Abc
  end
end

config.eager_load = false の時

$ rails c
irb(main):001:0> Object.const_defined?('Hogehoge::Abc')
=> false
irb(main):002:0> Hogehoge::Abc
=> Hogehoge::Abc
irb(main):003:0> Object.const_defined?('Hogehoge::Abc')
=> true

config.eager_load = true の時

$ rails c
irb(main):001:0> Object.const_defined?('Hogehoge::Abc')
=> true

参考

Rails5 の require_dependency を使ってみる

2019-07-11

やったこと

Rails の require_dependency を使ってみます。

確認環境

$ ruby --version
ruby 2.6.3p62 (2019-04-16 revision 67580) [x86_64-darwin17]

$ rails --version
Rails 5.2.3

調査

クラス名が衝突する

app/controllers/concerns/hoge/piyo_controller.rb

このファイルがロードされる時、Hoge::ApplicationController が呼ばれていないと

::ApplicationController を見に行ってしまいます。

module Hoge
  class PiyoController < ApplicationController
  end
end

app/helpers/application_controller.rb

module Hoge
  class ApplicationController
    def abc
      p "method: #{__method__}"
    end
  end
end

app/controllers/application_controller.rb

class ApplicationController < ActionController::Base
  def root_app
    p "method: #{__method__}"
  end
end

出力結果

irb(main):009:0> Hoge::PiyoController.new.abc
Traceback (most recent call last):
        1: from (irb):9
NoMethodError (undefined method `abc' for #<Hoge::PiyoController:0x00007fb4244b20c8>)
irb(main):010:0> Hoge::PiyoController.new.root_app
"method: root_app"
=> "method: root_app"

以上より、::ActionController が継承されていることが分かります。

クラス名の衝突を解決する

変更があるファイルだけ載せます。

解決方法は下記の方法があるようでした。

  • 名前空間をきっちり記述する
  • require_dependency を使う

今回は require_dependency を使います。

require_dependency 'app/helpers/application_controller'

module Hoge
  class PiyoController < ApplicationController
  end
end

出力結果

irb(main):012:0> Hoge::PiyoController.new.abc
"method: abc"
=> "method: abc"
irb(main):013:0> Hoge::PiyoController.new.root_app
Traceback (most recent call last):
        1: from (irb):13
NoMethodError (undefined method `root_app' for #<Hoge::PiyoController:0x00007fb423ee5a00>)

Hoge::ApplicationController が継承されていることが分かりました。

ちなみに

Rails がファイルを読み込むときのパスは下記のようになっています。

irb(main):001:0> puts ActiveSupport::Dependencies.autoload_paths
/Users/demo/app/assets
/Users/demo/app/channels
/Users/demo/app/controllers
/Users/demo/app/controllers/concerns
/Users/demo/app/helpers
/Users/demo/app/jobs
/Users/demo/app/mailers
/Users/demo/app/models
/Users/demo/app/models/concerns
/Users/demo/app/workers
/Users/demo/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/activestorage-5.2.3/app/assets
/Users/demo/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/activestorage-5.2.3/app/controllers
/Users/demo/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/activestorage-5.2.3/app/controllers/concerns
/Users/demo/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/activestorage-5.2.3/app/javascript
/Users/demo/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/activestorage-5.2.3/app/jobs
/Users/demo/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/activestorage-5.2.3/app/models
/Users/demo/spec/mailers/previews

参考

Ruby でマジックコメントの frozen_string_literal を使ってみる

2019-07-09

やったこと

Ruby でマジックコメントの frozen_string_literal を使ってみます。

確認環境

$ ruby --version
ruby 2.6.3p62 (2019-04-16 revision 67580) [x86_64-darwin17]

調査

test.rb

# frozen_string_literal: true

a = 'abc'

puts a.frozen?

puts a.upcase

# 例外が発生します
puts a.upcase!

出力結果

$ ruby test.rb
true
ABC
Traceback (most recent call last):
	1: from ruby-frozen.rb:9:in `<main>'
ruby-frozen.rb:9:in `upcase!': can't modify frozen String (FrozenError)

参考

Ruby で concat を使ってみる

2019-07-08

やったこと

Ruby で concat を使ってみます。

確認環境

$ ruby --version
ruby 2.6.3p62 (2019-04-16 revision 67580) [x86_64-darwin17]

調査

$ irb
irb(main):001:0> a = [1, 2]
=> [1, 2]
irb(main):002:0> b = [4, 3]
=> [4, 3]
irb(main):003:0> a.concat(b)
=> [1, 2, 4, 3]
irb(main):004:0> a
=> [1, 2, 4, 3]

concat を呼び出した a に破壊的な変更が入ります。

$ irb
irb(main):001:0> a = [1, 2]
=> [1, 2]
irb(main):002:0> b = [8, 9]
=> [8, 9]
irb(main):003:0> a + b
=> [1, 2, 8, 9]
irb(main):004:0> a
=> [1, 2]
irb(main):005:0> b
=> [8, 9]

Array の + を使うと、破壊的な変更を入れずに配列の結合ができます。

参考

Rails で generate コマンドを使った時に自動生成される rspec を制御する

2019-07-07

やったこと

Rails の generate コマンドを使った時、rspec のファイルも自動生成されますが

今回、自動生成される rspec のファイルを制御します。

確認環境

$ ruby --version
ruby 2.6.3p62 (2019-04-16 revision 67580) [x86_64-darwin17]

$ rails --version
Rails 5.2.3

$ gem list | grep rspec-rails
rspec-rails (3.8.2)

調査

変更前

$ rails g controller Users new
Running via Spring preloader in process 49766
      create  app/controllers/users_controller.rb
       route  get 'users/new'
      invoke  erb
      create    app/views/users
      create    app/views/users/new.html.erb
      invoke  rspec
      create    spec/controllers/users_controller_spec.rb
      create    spec/views/users
      create    spec/views/users/new.html.erb_spec.rb
      invoke  helper
      create    app/helpers/users_helper.rb
      invoke    rspec
      create      spec/helpers/users_helper_spec.rb
      invoke  assets
      invoke    coffee
      create      app/assets/javascripts/users.coffee
      invoke    scss
      create      app/assets/stylesheets/users.scss

変更後

config/application.rb

module Sample2
  class Application < Rails::Application
    # 途中コードはスキップ

    config.generators do |g|
      g.test_framework :rspec,
        fixtures: false,
        view_specs: false,
        helper_specs: false,
        routing_specs: false
    end
  end
end
$ rails g controller Users new
Running via Spring preloader in process 51917
      create  app/controllers/users_controller.rb
       route  get 'users/new'
      invoke  erb
      create    app/views/users
      create    app/views/users/new.html.erb
      invoke  rspec
      create    spec/controllers/users_controller_spec.rb
      invoke  helper
      create    app/helpers/users_helper.rb
      invoke    rspec
      invoke  assets
      invoke    coffee
      create      app/assets/javascripts/users.coffee
      invoke    scss
      create      app/assets/stylesheets/users.scss

参考

  • Everyday Rails - RSpecによるRailsテスト入門 (2. RSpecのインストール)

Rails5 の flash を使ってみる (keep、now)

2019-07-07

やったこと

Rails の flash について挙動を調べます。

keep、now についても調べます。

確認環境

$ ruby --version
ruby 2.6.3p62 (2019-04-16 revision 67580) [x86_64-darwin17]

$ rails --version
Rails 5.2.3

調査

検証で使ったコード

formからGETメソッドで下記のように遷移します。

/users/new -> /users/new2 -> /users/new3

config/routes.rb

Rails.application.routes.draw do
  get 'users/new'
  get 'users/new2'
  get 'users/new3'
end

app/views/users/new.html.erb

<p><%= flash[:abc] %></p>
<form action="/users/new2">
  <input type="submit">
</form>

app/views/users/new2.html.erb

<%= flash[:abc] %>
<form action="/users/new3">
  <input type="submit">
</form>

app/views/users/new3.html.erb

<%= flash[:abc] %>

通常 (flash)

app/controllers/users_controller.rb

class UsersController < ApplicationController
  def new
    # 通常 (flash)
    flash[:abc] = Time.current
    logger.debug("flash[:abc]: #{flash[:abc]}")
  end

  def new2
    logger.debug("flash[:abc]: #{flash[:abc]}")
  end

  def new3
    logger.debug("flash[:abc]: #{flash[:abc]}")
  end
end

出力結果 (抜粋)

Started GET "/users/new" for ::1 at 2019-07-07 01:23:52 +0900
flash[:abc]: 2019-07-07 01:23:52 +0900

Started GET "/users/new2" for ::1 at 2019-07-07 01:23:53 +0900
flash[:abc]: 2019-07-07T01:23:52.266+09:00

Started GET "/users/new3" for ::1 at 2019-07-07 01:23:55 +0900
flash[:abc]:

rails-flash.png

flash.now

app/controllers/users_controller.rb

class UsersController < ApplicationController
  def new
    # flash.now
    flash.now[:abc] = Time.current
    logger.debug("flash[:abc]: #{flash[:abc]}")
  end

  def new2
    logger.debug("flash[:abc]: #{flash[:abc]}")
  end

  def new3
    logger.debug("flash[:abc]: #{flash[:abc]}")
  end
end

出力結果 (抜粋)

Started GET "/users/new" for ::1 at 2019-07-07 01:15:06 +0900
flash[:abc]: 2019-07-07 01:15:07 +0900

Started GET "/users/new2" for ::1 at 2019-07-07 01:15:13 +0900
flash[:abc]:

Started GET "/users/new3" for ::1 at 2019-07-07 01:15:21 +0900
flash[:abc]:

rails_session_now.png

flash.keep

app/controllers/users_controller.rb

class UsersController < ApplicationController
  def new
    flash[:abc] = Time.current
    logger.debug("flash[:abc]: #{flash[:abc]}")
  end

  def new2
    # flash.keep
    flash.keep(:abc)
    logger.debug("flash[:abc]: #{flash[:abc]}")
  end

  def new3
    logger.debug("flash[:abc]: #{flash[:abc]}")
  end
end

出力結果 (抜粋)

Started GET "/users/new" for ::1 at 2019-07-07 01:26:54 +0900
flash[:abc]: 2019-07-07 01:26:54 +0900

Started GET "/users/new2" for ::1 at 2019-07-07 01:26:56 +0900
flash[:abc]: 2019-07-07T01:26:54.958+09:00

Started GET "/users/new3" for ::1 at 2019-07-07 01:26:57 +0900
flash[:abc]: 2019-07-07T01:26:54.958+09:00

rails-keep.png

rspec で binstub をインストールしてみる

2019-07-06

やったこと

binstub をインストールしてみます。

確認環境

$ ruby --version
ruby 2.6.3p62 (2019-04-16 revision 67580) [x86_64-darwin17]

$ rails --version
Rails 5.2.3

$ gem list | grep rspec-rails
rspec-rails (3.8.2)

調査

Gemfile

group :development do
  gem 'spring-commands-rspec'
end
$ bundle install

bin/rspec を作成します。

$ bundle exec spring binstub rspec

テストを実行します。

$ bin/rspec

RubyGemsのbinstubの目的は、gemの種類を問わず、本来の実行可能ファイルを呼び出す前に$LOAD_PATHを準備することです。

参考

pandas の DataFrame でカラム名を取得する

2019-07-06

やったこと

pandas の DataFrame からカラム名の一覧を取得します。

確認環境

$ ipython --version
6.1.0
$ jupyter --version
4.3.0
$ python --version
Python 3.6.2 :: Anaconda custom (64-bit)
import pandas as pd
print(pd.__version__)
0.20.3

調査

import pandas as pd
train = {'col1': [1, 2], 'col2': [3, 4]}
df = pd.DataFrame(train)
df.columns

Index([‘col1’, ‘col2’], dtype=‘object’)

列名の一覧を取得することができました。

参考

.rspec を変更してみる

2019-07-06

やったこと

rspec をインストールした時に生成される .rspec ファイルを変更してみました。

確認環境

$ ruby --version
ruby 2.6.3p62 (2019-04-16 revision 67580) [x86_64-darwin17]

$ rails --version
Rails 5.2.3

$ gem list | grep rspec-rails
rspec-rails (3.8.2)

調査

テストを実行する

今回、このコードを使います。

spec/models/task7_spec.rb

require 'rails_helper'

RSpec.describe Task, type: :model do
  it 'test7' do
  end
end

出力結果

$ rspec spec/models/task7_spec.rb
.

Finished in 0.00866 seconds (files took 3.99 seconds to load)
1 example, 0 failures

.rspec を編集してみる

.rspec

--require spec_helper
--format documentation

出力結果

$ rspec spec/models/task7_spec.rb

Task
  test7

Finished in 0.0017 seconds (files took 1.68 seconds to load)
1 example, 0 failures

補足

.rspec は設定ファイルです。

実行時に下記で実行したのと同等です。

$ rspec spec/models/task7_spec.rb --format documentation

出力のフォーマットを変更することができます。

一部抜粋

$ rspec spec/models/task7_spec.rb --format documentation
$ rspec --help

    -f, --format FORMATTER             Choose a formatter.
                                         [p]rogress (default - dots)
                                         [d]ocumentation (group and example names)
                                         [h]tml
                                         [j]son

参考

  • Everyday Rails - RSpecによるRailsテスト入門 (2. RSpecのインストール)