コード日進月歩

しんくうの技術的な小話、メモ、つれづれ、など

Rubyでカウントアップ/ダウンをするメソッドあれこれ

逆引き的にお送りします。

環境

$ ruby -v
ruby 2.6.2p47 (2019-03-13 revision 67232) [x86_64-darwin18]

メソッド

一定回数やる場合の times

x回繰り返すというときにつかえるもの、indexに入るのは0から

5.times { |n| p n }
# 0
# 1
# 2
# 3
# 4

指定した整数値から1ずつカウントアップする upto

決まった数から1ずつ挙げていきたい場合に使うupto

5.upto(7) { |n| p n }
# 5
# 6
# 7

なお、数が既に満たされている場合は何も実行されない

5.upto(4) { |n| p n }
# ブロック内のものは実行されない

指定した整数値から1ずつカウントダウンする downto

決まった数から1ずつ挙げていきたい場合に使う downto。uptoの逆。

10.downto(7) { |n| p n }
10
9
8
7

指定した数値から増加源させたい場合につかう step

細かく値を調整したいときに使える step 。incrementalする値も選べる。

5.step(6,0.5) { |n| p n }
# 5.0
# 5.5
# 6.0

小数値なども設定できるので、ループで取得できる値には気をつけること

# 0.3刻みなので、最後が4になるわけではない
5.step(4,-0.3) { |n| p n }
# 5.0
# 4.7
# 4.4
# 4.1

参考リンク

『Unity++ 〜ショートセッション勉強会 presented by Unity部〜』に行ってきたよメモ

Unity++ 〜ショートセッション勉強会 presented by Unity部〜 - Unity Meetup に言ってきたのでそれのメモ

各発表の感想

※資料スライドは見つけたら貼ります。


Democratized Unity Package Manager

twitter.com

感想

  • Unityでもパッケージ管理かぁ…!と思ったらnpmのフォーマットに乗っかるという手法はびっくり
    • でもよく考えたらcocoapodsもRubyのgem踏襲してるし似たようなものかとも思ったり
  • ゲーム開発ってクローズドにライブラリ管理する文化がありそうだからそういうところではとても役に立ちそう。かつネット上を毎度参照だとサーバが落ちているときに対処できないのでそこらへんのローカルコピーを持つみたいな対策も取れそう
  • publicでライブラリの提供ができるといいなと思う半面、アップデートが難しいゲームというジャンルで悪意のあるコードが入ると手直し大変かもなと思ったり(npmではトラブルあったりしたので)

関連リンク


よーし、パパ Cinemachineを2Dプロジェクトに適応して遊んじゃうぞー

感想

  • カメラのメタ的な考え方が盛り込まれた機能だな…と思ったし2Dのカメラワークってここまでラッピングしてくれるんだという感じがした
  • モバイルでも大丈夫なのかなこれとか思ったけど、いまのモバイル性能高いからそこまで心配ないのかな…
  • 本筋ではないけど「いい感じ」ってどこでも起きる話だよね…とか思った。

関連リンク


アクションゲームにおけるポーズ系演出の難しさと解決法

スライドは公開されたら貼ります

感想

  • 特定の対象だけ全体の時間の概念から切り離す方法の難しさと、それを解決するためのAssetの紹介
  • 対象オブジェクトが増えれば増えるだけ管理も煩雑にはなりますよね…とは思った
  • 対象ごとに時間の管理をするので、単純に考えるとそれだけ監視しなきゃいけなくなるのでそこらへんのパフォーマンス差異みたいのは気になった

関連リンク


Preview機能のプレビュー 公式Localizationパッケージの今

感想

  • 公式じゃない海外のAndroidマーケットに出せるようになったりするので、その結果ローカライズ増えるでしょ…!?からのローカライズ
  • テキストはできるのはもちろん、音声や画像に対してもマッピングができるの素晴らしいと思った
  • テキストは結構言語によって左よりや右よりなど阿鼻叫喚ポイントあるらしいので、音声とかのほうが適用はしやすそう。(Assetの関連性も巻き込めればだけど)

関連リンク


