Tech Racho エンジニアの「?」を「!」に。
  • 開発

週刊Railsウォッチ(20170915)Ruby 2.4.2リリースで脆弱性修正、strong_migrations gemでマイグレーションチェック、書籍『Mastering PostgreSQL』ほか

こんにちは、hachi8833です。Macbook Proの底のゴムが4つとも取れてしまったので、障子の滑りをよくするスライドクッション(ホームセンターで270円)を貼ってみたらすごく具合がよくてうれしい今日この頃です。なおGenius Barでのゴム修復の見積は1万2000円でした。

それでは今週のウォッチ、いってみましょう。

臨時ニュース: Ruby 2.4.2リリース: 脆弱性修正を含む

脆弱性の修正箇所を差分から追おうとしたのですが、CVE番号とかがコミットメッセージに見つからなくてあきらめました。


つっつきボイス: 「脆弱性はどれも注意してれば本番では踏まなさそう」

慌てず急いで正確にアップデート。

Rails: 先週と今週の改修

まずは先週分から。

imageタグのデフォルトaltテキストを生成しなくなった

-    assert_dom_equal '<img alt="Somelogo" src="http://www.example.com/images/somelogo.png" />', mail.body.to_s.strip
+    assert_dom_equal '<img src="http://www.example.com/images/somelogo.png" />', mail.body.to_s.strip

前にもこんな修正を見たような気がします。


つっつきボイス: 「これこの間もチェックしてたんですが、ダミーaltを取っ払うとW3C validatorとかで余分なエラーが出るからちょっと残念」「あー、そっか: でもいずれ書くことになりそうですけどね」

SET timezoneが1度だけ実行されるようになった

+          variables = @config.fetch(:variables, {}).stringify_keys
+
           # If using Active Record's time zone support configure the connection to return
           # TIMESTAMP WITH ZONE types in UTC.
-          # (SET TIME ZONE does not use an equals sign like other SET variables)
-          if ActiveRecord::Base.default_timezone == :utc
-            execute("SET time zone 'UTC'", "SCHEMA")
-          elsif @local_tz
-            execute("SET time zone '#{@local_tz}'", "SCHEMA")
+          unless variables["timezone"]
+            if ActiveRecord::Base.default_timezone == :utc
+              variables["timezone"] = "UTC"
+            elsif @local_tz
+              variables["timezone"] = @local_tz
+            end
           end

           # SET statements from :variables config hash
           # https://www.postgresql.org/docs/current/static/sql-set.html
-          variables = @config[:variables] || {}
           variables.map do |k, v|
             if v == ":default" || v == :default
               # Sets the value to the global or compile default

つっつきボイス: 「うん、これは単なるバグ」

Content-Dispositionのファイル名をRFC 2231に沿ってエンコーディングするようになった

テストコードがわかりやすいです。

# activestorage/test/models/filename/parameters_test.rb
+  test "parameterizing a non-Latin filename" do
+    filename = ActiveStorage::Filename.new("автомобиль.jpg")
+
+    assert_equal %(filename="%3F%3F%3F%3F%3F%3F%3F%3F%3F%3F.jpg"), filename.parameters.ascii
+    assert_equal "filename*=UTF-8''%D0%B0%D0%B2%D1%82%D0%BE%D0%BC%D0%BE%D0%B1%D0%B8%D0%BB%D1%8C.jpg", filename.parameters.utf8
+    assert_equal "#{filename.parameters.ascii}; #{filename.parameters.utf8}", filename.parameters.combined
+    assert_equal filename.parameters.combined, filename.parameters.to_s
+  end

参考: RFC2231 MIME Parameter Value and Encoded Word Extensions: Character Sets, Languages, and Continuations


つっつきボイス: 「あー、これIEだと挙動が違うやつだ(参考)」「ChromeやFirefoxだとエンコード指定がないときはUTF-8で解釈してくれるので、RailsをChromeだけでテストしてOKと思ってたらIEでコケるやつです」「ひょえー」「Rails初心者がよくはまってましたね」

cookieの期限をメタデータに追加

        def commit(options)
-         options[:value] = @verifier.generate(serialize(options[:value]))
+         options[:value] = @verifier.generate(serialize(options[:value]), expiry_options(options))

          raise CookieOverflow if options[:value].bytesize > MAX_COOKIE_SIZE
        end

