Rails + Semantic UIでmultiple select

Rails 5でsemantic-uiのmultipleなselectを使っているときに、初期値としてselectedされた値が表示されずに困っていた。 これはStackoverflowに書いてあった解決策だが、一旦option文のselectedを削除してからsemantic-uiのdropdown関数を呼び出しjavascriptからset selectedして、最後にoption文のseletctedを追加して元に戻しておく、というwalkaroundで解決した。以下に、coffeescript版を掲載しておく。

$(document).on 'ready turbolinks:load', ->
  $('.ui.dropdown').each ->
    $that = $(this)
    values = $that.val()
    $('option', $that).each ->
      $(this).removeAttr 'selected'
      return
    $that.dropdown 'set selected', values
    $('option', $that).each ->
      curr_value = $(this).val()
      i = 0
      while i < values.length
        if values[i] == curr_value
          $(this).attr 'selected', 'selected'
        i++
      return

で、これで解決と言いたいところだが、もう一工夫必要だった。selectedされてない場合はdropdown関数を呼ぶだけにすべき。

$(document).on 'ready turbolinks:load', ->
  $('.ui.dropdown').each ->
    $that = $(this)
    if $that.attr('multiple') && $('option[selected]', $that).length > 0
      values = $that.val()
      $('option', $that).each ->
        $(this).removeAttr 'selected'
      $that.dropdown 'set selected', values
      $('option', $that).each ->
        curr_value = $(this).val()
        i = 0
        while i < values.length
          if values[i] == curr_value
            $(this).attr 'selected', 'selected'
          i++
    else
      $(this).dropdown()

参考 jquery - Semantic UI: Multi Select Dropdown pre-select values - Stack Overflow

ActionMailerとMS Exchange server

RailsのActionMailerをMS Exchange serverで使うには。

Gemfileに

gem "ruby-ntlm

config/environment.rbで

 require 'ntlm/smtp'

config/environments/production.rbでメールサーバの設定

   config.action_mailer.delivery_method = :smtp
   config.action_mailer.smtp_settings = {
     address:              'mailserver.com',
     port:                 25,
     domain:               'mail.com',
     user_name:            'username',
     password:             'password',
     authentication:       :ntlm,
     enable_starttls_auto: false
   }

世界最長の吊り橋

7月にオープンしたスイスにある世界最長の吊り橋Europabrücke(ヨーロッパ橋)に行ってきたので、情報をまとめておく。まだ日本語情報はなかったし、英語でもニュース記事しかなたったので。行ったのは8月末。

場所

マッターホルンで有名なスイス南部の街、ツェルマットから電車で2駅15分程度のランダが最寄り駅。通常の観光であればツェルマットに宿泊して、ランダまで電車で移動するのが良いと思う。ランダは吊り橋以外には何もなさそうで、駅前に何もないし、無人駅だったとおもう。トイレはあった。切符はツェルマットからランダまでの往復を先に買っておいた方が良い。

f:id:eswai:20170825083214j:plain

ヨーロッパ橋まで

今回は次のサイトのコースを参考に吊り橋まで行って、ヨーロッパヒュッテには寄らずに戻った。

www.zermatt.ch

駅に降りたら山に向かって右に進んで行くが、あとは白の標識に従っていけばいい。橋ができたばかりなので、黄色の標識に追加して白の標識が後付けされている。自分はGPSで確認しながら進んだ。 ヨーロッパ橋までのアプローチは2つのセクションに分けられる前半2.3kmの激坂区間と、後半1kmの比較的歩きやすい区間。前半は駅からランダの街を抜けて登山道に入って行くが、ランダの街中からすでに激坂で、2.3kmで550m登る平均勾配なんと24%。とにかくコンスタントに登るので、休憩どころはない。心が折れそうになる。 少なくとも靴だけはちゃんとしたものは履いていかないとつらい。晴天でドライだったが、森林で直射日光はほとんどないので、快適。汗を発散する服装であればokと思う。 ランダ駅で降りたのは自分たちの他に3人1組だけだったけど、後から続々登って来て抜かれて行った。我々以外は欧米人で、もっと早いペースで登っているし、かなりラフな格好。おばちゃんでも日本人男性くらいのペースで歩くのでパワーが違う。