Unity開発者が知っておきたい.NETのこと

感想

  • Unityで使える、C#と.NETの話。
  • Untiy側で使える.NETの機能がもともと知ってるひとじゃないとわかりにくい部分があるのでそこをサポートする話でした。
  • Microsoft系言語は全然業務で触れてきてないのもあり、歴史的経緯みたいなしがらみのようなものも感じたし、直感的にわかりづらいな…と思った。

関連リンク


Unity サウンドTips 2019

感想

  • Unityのサウンド周りの話、主にご自身が発表されてきた振り返りとVRやADX2のお話。
  • 3Dのゲームになるとだんだんリアル世界の音声ミキシングと話がおなじになってくるんだな…と当たり前ながら感じてしまった。
  • 反響の計算とかライティング並に計算量掛かりそうなので、だましだましの手法は出てきそう
  • 全然本筋とは関係ないけど、実際に発表しながら手直しするあたり、Googleスライドの本気を見た

関連リンク


UniTask入門

感想

  • Unityに最適化されたTaskクラスであるUniTaskの話。
  • バックエンドサーバエンジニアやってると非同期処理って全然やらなくなるので、そこらへんと照らし合わせながら聞いてたけど、普通にそんな人でも直感理解しやすいので、そういう意味で使いやすさを感じた。
  • async/awaitはどの言語でも概念が浸透しつつあるのでちゃんと学び直したいなと思った

関連リンク


全体を通しての感想

  • Unity全然やれてないので勉強会でキャッチアップするマン(1年ぶり3度目)なので大変有意義な勉強会だった
  • 2Dゲームのつくりやすさは一昔前に比べたら断然あがってるし、C#という言語の使い勝手も格段にアップしてるので、普通にサンプルゲーム的なものを試作する時間を取りたいな…と思った
  • Unityで使われている概念は一定JavaScript世界観でも使えるので逆輸入する意味でも勉強するのアリだなと感じた

Rubyでeach.with_indexを使うと n+1みたいなことをしなくてもいい感じに1からはじまる値が取得ができる

配列の長さが個数を兼ねているときによく考えるネタ。

環境

$ ruby -v
ruby 2.5.0p0 (2017-12-25 revision 61468) [x86_64-darwin18]

実例

要件

配列に画像のファイル名が入っているので No.1:添字0の画像名No2:添字1の画像名 というように表示したい

対象となる配列は以下

file_names = ["pictureA.jpg","pictureB.jpg","example.gif"]

愚直なやり方

each_with_indeで回す

file_names.each_with_index { |name, index| p "No.#{index+1}:#{name}" }
"No.1:pictureA.jpg"
"No.2:pictureB.jpg"
"No.3:example.gif"

ただしこうすると index + 1 という感じで0から始まるという制約での計算となりもにゃっとする。

eachのwith_indexを使う考え方

eachのメソッドに with_index というのがある

生成時のパラメータに従って、要素にインデックスを添えて繰り返します。 インデックスは offset から始まります。 - instance method Enumerator#with_index (Ruby 2.6.0)

eachでアイテムをセットしつつ、オフセット数値から始まるインデックスを渡す。

file_names.each.with_index(1) { |name, index| p "No.#{index}:#{name}" }
"No.1:pictureA.jpg"
"No.2:pictureB.jpg"
"No.3:example.gif"

という感じで要素とイテレーションする数字を分離して使えるので直感的にかけたりする。

参考リンク

Excel/スプレッドシートで日付に対して月数で加減算するときはEDATEを使うと楽

突然のスプレッドシート小ネタ

利用ケース

スプレッドシートで日付を加減算するのは 整数値 を足せば勝手に解釈してくれる

f:id:shinkufencer:20190719093002p:plain
日付フォーマットに対して整数値分、日付の加減算をしてくれる

ただし、月を計算する場合は日での加減算だとブレが出てしまうので そういう場合に使うのが EDATE

使い方

=EDATE(対象値, 加算したい月数)

で使える

実例

下記のように値をしてすればその後の月が出てくる

f:id:shinkufencer:20190719093116p:plain