つっつきボイス: 「cookieの期限設定って前からありましたよね?」「もちろん」「"signed/encrypted cookies"が大事: cookieの暗号化に使うメタデータ生成に期限設定情報を含めることで、サーバーで期限設定を変更すると復号できなくなってcookieが無効になるという本来の望ましい動作になる」「ほっほーでござる」


続いて今週分です。

gemメソッドで複数バージョンのgemを扱えるようになった

       def gem(*args)
         options = args.extract_options!
-        name, version = args
+        name, *versions = args

         # Set the message to be shown in logs. Uses the git repo if one is given,
         # otherwise use name (version).
         parts, message = [ quote(name) ], name.dup
-        if version ||= options.delete(:version)
-          parts   << quote(version)
-          message << " (#{version})"
+
+        if versions = versions.any? ? versions : options.delete(:version)
+          _versions = Array(versions)
+          _versions.each do |version|
+            parts << quote(version)
+          end
+          message << " (#{_versions.join(", ")})"
         end
         message = options[:git] if options[:git]

つっつきボイス: 「#gemメソッドってBundlerが扱うGemfileに書かれている#gemメソッドなのかな?RubyMineで追いかけてみよう」「ほむ、これはRailsのGeneratorコードの中でGemfileを生成するのに使うRails::Generators::Actions#gem の方か」「Bundlerの#gemでは複数バージョンを設定できたのにこっちでできてなかったから、こっちでもできるようにしたということみたい」

メソッド再定義をremove_methodからredefine_methodに変更

この間kamipoさんがキリ番30000を取ったと思うのですが、#29233とは随分戻った感じですね。

# activesupport/lib/active_support/core_ext/date_time/compatibility.rb
require_relative "../date_and_time/compatibility"
-require_relative "../module/remove_method"
+require_relative "../module/redefine_method"

 class DateTime
   include DateAndTime::Compatibility

-  remove_possible_method :to_time
+  silence_redefinition_of_method :to_time

つっつきボイス:#remove_methodってどこにあるんじゃろか?:おー、Rubyに...いる!」
「うん、確かに#silence_redefinition_of_methodというメソッド名の方が意図がわかりやすい」

#silence_redefinition_of_methodは、Rubyのバージョンが低いときにredefineしてもWarningを出さないようにするのか」

+class Module
+  if RUBY_VERSION >= "2.3"
+    # Marks the named method as intended to be redefined, if it exists.
+    # Suppresses the Ruby method redefinition warning. Prefer
+    # #redefine_method where possible.
+    def silence_redefinition_of_method(method)
+      if method_defined?(method) || private_method_defined?(method)
+        # This suppresses the "method redefined" warning; the self-alias
+        # looks odd, but means we don't need to generate a unique name
+        alias_method method, method
+      end
+    end
+  else
+    def silence_redefinition_of_method(method)
+      if method_defined?(method) || private_method_defined?(method)
+        alias_method :__rails_redefine, method
+        remove_method :__rails_redefine
+      end
+    end
+  end
...

Rails

Turbolinksを使うRailsアプリでSJRは必要なのか(RubyFlowより)

とっても短い記事です。

In summary, Turbolinks will automatically handle your page-to-page navigation, whereas SJR can be used to handle XHR form submissions.
要するに、Turbolinksはページ遷移を自動ハンドリングするが、SJRはXHRフォーム送信のハンドリングに使えます。
同記事より


つっつきボイス: 「SJRってなんだっけ?と思って」「つ↓」

This technique is known generally as “Server-generated JavaScript Responses” or SJR for short.

link_to :remoteとかでformat.js { render text: '$('hoge').show();'}みたいに書くやつっぽいですね」
「バックエンドのコードを書く立場だけ考えれば、link_to :remoteと組み合わせてとても手軽にAjax処理を書ける点は好き: ただし次のような問題がある」

  • webpack等で処理できないのでprecompileされない
  • Babel等にも通らないのでJSの言語依存を把握した上で使わないと死ぬ
  • JS側だけでのSysntax Checkやコードポリシチェッカを通らない
  • Railsサーバとセットで動かさない検証できないし、ちゃんとテストするならheadless browserとかを使って検証しなければならず、テスト粒度も単体レベルでできないうえに重くなる

