ためすう

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のインストール)

Ruby で %Q を使ってみる

2019-07-05

やったこと

Ruby で %Q を使ってみます。

確認環境

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

調査

ダブルクオートの文字列と同等です。

%Q を使ったもの

$ irb
irb(main):001:0> method = %Q(
irb(main):002:0"   def hoge
irb(main):003:0"     print __method__
irb(main):004:0"   end
irb(main):005:0"
irb(main):006:0" )
=> "\n  def hoge\n    print __method__\n  end\n\n"
irb(main):007:0> print method

  def hoge
    print __method__
  end

=> nil

% を使ったもの

$ irb
...

irb(main):009:0> method2 = %(ddddd)
=> "ddddd"
irb(main):010:0> method2 = %(ddddd
irb(main):011:0"
irb(main):012:0"
irb(main):013:0" )
=> "ddddd\n\n\n"
irb(main):014:0> print method2
ddddd


=> nil

参考

第18章 Convention over Configuration

2019-07-05

「Rubyによるデザインパターン」の読書メモです。

CoC パターンの主な動機は、設定の負荷を軽減することです。

test.rb

require 'uri'

class Message
  attr_accessor :from, :to, :body

  def initialize(from, to, body)
    @from = from
    @to = URI.parse(to)
    @body = body
  end
end

class MessageGateway
  def initialize
    load_adapters
  end

  def process_message(message)
    adapter = adapter_for(message)
    adapter.send_message(message)
  end

  def adapter_for(message)
    protocol = message.to.scheme
    adapter_class = protocol.capitalize + 'Adapter'
    adapter_class = self.class.const_get(adapter_class)
    adapter_class.new
  end

  def load_adapters
    lib_dir = File.dirname(__FILE__)
    full_pattern = File.join(lib_dir, 'adapter', '*.rb')
    Dir.glob(full_pattern).each {|file| require file }
  end
end

m = Message.new('from', 'ftp://xxxxx?ggg=2', 'bodybody')
mg = MessageGateway.new
mg.process_message(m)

出力結果

$ ruby test.rb
"FtpAdapter:send_message #<Message:0x00007fe951195658>"

注意点

規約に基づいたシステムの構築で危険なことの1つは、利用する規約の出来が不完全な場合、その結果としてシステムにできることの幅を制限するかもしれないということです。

Ruby で itself を使ってみる

2019-07-04

やったこと

Ruby で itself を使ってみます。

確認環境

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

調査

itself は self 自身を返却します。

$ irb
irb(main):001:0> string = 'abcd'
=> "abcd"
irb(main):002:0> string.itself
=> "abcd"
irb(main):003:0> array = [3, 2, 1, 3, 2, 1]
=> [3, 2, 1, 3, 2, 1]
irb(main):004:0> array.group_by(&:itself)
=> {3=>[3, 3], 2=>[2, 2], 1=>[1, 1]}

nil とか false で試しても、 self が返却されました。

irb(main):001:0> nil.itself
=> nil
irb(main):002:0> false.itself
=> false

参考

第17章 カスタムオブジェクトを作る: メタプログラミング

2019-07-04

「Rubyによるデザインパターン」の読書メモです。

test.rb

class CompositeBase
  attr_reader :name

  def initialize(name)
    @name = name
  end

  def self.member_of(composite_name)
    code = %Q{
      attr_accessor :parent_#{composite_name}
    }
    class_eval(code)
  end

  def self.composite_of(composite_name)
    member_of composite_name

    code = %Q{
      def sub_#{composite_name}s
        @sub_#{composite_name}s = [] unless @sub_#{composite_name}s
        @sub_#{composite_name}s
      end

      def add_sub_#{composite_name}(child)
        return if sub_#{composite_name}s.include?(child)
        sub_#{composite_name}s << child
        child.parent_#{composite_name} = self
      end

      def delete_sub_#{composite_name}(child)
        return unless sub_#{composite_name}s.include?(child)
        sub_#{composite_name}s.delete(child)
        child.parent_#{composite_name} = nil
      end
    }
    class_eval(code)
  end
end

class Tiger < CompositeBase
  member_of(:population)
  member_of(:classification)
end

class Jungle < CompositeBase
  composite_of(:population)
end

class Species < CompositeBase
  composite_of(:classification)
end

tony_tiger = Tiger.new('tony')
se_jungle = Jungle.new('southeastern jungle tigers')
se_jungle.add_sub_population(tony_tiger)

p tony_tiger.parent_population.class

species = Species.new('P. tigers')
species.add_sub_classification(tony_tiger)
p tony_tiger.parent_classification.class

出力結果

$ ruby test.rb
Jungle
Species

まとめ

メタプログラミングは、必要なコードを取得するためのもっとも簡単な方法になりうるアイディアで、キーボードでコードをすべて書くのではなく、実行時にプログラムに基づいて作り出すというやり方によるものです。

Ruby で %i を使ってみる

2019-07-04

やったこと

%i を使って、シンボルを作ってみます。

確認環境

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

調査

%i を使ってシンボルが作れます。

$ irb
irb(main):001:0> %i(a b c)
=> [:a, :b, :c]
irb(main):002:0> %i(a\ b c)
=> [:"a b", :c]

参考

Ruby で collect を使ってみる

2019-07-02

やったこと

collect メソッドを使ってみます。

確認環境

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

調査

mapメソッドは、collectの別名です。

$ irb
...

irb(main):002:0> p (1..8).collect {|n| n**3}
[1, 8, 27, 64, 125, 216, 343, 512]
=> [1, 8, 27, 64, 125, 216, 343, 512]
irb(main):003:0> p (1..8).map {|n| n**3}
[1, 8, 27, 64, 125, 216, 343, 512]
=> [1, 8, 27, 64, 125, 216, 343, 512]

collect でも、 map でも同じ結果が返って来てます。

参考