ためすう

Rails で member ルーティングを使ってみる

2019-08-04

やったこと

Rails で member ルーティングを使ってみます。

以下は Rails ガイドからの引用です。

デフォルトで作成されるRESTfulなルーティングは7つですが、7つでなければならないということはありません。必要であれば、コレクションやコレクションの各メンバーに対して適用されるリソースを追加することもできます。

確認環境

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

$ rails --version
Rails 5.2.3

調査

コード追加

config/routes.rb

Rails.application.routes.draw do

  resources :hello do
    get 'index', action: :index
    get '(/:id)/show2', action: :show2
    get 'show3', on: :member
  end
end

app/controllers/hello_controller.rb

class HelloController < ApplicationController
  def index
  end

  def show2
    render :json => {ver: 2, id: params[:hello_id]}
  end

  def show3
    render :json => {ver: 3, id: params[:id]}
  end
end

結果を確認する

ルーティングを確認してみる

$ rails routes | grep -E "/hello" | grep "show."
                          GET    /hello/:hello_id(/:id)/show2(.:format)                                                   hello#show2
              show3_hello GET    /hello/:id/show3(.:format)                                                               hello#show3

パラメータの取得方法が変わっています。

member ルーティングでは id となっています。

下記の URL にアクセスすると、パラメータが取得できていることが確認できます。

http://localhost:3000/hello/1000/show2

http://localhost:3000/hello/1000/show3

参考

Rails で find_each、find_in_batches を使ってみる

2019-08-04

やったこと

Rails で大量のデータを処理するときに使う

  • find_each
  • find_in_batches

を使ってみます。

確認環境

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

$ rails --version
Rails 5.2.3

調査

find_each

$ rails c
...

irb(main):005:0> Task.find_each(batch_size: 1){ |task| p task }
  Task Load (0.1ms)  SELECT  "tasks".* FROM "tasks" ORDER BY "tasks"."id" ASC LIMIT ?  [["LIMIT", 1]]
#<Task id: 4, created_at: "2019-06-12 12:50:53", updated_at: "2019-07-14 16:01:58", name: "name2">
  Task Load (0.1ms)  SELECT  "tasks".* FROM "tasks" WHERE "tasks"."id" > ? ORDER BY "tasks"."id" ASC LIMIT ?  [["id", 4], ["LIMIT", 1]]
#<Task id: 5, created_at: "2019-06-12 12:52:31", updated_at: "2019-06-12 12:52:31", name: "name1">
  Task Load (0.1ms)  SELECT  "tasks".* FROM "tasks" WHERE "tasks"."id" > ? ORDER BY "tasks"."id" ASC LIMIT ?  [["id", 5], ["LIMIT", 1]]
=> nil

find_in_batches

$ rails c
...

irb(main):006:0> Task.find_in_batches(batch_size: 1){ |task| p task }
  Task Load (0.1ms)  SELECT  "tasks".* FROM "tasks" ORDER BY "tasks"."id" ASC LIMIT ?  [["LIMIT", 1]]
[#<Task id: 4, created_at: "2019-06-12 12:50:53", updated_at: "2019-07-14 16:01:58", name: "name2">]
  Task Load (0.1ms)  SELECT  "tasks".* FROM "tasks" WHERE "tasks"."id" > ? ORDER BY "tasks"."id" ASC LIMIT ?  [["id", 4], ["LIMIT", 1]]
[#<Task id: 5, created_at: "2019-06-12 12:52:31", updated_at: "2019-06-12 12:52:31", name: "name1">]
  Task Load (0.1ms)  SELECT  "tasks".* FROM "tasks" WHERE "tasks"."id" > ? ORDER BY "tasks"."id" ASC LIMIT ?  [["id", 5], ["LIMIT", 1]]
=> nil

参考

json の テストで gem の json_expressions を使ってみる

2019-07-29

やったこと

rspec で json_expressions を使ってみます。

利用シーンとしては、Web API で返却される json の型をチェックする時などです。

確認環境

$ 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

gem 'json_expressions'
$ bundle install

テスト対象の処理

app/controllers/users_controller.rb

class UsersController < ApplicationController
  def show
    data = {
      user: {
        id: 1,
        type: 'userType1',
        type2: 'userType2',
        point: 2300,
        is_valid: true
      }
    }
    render :json => data
  end
end

rspec を書く

spec/controllers/users_controller_spec.rb

require 'rails_helper'
require 'json_expressions/rspec'

module Boolean; end
class TrueClass; include Boolean; end
class FalseClass; include Boolean; end

RSpec.describe UsersController, type: :controller do
  describe "GET #show" do
    it "returns a user" do
      pattern = {
        user: {
          id: Integer,
          type: String,
          point: Integer,
          is_valid: Boolean,
        }.ignore_extra_keys!
      }

      get :show
      expect(response.body).to match_json_expression(pattern)
    end
  end
end

ignore_extra_keys! を指定することでテスト対象のキーを絞り込むことができます。

Boolean かどうかのテストをするための対応も必要でした。

参考

RSpec で shared_context を使ってみる

2019-07-29

やったこと

rspec で shared_context を使ってみます。

確認環境

$ 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/task10_spec.rb

require 'rails_helper'

shared_examples 'Example Login' do
  it 'should be hogehoge' do
  end
end

RSpec.describe Task, type: :model do

  context '例) ログインしているユーザー' do
    it_behaves_like 'Example Login'
  end
end

出力結果

$ rspec spec/models/task10_spec.rb

Task
  例) ログインしているユーザー
    behaves like Example Login
      should be hogehoge

Finished in 0.0028 seconds (files took 3.85 seconds to load)
1 example, 0 failures

エイリアス

  • shared_examples_for
  • shared_context

これらのメソッドは、shared_examples のエイリアスです。

参考

rspec で and_call_original を使ってみる

2019-07-27

やったこと

rspec で and_call_original を使ってみます。

確認環境

$ 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/task9_spec.rb

require 'rails_helper'

class Sample
  attr_reader :count
  def initialize
    @count = 0
  end

  def increment
    @count += 1
  end
end

RSpec.describe Task, type: :model do
  it '呼び出しているかどうかのテスト' do
    sample = Sample.new
    expect(sample).to receive(:increment)

    expect(sample.count).to eq(0)
    # 実際に呼び出してはいない
    sample.increment
    expect(sample.count).to eq(0)
  end

  it '実際に呼び出すテスト' do
    sample = Sample.new
    expect(sample).to receive(:increment).and_call_original

    expect(sample.count).to eq(0)
    sample.increment
    expect(sample.count).to eq(1)
  end
end

出力結果

$ rspec spec/models/task9_spec.rb

Task
  呼び出しているかどうかのテスト
  実際に呼び出すテスト

Finished in 0.00736 seconds (files took 1.75 seconds to load)
2 examples, 0 failures

and_call_original を使うと実際のメソッドが呼び出されていることが分かります。

参考

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)

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

参考