「なるほど、書くのは楽だけど後でつらくなる感じですね、特にテストが」「何よりフロントエンジニアは確実に嫌がるでしょうね」「Railsアプリを一人で全部書いてずっとメンテするならワンチャンあるかもですが」

RailsとGraphQLのパフォーマンス(RubyFlowより)


blog.codeship.comより

GraphQLだったのでつい拾ってみました。


つっつきボイス: 「GraphQLを、アクセスがめちゃめちゃ集中するようなサービス構築に使うにはもっとノウハウの蓄積が必要そうですね」「GraphQLの性質上Railsより手前でキャッシュしづらいはずで、JSONやURLがほんのちょっと違うだけでキャッシュにヒットしなくなって、パフォーマンス・チューニングで打てる手段が限られてくるかも」「Burst read対策にとりあえずVarnish、みたいな手が使えなくなるのはとてもつらい」
「GraphQLはカラムの少ないテーブルで使う方がいいのかな?」「いや、むしろカラムの多いテーブルこそ有効」
「ところでVarnishって?」「コンテンツキャッシュサーバーと呼ばれているもので、キャッシュサーバ機能に特化したリバースプロキシです」「うさぎのマークが目印でござるよ↓」


varnish-cache.orgより

RailsのモデルでちゃんとuniqueバリデーションするためにDBインデックスを適切に設定しよう(RubyFlowより)

記事では1.を推しています。

  1. 適切なDBインデックスを追加する
  2. uniqueバリデーションをDBレベルに移す

つっつきボイス: 「うん、書いてあることはとっても普通」「つまりやってて当然ということですね」
「記事最後の『How to identify these issues in your existing project』、このexisting projectでやるってのがねー、大変なんです」

記事では、soulfly/unique_validation_inspectorというgemも紹介しています。

「このツールが有用なのはわかる: でもこのツールを使わなきゃいかん人ほど使わないんですよ」

⭐strong_migration: 危ないマイグレーション操作を検出⭐(Postgres Weeklyより)

今回よりPostgres Weeklyも巡回しています。

記事はTechRachoのPostgreSQL関連翻訳記事でおなじみCraig Kerstiensさんです。


www.craigkerstiens.comより

おなじみankaneさんがまた何か作ったようです。GitHub TrendingでもRuby部門のトップに上がっていました。
dev環境で(主にPostgreSQLで)問題を起こしやすい以下のマイグレーション操作を検出します。

  • not nullかつデフォルト値を持つカラムを既存テーブルに追加する
  • カラムの型を変更する
  • テーブルのリネーム
  • カラムのリネーム
  • カラムの削除
  • インデックスをnon-concurrentに追加する(PostgreSQLのみ)
  • JSONカラムを既存テーブルに追加する(PostgreSQLのみ)

production環境での危険な操作はデフォルトで禁止されます(オプションで解除可能)。

たとえば運用中のテーブルのリネームを安全に行うには、以下のように(自分で)マイグレーションする必要があるそうです。

  1. テーブルを新規作成する
  2. 書き込みを両方のテーブルに行うようにする
  3. 古いテーブルのデータを新しいテーブルに複製する
  4. 読み込みを古いテーブルから新しいテーブルに切り替える
  5. 古いテーブルの書き込みを止める
  6. 古いテーブルを削除(drop)

つっつきボイス: 「最近バズってるgemみたいです」「おー、これよさそう!: PostgreSQLってこの手の独特の縛りがいろいろあるんですよ」「なんと」「MySQLだと通るマイグレーション操作がPostgreSQLだとコケたりとか、MySQLで慣れてる開発者がPostgreSQLに乗り換えるとこういうのにつまづきやすい」
「PostgreSQL案件にはとりあえずこのgem入れておくのがよさそう」

今週の⭐を進呈いたします。おめでとうございます。

RubyMineアップデート情報: WindowsでのDocker Composeやデバッガ強化など


blog.jetbrains.comより

社内Slackに投下されました。


つっつきボイス: 「2017.2.3だから一瞬今年初頭かと思ってしまいました:、RubyMineのバージョン表記紛らわしい」「Docker Composeもさることながら、デバッグ機能の強化は特に初心者にはうれしいかも」「社内のインターンくんに使ってもらおうかな」

type_scopes: 型に応じてActive Recordモデルのスコープを設定するgem

# READMEより
# paid_at: datetime
# amount: decimal
# description: string
class Transaction < ActiveRecord::Base
  include TypeScopes