f:id:eswai:20170825090936j:plain f:id:eswai:20170825093820j:plain f:id:eswai:20170825100641j:plain f:id:eswai:20170825100720j:plain

後半は勾配1%の快適なハイキングコース。特筆すべき点はない。

f:id:eswai:20170825102833j:plain

両親と一緒だったので休憩しながらゆっくりペース。前半区間を1.5時間、後半区間を40分で歩いた。60代女性でも完走したので、とんでもないコースではないが、誰にでも勧められる気軽な観光地ではない。少なくとも日本で山に行ったことがある人でないと、途中リタイアを余儀なくされるかも。 ここまで、全く吊り橋は見えず、突然目の前に現れるので感動はひとしお。

ヨーロッパ橋

500mあるので渡るのに10分くらいかかる。橋はギリギリすれ違えるくらいの幅しかないが、その方が両手で橋を持てるので安心。当日、風はほとんどなかったのもあるけど、思ったほど揺れない。それでもゆらゆらしてるので少し怖い。片側は山の斜面なので、空中を歩いてる感覚はなく、視覚的な恐怖はほとんどない。下はグレーチングなので下は見えるが、地面からの高さもそれほどない。中央から雪をかぶった山が左手に見えるのがハイライト。でもマッターホルンは全く見えません。 同時に渡っているのは大体10人以下だったし瞬間的には自分たちだけのこともあった。まだ、できたばかりだし、アプローチの難易度は高いし、まだまだ観光地化はしてない感じ。人が増えると景色は変わるだろう。 橋の両端に少し休憩できるスペースがあり、特に橋を渡ってからはテーブルや斜面など良い休憩場所があるので、サンドイッチでも持っていけば良い。橋の眺めも渡ってからの方がいい。20人くらいの人が常に休憩していた。TVクルーもいて何か撮影していた。 この橋はスポンサーからの資金提供で作られたようで、橋の手前に看板があるが控えめ。メインスポンサーのCharles Kuonenホテルの名前を冠して、Charles Kuonen Hängebrücke (Charles Kuonen suspension bridge)というのが正式名称みたい。

f:id:eswai:20170825104149j:plain f:id:eswai:20170825104410j:plain f:id:eswai:20170825110506j:plain f:id:eswai:20170825110532j:plain f:id:eswai:20170825111710j:plain f:id:eswai:20170825114802j:plain

橋からの戻り

戻りは下り2.7kmで640m下るので平均24%の下り。岩も多く足場は悪いところが多い。気をつけないと足をくじいたりしかねない。1時間45分くらいで休憩しながら下った。たまたま電車が止まっていたのでツェルマット行きに飛び乗った。しっかり車掌が検札に来て、吊り橋に行って来たのか、と聞かれたので、地元でも注目スポット。 ランダの間にも小さな村だが、趣があって通り抜けるだけでもいい。まだ、観光の準備ができてない感じ。

f:id:eswai:20170825120300j:plain f:id:eswai:20170825120809j:plain f:id:eswai:20170825121419j:plain f:id:eswai:20170825132526j:plain f:id:eswai:20170825133430j:plain

その他

逆回りのコースはやめた方がいい。足場の悪いきつい登りを登るのはつらいし、何より登る前からチラチラ橋が見えてるので感動が薄い。逆回りしている人もいるけど多くはない。 登った満足感と、目前に突然現れる長い吊り橋、ゆっくり渡れる吊り橋、眺め、渡ってからの休憩スポット、など総じて満足感は高い。天気が良ければおすすめ。 観光地と呼ぶにはアプローチの難易度が高い。10年後にはロープウェイができてるかも。

最後に筆者は英語と少しのドイツ語がわかり、スイスには何度も行ったことがあって、ヨーロッパの電車移動も慣れているが、ハイキング初心者である前提と記載しておく。

