ためすう

Rails で content_for と yield を使ってみる

2019-07-25

やったこと

Rails で content_for と yield を使ってみます。

確認環境

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

$ rails --version
Rails 5.2.3

調査

app/views/layouts/application.html.erb

<!DOCTYPE html>
<html>
  <head>
    <title><%= yield :my_title %></title>
    <%= csrf_meta_tags %>
    <%= csp_meta_tag %>

    <%= stylesheet_link_tag    'application', media: 'all', 'data-turbolinks-track': 'reload' %>
    <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
  </head>

  <body>
    <%= yield %>
  </body>
</html>

app/views/tasks/new.html.erb

<% content_for :my_title do %>my title!!!<% end %>

app/controllers/tasks_controller.rb

class TasksController < ApplicationController
  def new
  end
end

http://localhost:3000/tasks/new にアクセスして確認すると、

title タグに content_for で指定した文字が表示されていることが分かります。

参考

numpy.random.randint を使ってみる

2019-07-25

やったこと

Numpy で numpy.random.randint を使ってみます。

確認環境

$ ipython --version
6.1.0
$ jupyter --version
4.3.0
$ python --version
Python 3.6.2 :: Anaconda custom (64-bit)
import numpy as np
np.__version__
'1.13.1'

調査

np.random.randint(0, 2, size=5)

array([1, 0, 1, 1, 1])

0 以上 1 以下で、要素が 5 つの配列が作成されます。

参考

Ruby で Method オブジェクトから引数の情報を得る

2019-07-24

やったこと

Ruby で const_get を使ってみます。

確認環境

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

調査

test.rb

class Sample
  def hogehoge(a, b = 1, c:, d: 222)
  end
end

p Sample.new.method(:hogehoge)
p Sample.new.method(:hogehoge).parameters

実行結果

$ ruby test.rb
#<Method: Sample#hogehoge>
[[:req, :a], [:opt, :b], [:keyreq, :c], [:key, :d]]

引数の情報を取得することができました。

参考

Anaconda で OpenCV をインストールする

2019-07-24

やったこと

Anaconda で OpenCV をインストールします

確認環境

$ ipython --version
6.1.0
$ jupyter --version
4.3.0
$ python --version
Python 3.6.2 :: Anaconda custom (64-bit)

調査

下記を参考に、ターミナルで conda の仮想環境を active にします。

OpenCV のインストール

$ conda install -c conda-forge opencv
import cv2
print(cv2.__version__)

4.1.0

OpenCV の4系をインストールすることが出来ました。

参考

Ruby で const_get を使ってみる

2019-07-23

やったこと

Ruby で const_get を使ってみます。

確認環境

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

調査

test.rb

class Sample
  ABC = 'abc'
end

p Object.const_get('Sample')
p Class.const_get('Sample')

p Object.const_get('Sample::ABC')
p Class.const_get('Sample::ABC')
p Sample.const_get('ABC')

p Object.const_get('Sample::ABCD')

実行結果