end

# Time scopes
Transaction.paid_to("2017-09-06") # => where("paid_to <= '2017-09-06'")
Transaction.paid_from("2017-09-06") # => where("paid_to >= '2017-09-06'")
Transaction.paid_after("2017-09-06") # => where("paid_to > '2017-09-06'")
Transaction.paid_before("2017-09-06") #= where("paid_to < '2017-09-06'")
Transaction.paid_between("2017-09-06", "2017-09-07")  # => where("paid_to BETWEEN '2017-09-06' AND '2017-09-07'")

★7つです。


つっつきボイス: 「あー、これやってみたい気持ちはとてもわかる: でも現実にはこんな感じになりそう」

  • 使わないscopeが大量に定義される(しかもカラム数 * n)のでメモリがっつり食いそう
  • 組み合わせ次第でscope名とcolumn名がかぶりそう: access_fromaccess_toとか普通にカラム名で使われそうだし

「なので、業務としての案件にこのgem入れられるとあまりうれしくないかも」
「メモリを食うのはどのタイミングでしょうか?」「起動時でしょうね」

Ruby

language_server-ruby:

最近よく話題に上がっているlanguage_server-rubyです。来週のRubyKaigiでもスピーチがあります。Matzによる解説を引用しました。

LanguageServerっていうのはエディターと通信して、リアルタイム構文解析やコード補完の機能を提供するものです。 もともと、コンパイラとエディタは独立しているので、IDEとかは内部的にコードを解析してエラーが出た時にはポップアップを出しますよね。 そういう機能を任意の言語でできるようにするのがLanguage Serverです。

これに対応するとLanguage Serverプロトコルに対応しているあらゆるエディタでコード補完が使えるようになります。 開発効率アップの可能性がありますね。
http://tech.vasily.jp/entry/rubykaigi2017_matz#Ruby-Language-Serverより


つっつきボイス: 「おー、ものすごく大規模な案件とか、カスタマイズしたRubyを共用したいときにはこれ有用だと思います」
「特定のパッチ当てたりとかですね」「チームで各自の環境のRubyバージョンを揃えるのって面倒じゃわい確かに」
「お、もしかしてこれ使ったらiOSアプリでRubyコード実行できるんじゃ?: たしかAppleのアプリ審査ガイドラインでは、任意のコードを実行する機能は許されてなかった気がするけど、これならAppleの審査とおるかもw」

RDBMS

Dimitri Fontaine氏のPostgreSQL本、刊行間近


masteringpostgresql.comより

PostgreSQL関連のツール開発やコンサルティングで著名なDimitri Fontaine氏の新作予告です。

pgloader 3.4.1でMySQLからPostgreSQLへスマートに移行しよう(翻訳)


つっつきボイス: 「うん、かなりディープだな: よさそう」「PostgreSQL 10も対応してるんでしょうねきっと」「この時期に出すなら当然ですね」
「このレベルでPostgreSQLを理解しておけば、鬼パフォーマンスチューニング案件とかが処理できるな: よっしゃ買うか」「歯ごたえありそうだけど、輪読会にはうってつけの内容ですね」「PostgreSQLを真面目に勉強したのは6.xのときだったかな」

PostgreSQL内部を一枚の図で表す(Postgres Weeklyより)


blog.postgresql-consulting.comより

とても短い記事で、かつ図が記事のヘソなのでここには引用しません。


つっつきボイス: 「おー、これはいい図だナー」「ここに引用したら仁義に反するので」「そりゃそうだ」
「普通に元記事開いて読んでね♪」

JackDB: PostgreSQLクライアントの新顔(Postgres Weeklyより)

www.jackdb.comより


つっつきボイス: 「ほほー、と思ったら試用期間はあるけど有料なのね: 自分はJetBrains製品をフルでsubscribeしているからDataGripの方が割安かな」


https://www.jetbrains.com/datagrip/より

アトミックなトランザクションで冪等なAPIを強化(Postgres Weeklyより)


brandur.orgより


つっつきボイス: 「DBのトランザクションとAPIのトランザクションの競合の話とかしてて、よい記事だと思う」
「DBでいくらトランザクションがんばっても、実はAPIレベルでatomicity保ててなかった、というのはよくある話」

Microsoftの中の人にインタビュー: AzureへのPostgreSQL追加とコミュニティへの参加について(Postgres Weeklyより)


