脳汁portal

アメリカ在住(だった)新米エンジニアがその日学んだIT知識を書き綴るブログ

Rails(ActiveRecord)に関して

Active Recordの値の取り扱いに関して

こんなレコードがあるとして

mysql> select id,name from users;
+----+---------+
| id | name    |
+----+---------+
|  1 | foo     |
|  2 | bar     |
|  3 | fizz    |
+----+---------+

これをActiveRecord経由で取得した場合どういうデータ形式になったりメソッドが使えるかという話

find_byだと

Userインスタンスが返ってくる
> User.select(:id, :name).find_by(id: 1)
=> #<User id: 1, name: "foo">
それぞれの値の取得方法
> user = User.select(:id, :name).find_by(id: 1)
=> #<User id: 1, name: "foo">

> user.id
=> 1
> user.name
=> "foo"

> user[:id]
=> 1
> user[:name]
=> "foo"
to_aメソッドやeachは使えない
> User.select(:id, :name).find_by(id: 1).to_a
Traceback (most recent call last):
        9: from script/rails:8:in `<main>'
        8: from script/rails:8:in `require'
        .
        .
        .

whereの場合

ActiveRecord::Relationが返ってくる
# ActiveRecord::Relationとして返ってくる
> User.select(:id, :name).where(id: [1,3])
=> #<ActiveRecord::Relation [#<User id: 1, name: "foo">, #<User id: 3, name: "fizz">]>
> User.select(:id, :name).where(id: [1,3]).class
=> User::ActiveRecord_Relation

