ためすう
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 が呼び出されるのかを検証してみます。
確認環境
$ 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 のメソッドであることが分かりました。