2017.postgresopen.orgより

Postgresopen 2017というカンファレンスでのインタビューです。


つっつきボイス: 「マイクロソフトがPostgreSQLコミュニティに貢献する時代になったんですね」「最近のマイクロソフトは『いいマイクロソフト』だから」「確かに」

pqstream: PostgreSQLデータベースにイベントストリームでアクセスするツール(Postgres Weeklyより)

# psqlでの操作
a=> insert into notes values (DEFAULT, DEFAULT, 'here is an example note');
INSERT 0 1
a=> delete from notes where id=1;
DELETE 1
# psqtreamでの出力
$ pqs
{"schema":"public","table":"notes","op":"INSERT","payload":{"created_at":"2017-09-04T01:11:34.65629","id":1,"notes":"here is an example note"}}
{"schema":"public","table":"notes","op":"DELETE","payload":{"created_at":"2017-09-04T01:11:34.65629","id":1,"notes":"here is an example note"}}

つっつきボイス: 「イベントストリームってどう理解すればいいでしょうか?」「tailfだと思えばいいですヨ」
「普通はfluentdあたりを使うと思うけど、ちょっとadminでログインして取り急ぎ障害調査するときには便利かも」


www.fluentd.orgより

JavaScript

JavaScript Liveを巡回先に加えました。JSはニュースが多すぎるので絞るのが大変です。

ダウンロードを増やせるモバイルアプリデザインのトレンド2017(JavaScript Liveより)


excellentwebworld.comより

元記事の図を読むだけで足りる感じです。

  1. Design with details (Microinteraction)
  2. Material design
  3. In-App Animations
  4. Bottom navigations
  5. In-app gestures

JavaScriptでアクターモデルを理解する(JavaScript Liveより)


monades.roperzh.comより


上記事より


つっつきボイス: 「Actorって言葉、デザインパターンのアクターと混じって使われてることが一般に多いですね」「この記事は何かをしながら巡回する方のActorか」「エージェント的なモデルの概念説明のためのサンプルの記事かな」

CSS/HTML/フロントエンド

Web開発でも大きなウェイトをしめるデザイン面の記事をチェックしてみました。

コードの3つの一貫性: よいコードを書くために(Frontend Weeklyより)


css-tricks.comより

  • レベル1: 個人レベルでの一貫性
  • レベル2: チームレベルでの一貫性
  • レベル3: もっと大きなレベルでの一貫性

つっつきボイス:
「Rubyについては、ほとんどのプロジェクトでcoding guidelineが共有されているので、Lv.2-3の開きはほとんどありませんね(少なくともSyntaxとかbad know-howレベルでは)」
「Rubyのrubocopは、初歩的なSyntaxレベルだけじゃなく構造レベルの指摘もかなりやってくれるので、それに従ってるなら大丈夫」「rubocopって結構凄いのか」「その分ビシビシやられるでござるよ」
「ただJSなんかだとLv.2-3の開きはかなりあります: Googleと他の会社とかですらかなり違う」

「なお、Lv.1ができてないとBPSで仕事はできません」「Lv.1すら出来てない自称プログラマを見分けるにはGitHubのコードなんかを見せてもらうのが有効ですね」

【保存版】Rubyスタイルガイド(日本語・解説付き)総もくじ

デザイン上のやりとりを共通言語化するデザイン用語集(Frontend Weeklyより)


blog.prototypr.ioより


つっつきボイス: 「デザインスタイルガイドの見本みたいな感じですね」
「ちゃんとしたデザイン会社なら、まさにこういう感じのデザインガイドラインをきちんと出してくれますよ: その分高いですがw」
「特にこういうところ↓: どこからどこまでを黒い字で、どこから白い字にするか、みたいな部分がガイドラインで定められているととてもありがたいんですよ」

「前の職場で黒背景に黒い字で出してきたヤツいたなー」

フロントエンドインフラチームをうまく運用するには(Frontend Weeklyより)


tech.adroll.comより


つっつきボイス: 「Front-End Infrastructure Teamという言葉が、ありそうで見かけたことがなかったので」「うん、これはいい話: どちらかというとフロントエンド開発チームの編成とか組織づくりがメインかな」
「すごく大きなプロダクトにさまざまな専門家が集結しているプロジェクトがこんな感じに運営されればうまく回ると思う: 少人数だと多分無駄になるとおもうけど」