# to_aにすると配列として返ってくる
> User.select(:id, :name).where(id: [1,3]).to_a
=> [#<User id: 1, name: "foo">, #<User id: 3, name: "fizz">]
irb(main):315:0> User.select(:id, :name).where(id: [1,3]).to_a.class
=> Array
それぞれの値の取得方法
# 配列のように指定ができる
> User.select(:id, :name).where(id: [1,3])[0]
=> #<User id: 1, name: "foo">
> User.select(:id, :name).where(id: [1,3])[1]
=> #<User id: 3, name: "fizz">

# その上で値が取得できる
> User.select(:id, :name).where(id: [1,3])[0].name
=> "foo"
> User.select(:id, :name).where(id: [1,3])[1].name
=> "fizz"
ActiveRecord::Relationでも配列でもeachが使える(取得できるのはuserインスタンス)
# ActiveRecord::Relation
> User.select(:id, :name).where(id: [1,3]).each do |user|
>     puts user
> end
#<User:0x00005560a6bd4d20>
#<User:0x00005560a6bd46b8>

# Array
> User.select(:id, :name).where(id: [1,3]).to_a.each do |user|
>     puts user
> end
#<User:0x00005560a6b3aef0>
#<User:0x00005560a6b3a6a8>

ubuntu16.04にrbenvでrubyをインストールする

# library install and update
sudo apt-get update
cd 
sudo apt-get install git build-essential libssl-dev libreadline-dev

vi ~/.profile
### 以下を末尾に追加 ###
export PATH="$HOME/.rbenv/bin:$PATH"
eval "$(rbenv init -)"
### ここまで ###

source ~/.profile

# installできるversionのチェック
rbenv install --list

# install
rbenv install 2.5.1
rbenv rehash

# globalへの設定&確認
rbenv global 2.5.1
ruby -v

RubyのThreadのステータスに関して

class Thread (Ruby 2.4.0)
instance method Thread#status (Ruby 2.4.0)
instance method Thread#alive? (Ruby 2.4.0)

Rubyのスレッドに関して各ケースのステータスまとめ

各項目がとる値

  • thread object(thread.inspect)
    • run
    • sleep
    • aborting
    • dead
  • thread.status
    • run
    • sleep
    • false
    • nil
  • thread.alive?
    • true
    • false

調査

通常時(スレッドが生きているとき)

ソース
t1 = Thread.start{
  loop do
    sleep 1
  end
}

loop do
  p t1 # run, sleep, aborting, dead
  puts t1.status || t1.status.class # run, sleep, false, nil
  puts t1.alive? # true, false
  puts "--------------------------------"
  sleep 1
end
実行結果
#<Thread:0x55e80d30 sleep>
run
true
--------------------------------
#<Thread:0x55e80d30 sleep>
run
true
--------------------------------
#<Thread:0x55e80d30 sleep>
run
true
--------------------------------
各ステータス
  • thread object : (run), sleep
  • thread.status : run, (sleep)
  • thread.alive? : true

正常終了時

ソース
t1 = Thread.start{
  2.times{|n|
    sleep 1
    puts n+1
  }
}

loop do
  p t1
  puts t1.status || t1.status.class # run, sleep, aborting, false, nil
  puts t1.alive? # true, false
  puts "--------------------------------"
  sleep 1
end
実行結果
#<Thread:0x566a0c48 run>
sleep
true
--------------------------------
1
#<Thread:0x566a0c48 sleep>
sleep
true
--------------------------------
2
#<Thread:0x566a0c48 dead>
FalseClass
false
--------------------------------
#<Thread:0x566a0c48 dead>
FalseClass
false
--------------------------------
#<Thread:0x566a0c48 dead>
FalseClass
false
--------------------------------
各ステータス
  • thread object : dead
  • thread.status : false
  • thread.alive? : false

異常終了時

ソース
t1 = Thread.start{
  2.times{|n|
    sleep 1
    puts n+1
  }
  raise
}

loop do
  p t1
  puts t1.status || t1.status.class # run, sleep, aborting, false, nil
  puts t1.alive? # true, false
  puts "--------------------------------"
  sleep 1
end
実行結果
#<Thread:0x558e8bf0 run>
sleep
true
--------------------------------
#<Thread:0x558e8bf0 run>
sleep
1
true
--------------------------------
#<Thread:0x558e8bf0 run>
2
sleep
false
--------------------------------
#<Thread:0x558e8bf0 dead>
NilClass
false
--------------------------------
#<Thread:0x558e8bf0 dead>
NilClass
false
各ステータス
  • thread object : dead
  • thread.status : nil
  • thread.alive? : false

まとめると

  • thread.statusはスレッドが生きている間はrunかsleepで、正常終了するとfalseになり、異常終了するとnilになる
  • thread.alive?はスレッドが生きている間はtrueで、終了すると正常・異常に関わらずfalseになる
  • thread情報を直接見ると、スレッドが生きている場合はrunかsleepで、終了処理中はabortingになり、完全に終了するとdeadになる

Rubyでシリアル通信する方法(serialport gem)

Rubyでシリアル通信する場合は、serialport gemを使うと簡単にできます。

install serial port

$ gem install serialport

How to Use

require 'serialport'

sp = SerialPort.new('/dev/ttyS0', 115200, 8, 1, 0) # device, rate, data, stop, parity

# 送信
sp.puts("foobar")

# 受信
sp.gets
sp.readline.chomp.strip # こっちだと空白とか余分な情報をそぎ落としてくれる

Rubyの配列に文字列として入っている数字をFixnumに一括置換する方法

eachで回して一つ一つto_iして上書きしてもいいですが、以下のようにすると1行で書けます

方法

配列.map(&:to_i)
  • map!で破壊的に上書き

検証

ソースコード
array = ["1", "2", "3", "0", "10\r\n", nil, "", "-5"]

array.map(&:to_i).each{|val|
  puts "#{val}: #{val.class}"
}
実行結果
1: Fixnum
2: Fixnum
3: Fixnum
0: Fixnum
10: Fixnum
0: Fixnum
0: Fixnum
-5: Fixnum

railsで対応したcontrollerのjsやcssだけ読みこむ方法

Railsではassetsディレクトリ以下にcssファイルやjsファイルを置くとそれらを全て自動で読み込んでくれますが、それを無効にしてcontrollerに対応するcssやjsファイルだけ読み込ませるように変更できます

方法

1. 全ファイルの読み込み設定を削除する
  • app/assets/stylesheets/application.css
  • app/assets/javascripts/application.js

上記のファイルの以下の記述を削除します

//= require_tree .
2. 対応するcontrollerを読み込む設定を記述する
  • app/views/layouts/application.html.erb

layoutファイルに以下のように記述を追加する

<!DOCTYPE html>
<html>
<head>
  .
  .

  <%= stylesheet_link_tag controller.controller_name , media: "all" %>
  .
  .
</head>
.
.
.
  <%= javascript_include_tag controller.controller_name %>
</body>
</html>