ツール

  • GoPro Session バックパックの肩ストラップにGoPro Sessionをマウントして、2秒に1回のタイムラプスを取り続けた。SDカードは64GBで1日取れるが、バッテリーが全く持たないので、常にモバイルバッテリーから給電しながら記録した。記事の写真は全てGoProで撮ったもの。

  • iPhone + Geographica GPSがないと自分がどこにいるのかわからないので迷わないためにも必要。Google Mapsでもいいけど、標高みたいし、ログを取りたいのでGeographicaを購入した。

  • Swisscom prepaid SIM 1日2CHFでデータ通信が使い放題(4GB/月で減速のキャップあり)。LockされてないiPhone 6Sに入れて使った。

  • SBB Mobile アプリ スイスの電車の切符はアプリで買える。クレジットカード支払いできるので、電車移動するときは必須。検札に来たらチケットのバーコードを見せればOK。

  • MyGPSFiles 記録したGPXファイルは以下のサイトで可視化しみた。 MyGPSFiles

Redmine + view customize pluginで連続タスク入力を楽に

Redmineを使い始めたのですが、最初にどんどんタスクを入力したいんだけど、バージョンとか親タスクとか入力が面倒だし、入力を忘れるとガントチャートで変なところに表示されるので、テンポ良く入力できませんでした。 View customize pluginを使って、issue画面に、その次に続くタスクを入力するためのリンクを作ることにしました。versionと親idは同じ、開始日・終了日は前のタスクの終了日をコピーします。関連付けまでしてませんが、できるはず。 Redmineのversionは3.3.0です。

github.com

Futureパターン2

concurrent-rubyをつかうとfutureパターンが、かなりきれいに書ける。

github.com

require 'concurrent-edge'

Concurrent.future {
  raise "exception" if [true, false].sample
  true
}.then {|m|
  puts "succeed #{m}"  # 成功した時の処理、viewになげたり
}.rescue{|m|
  puts "failed #{m}" # 失敗した時の処理
}.then{|m|
  puts "finished" # finalize 
}

sleep 0.1

SlimでHTMLメールを送る

HTMLメールをrubyで送るのにslimテンプレートエンジンを使いたくて。

require 'mail'
require 'slim'

mail = Mail.new do
  from = 'foo@example.net'
  to = 'bar@example.net'
  subject = 'html mail'
end

@name1 = 'Sherlock Holmes'
@name2 = 'John Watson'
mail.html_part = Slim::Template.new('template.slim').render(self)

puts mail.to_s

template.slim

p =@name1 + ' is a private detective'
p =@name2 + ' is his assistant'

Futureパターン

EventMachineでFuture(Promise)パターンするときの例文をメモ

GitHub - cotag/em-promise: A promise/deferred implementation for EventMachine

require 'em-promise'

def testMethod
  deferred = EM::Q.defer
  EM.defer do
    begin
      # databaseなどを非同期処理
      raise "exception" if [true, false].sample # テストなのでわざと例外発生
      deferred.resolve('true') # 成功した時はresolveを実行、引数を渡せる
    rescue => e
      deferred.reject(e) # 例外のときはrejectを実行、引数を渡せる
    end
  end
  deferred.promise # promiseを返す
end

EventMachine.run do
  testMethod.then(proc{|m|
    puts "succeed #{m}" # 成功した時の処理、viewになげたり
  }, proc{|m|
    puts "failed #{m}" # 失敗した時の処理
  }).then(proc{|m|
    puts "finished" # finalize  
    EM.stop
  })
  puts "async"
end

非同期実行なのでasyncが表示されてからtestMethodが、実行されます。 testMethodの中身を、もうすこしすっきり書きたいので、書き直し。

require 'em-promise'

def future
  deferred = EM::Q.defer
  EM.defer do
    yield(deferred)
  end
  deferred.promise
end

def testMethod
  future do |dfr|
    begin
      # databaseなどを非同期処理
      raise "exception" if [true, false].sample # テストなのでわざと例外発生
      dfr.resolve('true') # 成功した時はresolveを実行、引数を渡せる
    rescue => e
      dfr.reject(e) # 例外のときはrejectを実行
    end
  end
end

EventMachine.run do
  testMethod.then(proc{|m|
    puts "succeed #{m}" # 成功した時の処理、viewになげたり
  }, proc{|m|
    puts "failed #{m}" # 失敗した時の処理
  }).then(proc{|m|
    puts "finished" # finalize  
    EM.stop
  })
  puts "async"
end