$ ruby test.rb
Sample
Sample
"abc"
"abc"
"abc"
Traceback (most recent call last):
test.rb:11:in `<main>': uninitialized constant Sample::ABCD (NameError)

存在しない値を参照しようとすると、例外が発生します。

参考

アジャイルソフトウェア開発の奥義 第8章 単一責任の原則 (SRP)

2019-07-20

「アジャイルソフトウェア開発の奥義」の読書メモです。

時々、個人の見解入りです。

単一責任の原則

SRP: The Single Responsibility Princple

クラスを変更する理由は1つ以上存在してはならない。

クラスが複数の役割を背負っているような場合、それらの役割は結合してしまう。その結果、ある役割が変更を受けると、そのクラスが担っている他の役割も 影響を受け、不具合が生じる可能性がある。

このクラスは下記2つの役割を持っています。

  • 接続の管理
  • データ通信

「接続の管理」「データ通信」の2つの役割を持つ

test1.rb

module Modem
  # 接続の管理
  def dial(pno)
    raise '実装してください'
  end

  def hangup()
    raise '実装してください'
  end

  # データ通信
  def send(c)
    raise '実装してください'
  end

  def recv()
    raise '実装してください'
  end
end

class ModemImplementation
  include Modem

  def hangup
    p "#{self.class} #{__method__}"
  end
end

ModemImplementation.new.hangup

仮に、「接続を管理」する関数が影響を受けるような変更がされるなら、分離するべきです。

2つの役割が必ず同時に変更されるなら、分離してしまうと不必要に複雑になってしまいます。

「接続の管理」「データ通信」の2つの役割を分離する

test2.rb

module DataChannel
  def send(c)
    raise '実装してください'
  end

  def recv()
    raise '実装してください'
  end
end

module Connection
  # 接続の管理
  def dial(pno)
    raise '実装してください'
  end

  def hangup()
    raise '実装してください'
  end
end

class ModemImplementation2
  include DataChannel
  include Connection

  def hangup
    p "#{self.class} #{__method__}"
  end
end

ModemImplementation2.new.hangup

Ruby で class_eval を使ってみる

2019-07-20

やったこと

Ruby で class_eval を使ってみます。

確認環境

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

調査

test.rb

class Sample
end

Sample.class_eval %Q{
  def hoge
    p "Sample.class_eval"
    p "self.class: #{self.class}"
    p "__method__: #{__method__}"
  end
}

Sample.new.hoge

実行結果

$ ruby test.rb
"Sample.class_eval"
"self.class: Object"
"__method__: "

method は空になりました。

参考

Rails の ActiveRecord の update で validate が実行されるかを見てみる

2019-07-17

やったこと

Rails の ActiveRecord で update を実行するときに、 validate が呼び出されるのかを検証してみます。

確認環境

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

$ rails --version
Rails 5.2.3

調査

validate が呼び出されているかを調べる

app/models/task.rb

class Task < ApplicationRecord
  validate :hoge

  def hoge
    logger.debug("custom validate: #{__method__}")
  end
end

実行結果

$ rails c
Running via Spring preloader in process 29317
Loading development environment (Rails 5.2.3)
irb(main):001:0> Task.all
  Task Load (1.9ms)  SELECT  "tasks".* FROM "tasks" LIMIT ?  [["LIMIT", 11]]
=> #<ActiveRecord::Relation [#<Task id: 4, created_at: "2019-06-12 12:50:53", updated_at: "2019-06-12 12:50:53", name: "name1">, #<Task id: 5, created_at: "2019-06-12 12:52:31", updated_at: "2019-06-12 12:52:31", name: "name1">]>
irb(main):002:0> t = Task.find(4)
  Task Load (0.2ms)  SELECT  "tasks".* FROM "tasks" WHERE "tasks"."id" = ? LIMIT ?  [["id", 4], ["LIMIT", 1]]
=> #<Task id: 4, created_at: "2019-06-12 12:50:53", updated_at: "2019-06-12 12:50:53", name: "name1">
irb(main):003:0> t.update(name: "name22")
   (0.1ms)  begin transaction
custom validate: hoge
  Task Update (0.5ms)  UPDATE "tasks" SET "updated_at" = ?, "name" = ? WHERE "tasks"."id" = ?  [["updated_at", "2019-07-14 15:51:29.933901"], ["name", "name22"], ["id", 4]]
   (3.5ms)  commit transaction
=> true

update が実行されると validate も実行されていることが分かります。

validate の unique 制約が働くのか調べる

app/models/task.rb

class Task < ApplicationRecord
  validates :name , uniqueness: true, presence: true
  validate :hoge

  def hoge
    logger.debug("custom validate: #{__method__}")
  end
end

実行結果

$ rails c
Running via Spring preloader in process 30205
Loading development environment (Rails 5.2.3)
irb(main):001:0> Task.all
  Task Load (1.4ms)  SELECT  "tasks".* FROM "tasks" LIMIT ?  [["LIMIT", 11]]
=> #<ActiveRecord::Relation [#<Task id: 4, created_at: "2019-06-12 12:50:53", updated_at: "2019-07-14 16:01:58", name: "name2">, #<Task id: 5, created_at: "2019-06-12 12:52:31", updated_at: "2019-06-12 12:52:31", name: "name1">]>
irb(main):002:0> task = Task.find(4)
  Task Load (0.2ms)  SELECT  "tasks".* FROM "tasks" WHERE "tasks"."id" = ? LIMIT ?  [["id", 4], ["LIMIT", 1]]
=> #<Task id: 4, created_at: "2019-06-12 12:50:53", updated_at: "2019-07-14 16:01:58", name: "name2">
irb(main):003:0> task.update(name: "name1")
   (0.1ms)  begin transaction
  Task Exists (0.2ms)  SELECT  1 AS one FROM "tasks" WHERE "tasks"."name" = ? AND "tasks"."id" != ? LIMIT ?  [["name", "name1"], ["id", 4], ["LIMIT", 1]]
custom validate: hoge
   (0.1ms)  rollback transaction
=> false

unique 制約のバリデーションが効いていることが分かります。

参考

Ruby で etc モジュールを使ってみる

2019-07-17

やったこと

Ruby で etc モジュールを使ってみます。

確認環境

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

調査

etc モジュールとは

/etc に存在するデータベースから情報を得るためのモジュールです。

検証

$ irb
irb(main):001:0> require 'etc'
=> true
irb(main):002:0> Etc.uname
=> {:sysname=>"Darwin", :nodename=>"hogehoge-no-MacBook-Pro.local", :release=>"17.7.0", :version=>"Darwin Kernel Version 17.7.0: Wed Apr 24 21:17:24 PDT 2019; root:xnu-4570.71.45~1/RELEASE_X86_64", :machine=>"x86_64"}
irb(main):003:0> Etc.getlogin
=> "hogehoge"

※ ユーザー名を hogehoge に変更しています。

参考

Ruby で initialize が呼ばれる順番を調べる

2019-07-16

やったこと

Ruby で initialize が呼び出される順番を調べます。

確認環境

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

調査

module と 親クラスがある場合

test.rb

module SampleModule
  def initialize
    p "1: #{self.class} #{__method__}"
  end
end

class Parent
  def initialize
    p "2: #{self.class} #{__method__}"
  end
end

class Child < Parent
  include SampleModule

  def initialize
    super
    p "3: #{self.class} #{__method__}"
  end
end

出力結果

$ ruby test.rb
"1: Child initialize"
"3: Child initialize"

親クラスがある場合

test.rb

class Parent
  def initialize
    p "2: #{self.class} #{__method__}"
  end
end

class Child < Parent
  def initialize
    super
    p "3: #{self.class} #{__method__}"
  end
end

出力結果

$ ruby test.rb
"2: Child initialize"
"3: Child initialize"

module と親クラスが両方ある場合、super で呼び出されるのは module のメソッドであることが分かりました。