デザインの法則: フィードバックを減らすコツ(Frontend Weeklyより)


medium.com/apegroup-textsより


つっつきボイス: 「デザイナ向けの話に見えて、実はエンジニアにも通じる話」
「コードと違ってデザインは誰でも感想を言うことができるので、デザイン方針がぶれないように顧客を説得する技術はとても重要だし、デザインではそういう手法や法則の追求がとても進化している」「Design principleはそういうことか」「確かにエンジニアもそれやってるし、できないとイカンやつや」

「なおBPSデザインチームのFさんは、こういうのがものすごくうまい」

開発者とデザイナーが互いのプロ意識を深く理解してうまく役割分担できたら、きっとよい感じになると思えてきました。

弊社BPSのコーポレートサイトをリニューアルしました。

その他

Slack新機能: Shared Channels -- 外部メンバーとやりとりしやすいSlackチャンネル

既に日本語ヘルプも出てますが、Slackの新機能だそうです。

Google公式のスタイルガイドサイト

以前から公開されていますが、ドメインがときどき引越してたらしく、上が最新のようです。

以下がCreative Commons BY 3.0で公開されています。Rubyは見当たりませんでした。

スタイルガイドの変更履歴はあるかなと思ったらちゃんとありました。

W3Cの仕様やRFCなんかも、GitHubに置いて欲しいと思う今日この頃です。


つっつきボイス: 「Vimscriptのスタイルガイドまであるw」「Rのスタイルガイドが一番短そうです」「Rはどう書いてもグタグタになりそうだけど」


なおスタイルガイドとは少し違いますが、GoとDartについては以下があるとご注進をいただきました。

wpscan: WordPressの脆弱性スキャナー


wpscan.orgより


つっつきボイス: 「お、これ使ったことある」

src2png: ソースコードをシンタックスハイライト付きでpng化するJSツール(GitHub Trendingより)


つっつきボイス: 「こういうのってたまにとても必要になったりしますよね」「今度授業の資料作りに使ってみるかな: すごく縦長のコード画像はスライド向きじゃないんで使わないけど」

PlantUML: Atomエディタ用UMLレンダラー

元々Atomエディタ用ですがSublimeでも使えるようです、というか使えました。

参考: SublimeText3からPlantUMLを使う

もしやと思ったら、この間のチケット詐欺事件のチャート作成でも大活躍していました。


shunirr/criminal_jc.mdより


つっつきボイス: 「PlantUMLって前からありますね」「graphviz使ってみたことあったんですがしっくりこなかった」
「テキストでUML生成するツールって、UML本来の自由度を捨ててしまってるみたいであまり使いたくないんですよ」「自分の理解では、UMLって大枠だけ決めて後はご自由に、というもののはずなんだけど、テキストだとsyntaxに縛られすぎる感ありますね」
「UIは古いけど、UML作成ツールとしてはastah↓がやっぱりよくできてるし使いやすい: UMLからちょっと外れたような図もちゃんと描ける」


astah.change-vision.comより

Design Patterns for Humans™ -- ウルトラ簡単なデザインパターン解説


github.com/kamranahmedse/design-patterns-for-humansより

社内Slackで評判になってました。すごくよさそうです。

言われてみればなっとく(morimorihoge)

番外

21世紀に生きてる感

もういくつねると完全武装するのかな。


今週は以上です。来週はRubyKaigiでお会いしましょう。

バックナンバー(2017年度)

週刊Railsウォッチ(20170908)Rails 5.1.4と5.0.6リリース、コード書換え支援gem「synvert」、遅いテストを分析するTestProfほか

今週の主なニュースソース

ソースの表記されていない項目は独自ルート(TwitterやRSSなど)です。

Ruby 公式ニュース

Rails公式ニュース

Ruby Weekly

Awesome Ruby

Random Ruby

Ruby on Rails Security Project

RubyFlow

160928_1638_XvIP4h

RubyFlow

postgres_weekly_banner

Product Hunt

producthunt

Frontend Weekly

frontendweekly_banner_captured

JavaScript Live

javascript_live_logo_captured

Github Trending

160928_1701_Q9dJIU


CONTACT

TechRachoでは、パートナーシップをご検討いただける方からの
ご連絡をお待ちしております。ぜひお気軽にご意見・ご相談ください。