もし過去の月を指定したい場合はマイナスを使えばOK

f:id:shinkufencer:20190719093129p:plain

参考リンク

CircleCIでrubyのイメージを使っている際にmysql-clientがなくてエラーになってしまう場合はdefault-mysql-clientを入れてあげると解決できる

時事ネタ、かつ暫定的なトラブルシュート

環境

  • CiecleCI (version2) でCIを動かしている
    • Railsアプリ
    • bundle installなどを.circleci/config.ymlでやってる
    • DBはMySQL
    • JSのコードも有るので使っていたイメージは circleci/ruby:2.6.3-node-browsers

発端

とあるタイミングから動いていたCIが突然失敗するようになった、エラーとしては

rake aborted!
LoadError: libmariadbclient.so.18: cannot open shared object file: No such file or directory - /home/circleci/rails_app/vendor/bundle/ruby/2.6.0/gems/mysql2-0.5.2/lib/mysql2/mysql2.so

というようにMySQLになにかしようとしたらclientがないよエラー

原因

  • Debian GNU/Linux 10 (buster) からはmysql-clientがなくなった
  • circleciで配布しているイメージでDebianOSを指定しないタグを使っているとよしなにバージョンアップしている

ということでこの2つの合わせわざが起こした事象の様子

参考ツイート

解決策

  • default-mysql-clientを入れる
  • その後にbundle installをかけてmysql2のgemで正しく紐付けてもらう

なのでstepとして

- run:
    name: default mysql client install
    command: |
      sudo apt update
      sudo apt-get install default-mysql-client
- run:
    name: bundle Install
    command: bundle install --path vendor/bundle

みたいな順番で対処すれば解決

参考サイト

Railsにおける未保存状態のリレーションモデルのつくりかた

リレーションするモデルも一気に保存したい、という場合の逆引きマニュアル的なもの

環境

$ bin/rails -v
Rails 5.2.2

やり方

has_many の場合と has_one で書き方が違う

has_manyの場合

{{has_manyをつけたモデルのインスタンス}}.{{belongs_toのモデル名の単数}}.build

has_oneの場合

{{has_oneをつけたモデルのインスタンス}}.build_{{belongs_toのモデル名の単数}}

こんなモデルがある場合

class User < ApplicationRecord
  has_many :message
  has_one :user_profile
end
class Message < ApplicationRecord
  belongs_to :user
end
class UserProfile < ApplicationRecord
  belongs_to :user
end

以下のように使う

user = User.new(name: "KenShiro")

user.message.build(name:"Hello!")
# => #<Message id: nil, name: "Hello!", user_id: nil, created_at: nil, updated_at: nil>

user.build_user_profile(age:10)
# => #<UserProfile id: nil, user_id: nil, age: 10, created_at: nil, updated_at: nil>

こんな感じで未保存のモデルが作られるので、userをsaveすれば連動して全てのレコードが作られる

参考サイト

Rubyの and と && は使い方によって優先度の影響で振る舞いが変わるので気をつける

DoubleRenderError避けに使う書き方で render :hoge and return みたいになぜandを使うのかという話。

実例

たとえばこんな感じで test.rb を作る

def normal(val)
  p val and return
  p "end of normal"
end

def shortcut(val)
  p val && return
  p "end of shortcut"
end

normal("hello")
shortcut("hello hello")

期待値として

hello
hello hello

と出てきてほしいが

$ ruby test.rb 
"hello"
$

という感じで終わる

こうなる原理

andは&&に比べて 優先順位の低い演算子 と説明がある

左辺を評価し、結果が偽であった場合はその値(つまり nil か false) を返します。左辺の評価結果が真であった場合には 右辺を評価しその結果を返します。 and は同じ働きをする優先順位の低い演算子です。 - 演算子式 (Ruby 2.6.0) - and

そのためメソッド呼び出しの括弧を省略すると解釈が変わる

p val and return
# 以下と同義
p(val) and return
p val && return
# 以下と同義
p(val && return)

そのため、後者はval && return が実行されるので、右式のreturnが評価され、pが実行される前に終わる

参考サイト