monolog

monora log #=> ものろーぐ

Tag Archives: Ruby

ICTSCのコンテストサイトを支えた技術

Programming

この記事は whywaita Advent Calendar 2020 の10日目の記事です。2週目です。来週何を書くか考えるだけで気が遠くなります。

昨日は @icchy さんで 「whywaitaであいうえお作文する」でした。タイトルだけでだいたい想像できますね。

なるほど。


@icchy さんのおすすめインターネットコンテンツは飲酒日記です。

閑話休題。
アドベントカレンダー、書くネタはあれど頭を使うものばかりで泣きそうになったので、とりあえず過去の下書きを漁っていたらタイトルだけ書かれたこの記事の下書きを見つけました。
最近思うこともあったので、すでに忘れ去られ、誰もが忘れたままでいたいと思っていたICTSCのコンテストサイトの歴史を紐解いてみたいと思います。
whyawitaさんとの関わりもあるし、whywaita Advent Calendar的には100点満点のネタですね。よろしくお願いします。

read more »

総資産を Dr.Wallet から Slack へポストするようにした

Programming

こんにちは。JST+11で生きているので昼です。
ところで最近は世界から10年遅れて Rails に入門したり、それとは関係なく Sinatra のアプリケーションに
RSpec を書いてテストの重要性を感じながら七夕に笹の葉ラプソディを見たりしています。10年前って単語がよく聞かれる今日このごろです。

皆さんはおそらく何らかのチームでのコミュニケーションに Slack を使っていて、総資産を Dr.Wallet で管理されていて (ここで読者の8割が脱落)、その総資産を逐次仲間に共有したいですよね! (残存者0)

で、やっぱり皆さんも共有したいでしょう、というわけで作りました。

read more »

shotgun じゃなくて rerun を使おうという話

Programming

Ruby で Rack アプリケーションを書いているときに、コード変更したら自動的にサーバー再起動したいという話。

今までは shotgun でやっていたのだけれど、これは毎回リクエストする度に変更の有無に関係なくサーバーを立ち上げ直すので、遅いという欠点があった。
副次的な問題として、better_errors で REPL が無効になるという欠点があった。(レスポンスを返すとそのコンテキストを捨ててしまうから?)

ずっと前からどうにかならないかなーと思っていたのでググったら rerun というものを見つけた。
Rack とか関係なくもっと汎用的なやつで、ファイル変更検知してサーバー上げ直すぞ! みたいなプロダクトらしい。

入れたら下のような感じで使える。便利。

RACK_ENV=development rerun -- rackup -o 127.0.0.1

調子に乗って通知有効化するぞ! というノリで terminal-notifier を入れてみたらサーバーが上がらなくなった。何事かと思ったら tmux 上で使おうとすると一癖あるらしく、こういうIssue が立っていたので適当に読んだら解決した。

要するに、brew なりなんなりで、reattach-to-user-namespace をインストールして、.tmux.conf に下を書き加えるという話。

set -g default-command "which reattach-to-user-namespace > /dev/null && reattach-to-user-namespace -l $SHELL || $SHELL -l"

再起動に掛かる時間が体感で倍ぐらいになったけれど、better_errors使えることで圧倒的効率アップみたいなところがあるので、トータルで幸福度が向上した気がする。

Sinatra Modular-Application で configure が上書きされる問題の対処

Programming

Ruby の Siantra で、Modular-Application を書いていたら良く分からない挙動にぶち当たって気が付いたら朝になっていたのでメモ。

app.rb

require_relative "hoge"

class App < Sinatra::Base
  configure do
    disable :protection
  end

  use HogeRoutes
end

hoge.rb

class HogeRoutes < Sinatra::Base
  get "/" do
     ...
  end
end

みたいな事をしていた。
disable :protection をしているのにどうしても Rack::Protection が有効になるので、どうしてこうなるんだとあちこちのコードを追いかけたりした結果、HogeRoutesApp とは別にもう一度 session, protections 等のセットアップが行われるので、以下のように、 use HogeRoutesconfigure より上に持ってくる必要があった。

app.rb

require_relative "hoge"

class App < Sinatra::Base
  use HogeRoutes

  configure do
    disable :protection
  end
end

HogeRoutes 内の configuredisable :protection とやってもいいが、こうするとクラスが増えた際にその分だけ書かないといけなくて大変。セッションみたいなアプリケーション全体で統一的な設定を持つ部分は親の App でやって良いんじゃないかと思う。

sinatra-activerecord で seed_fu を使ってみた

Programming

Sinatra で、sinatra-activerecord を使っているときに、$ rake db:seed すると、既に存在するレコードが重複登録される。

これ、とても一般的な問題で、 Rails だと、seed_fu というのを使って解決したりするらしい。

Rails (ActiveRecord 4.x) で動くなら Sinatra (sinatra-activerecord) でも問題なく動くとおもいきや、$ rake -T しても db:seed_fu が表示されない……

ソースやらなんやら見ながら唸っていたら、どうも Rake のタスク追加を、 Railtie を使ってやろうとしているところを発見した。
どうやら Rails だと、初期化時にここのコードが走るらしいのだけれど、Sinatra にそんなものはないので当然タスクは追加されない。

というわけで、Rakefile にベタ書きしてみる。
メインのアプリケーションソースが ./app.rb にあるということになっています。(適宜書き換えてください)
あと、なぜか <<< < に置き換えられたので修正してください。

namespace :db do
  desc < <-EOS Loads seed data for the current environment. It will look for ruby seed files in (settings.root)/db/fixtures/ and (settings.root)/db/fixtures/(settings.environment)/. By default it will load any ruby files found. You can filter the files loaded by passing in the FILTER environment variable with a comma-delimited list of patterns to include. Any files not matching the pattern will not be loaded. You can also change the directory where seed files are looked for with the FIXTURE_PATH environment variable. Examples: # default, to load all seed files for the current environment rake db:seed_fu # to load seed files matching orders or customers rake db:seed_fu FILTER=orders,customers # to load files from settings.root/features/fixtures rake db:seed_fu FIXTURE_PATH=features/fixtures EOS task :seed_fu => :environment do

    if ENV["FILTER"]
      filter = /#{ENV["FILTER"].gsub(/,/, "|")}/
    end

    if ENV["FIXTURE_PATH"]
      fixture_paths = [ENV["FIXTURE_PATH"], ENV["FIXTURE_PATH"] + "/" + settings.environment.to_s]
    end

    SeedFu.seed(fixture_paths, filter)
  end

  task :load_config do
    require "./app"
  end
end

Rake::Task["db:seed_fu"].enhance(["db:load_config"])

SeedFu.fixture_paths = [
  Pathname(settings.root).join("db/fixtures").to_s,
  Pathname(settings.root).join("db/fixtures/#{settings.environment}").to_s
]

コードとしては、seed_fu の rakeファイル を元に、sinatra-activerecord から、データベースの接続設定を拾ってくる部分を参考にしたりした。

Rake::Task["db:seed_fu"].enhance(["db:load_config"])

の部分がミソで、これでアプリケーションを通してデータベースに接続する必要がある。ここで2時間ぐらいハマった。