Subscribed unsubscribe Subscribe Subscribe

Islands in the byte stream

Technical notes by a software engineer

<meta name="robots" content="noindex"/> でも検索エンジンにインデックスされるケースがある

noindex tagがあるにも関わらずインデックスされているケースを見かけたので調べてみたところ、googlebotに関してはどうやらそういう仕様があるようです。 noindex tag は常にインデックスの削除を行うのだと思っていたのでちょっと驚きました。

メタタグを使用して検索インデックス登録をブロックする - Search Console ヘルプ

重要: noindex メタタグを有効にするには、robots.txt ファイルでページをブロックしないでください。ページが robots.txt ファイルでブロックされると、クローラは noindex タグを認識しません。そのため、たとえば他のページからリンクされていると、ページは検索結果に引き続き表示される可能性があります。

Block search indexing with meta tags - Search Console Help (同ページ英語版)

Important! For the noindex meta tag to be effective, the page must not be blocked by a robots.txt file. If the page is blocked by a robots.txt file, the crawler will never see the noindex tag, and the page can still appear in search results, for example if other pages link to it.

ちょっとこの説明だけだとよくわかりませんが、 noindex を指定していても検索エンジンにインデックスされるケースがあるようです。

googlebotが「noindex tagをみるとそのページをインデックスしない、既にインデックス済みの場合はインデックスを消す」というロジックだと仮定すると、たとえば次のようなケースではインデックスされるのかもしれません。

  1. noindex tagを指定しないままページを公開する
  2. noindex tagの指定とrobots.txtによる該当ページのブロックを 同時に 行う
  3. googlebotは該当ページを見に行かないので、「noindex tagをみてインデックスを削除する」という処理を行わない

これが正しいのだとすると、このgooglebotの注意書きのとおり、 robots.txt で該当ページのブロックを外せばインデックスが削除されるはずですね。goolebotがrobots.txt でブロックしているのを見つけたら、ブロックされているURLですでにあるインデックスをすべて削除すればいいような気もしますが、そうはなっていないようです。

ただ上記のgooglebotの注意書きの「たとえば他のページからリンクされていると、ページは検索結果に引き続き表示される可能性があります」はよくわかりません。最初からnoindex tagとrobots.txtによるブロックしていて、かつ他のページからリンクされているときもインデックスされるかのように読めますが、この解釈が正しいのかどうかはわかりません。

Ormaに関する雑談&質問用にgitterのchat roomをつくりました

en: https://gitter.im/Android-Orma/Lobby ja: https://gitter.im/Android-Orma/Ja

背景

GitLab、Slackライクなサービス「Gitter」を買収。有償プラン廃止で何人でも無料で利用可能に。オープンソース化も約束 - Publickey でひさびさにgitterを知って、悪くないんじゃないかと思って設置してみました。

OSSコミュニティの母体としてSlackをつかうことが増えてるようですが、gitterだとpublic channelであれば招待されなくても入れるし、コミュニティとしてはそのほうがいいですよね。

正直チャットサービスとしてのクオリティはSlackのほうが高いです。gitterはリアクションとかできないし、モバイルアプリもGitHubのパスワードをアプリ内ブラウザで入力しないといけないので使えないし。しかしライブラリやフレームワークごとにslackチャンネルに入るのも大変面倒なので、それよりはgitterのほうがよさそうだなと思っています。

カンファレンススタッフ用アプリがあるとよさそう

DroidKaigi 2017お疲れさまでした。スタッフとしては3回目、スピーカーとしては初めての参加でした。

スタッフとしては、受付の誘導、司会、副司会、会場の片付けなどをしました。特に司会はわりと臨機応変に行動しなければならず、部屋ごとにけっこうバラバラだったのではないかなあと思います。

カンファレンスが始まってからも次々と様々な仕様変更がきて、「意識を高くもって気をつける」だけだとカバーしきれないところがあります。そういう点をカバーできるようにカンファレンススタッフ用アプリがあるといいなーと思って記憶が鮮明なうちにメモしておきます。もちろん関係者でのKTPは別途しますが、それは公開されないと思うので。

実際に起きたこと

  • スタッフのシフト表の変更
    • 頻繁におきてた印象、というのもいくつか不整合がみつかるので
    • シフト表にいれるスタッフは40人くらいいるので、不整合なく保つのは至難の業
  • セッションのTimetableの変更
    • やむを得ない事情によりキャンセルになった枠に当日の判断でFireside Chatをいれることになった
    • 決定があった時点でアナウンスしたけど館内放送があるわけではないので全員に周知できたかどうかは不明
  • 司会用チートシートがどんどん増える問題
    • 部屋 x 時間帯(ランチ前・一日目終了後・二日目終了後)などで微妙に言うことが違うのもなかなか大変
  • 適切な人に適切なタイミングで情報をpush通知する必要性
    • インカム(トランシーバ)を多用していたけど、インカムから情報を聞き取るのはかなり集中しないといけない
    • インカム議事録係がいたけど大変そうだった
  • 司会から発表者への残り時間の通知を適切にするためのツールが乏しく意識だけでやってる、ゆえにときどきミスる

こういうアプリがほしい

  • 1秒で起動して「いま自分が何をすべきか」を知りたい(チートシート)
  • チートシートに差分があればわかりやすく表示してほしい
  • 司会の場合、発表開始5分前、開始時、発表終了10分前、5分前、終了時に通知がほしい
  • スタッフ(あるいはスタッフグループごと)へ情報をpushできるようにする
    • 重要な知らせは強いpush通知(5分くらいバイブレーションが続くとか)があってもいいかもしれない

DroidKaigi 2017で「ORMの選び方」という発表をしました

Ormaの開発の際に他のORMはどういう設計思想なのかを調べたときの知見をもとに、DroidKaigi 2017用に仕上げた発表です。

これ契機にORMについて一家言ある人が増えるといいなと思いながら発表しました。

SQLiteDatabase (SQLiteOpenHelper) を直接つかうかどうかでいうと圧倒的にORMをつかったほうが早く品質のよいアプリを開発できると思っていて、それはやはりORMのマッピング、クエリビルダ、アソシエーション、pub-sub、マイグレーションといった機能が便利だからなんですよね。ただ便利といういだけのみならず、型安全だったり自動化してくれたりと信頼性を高める工夫を書くORMがしているわけで、それを使わないのはもったいないです。

その上で、まあ私としてはOrmaが私の感じる問題を解決してくれる唯一のORMなのでOrmaを使いますが、機能や将来性などを考えるとフルコミッターを大勢抱えるRealmはよさそうだなとは思います。Ormaはすばらしいライブラリですが、開発者がSPOFという点は否めませんからね。ただなぜ私がRealmを好かないのか、Realmがある世界に敢えてもうさらにORMを追加したのかというのも資料で触れてます。

というのはすべて差し置いて、ORMの開発はめちゃくちゃ楽しかったのでよかったらあなただけのオリジナルORMを作ってみてください。

Bit Journeyに転職してKibelaをリリースしました

半年くらいまえにBit Journeyに転職してKibelaを作ってました。AndroidエンジニアからRails + Reactエンジニアへの転向ということになります。

Kibelaはこちら。ようやく本日リリースできました。といっても開発面でいうとこれからが正念場ではあります。

Kibela - 個人の発信を組織の力にする情報共有ツール

“個人の発信を組織の力にする情報共有ツール” と銘打っているとおり、これは 個人が組織内で自由に情報を発信すると組織が活性化する という仮説に基づいて設計されている、会社などの組織向けのサービスです。もちろんそれだけでなく、仕様書の整理につかったり議事録をとりあえず突っ込んでおくみたいなのもありです。

さてKibelaでできることはBlogとWikiを書くことです。これはつまり 個人が発信する情報 とそれ以外を分けるということです。このあたりの思想やベストプラクティスは追々公式ブログで語っていきたいです。

今回の転職は、このKibelaというサービス自体に興味があったというのが主な理由でした。Kibelaはクックパッドの社内向け内製ツールGroupadにヒントを得て設計されています。実際のところ、 個人が組織内で自由に情報を発信すると組織が活性化する という仮説は、私やBit Journey創業メンバーがいたクックパッド社での経験がもとになっています。Groupadが見せてくれた組織における情報共有のありかたには在職中ずっと興味をもっていて、クックパッド社の活力の源のひとつだと考えていたのです。そういう思いがあったので、Bit Journey代表の井原からの「一緒にKibelaを作らないか」という誘いに乗ることにしたのでした。

Kibelaは技術的にみると普通のRailsアプリケーションといえますたサービスの性質上そこまでスケーラビリティやパフォーマンスへのプレッシャーはありません。しかし半年経験してみると、技術的に深掘りできるポイントもたくさんあり、いまのところ楽しんで開発してます。

というわけで、Kibelaをどうぞよろしく!

Herokuのreview appsでRailsのLetter Opener WebをつかうHack

github.com

これのREADMEにもありますが、Letter Opener (-Webも含む)をHerokuで使うにはちょっと注意が必要です。つまり、

  • Letter Openerはデータを #{Rails.root}/tmp/letter_opener に保存する
  • Herokuはdyno (node) 間でデータのやりとりは出来ない設計
  • ActionMailerの deliver_later! はActiveJobで実行するので、web dynoではなくworker dyno のファイルシステムにLetter Openerのデータを保存する

という状況なので、 #deliver_now! で送信したものはLetter Openerで見えますが、 #deliver_later! で送信したものは見えない、ということになります。

じゃあHeroku review appのときだけ #deliver_later!#deliver_now! に置き換えればいいんですねということでApplicationMailerにこんな感じのhackを入れました。

ActionMailerの内部実装に強く依存しているのでRailsのアップデートなどで動かなくなる可能性はありますが、 Rails 4.2.x, 5.1.x あたりはこれで大丈夫そうです。

# rubocop:disable Style/MethodMissing

class ApplicationMailer < ActionMailer::Base
  # Heroku web apps do not access worker's filesystem
  # https://github.com/fgrehm/letter_opener_web#usage-on-heroku

  # override
  def self.method_missing(method_name, *args)
    if action_methods.include?(method_name.to_s)
      MyMessageDelivery.new(self, method_name, *args)
    else
      super
    end
  end

  class MyMessageDelivery < ActionMailer::MessageDelivery
    # override
    def deliver_later!
      if Rails.env.heroku_review_app?
        deliver_now!
      else
        super
      end
    end

    # override
    def deliver_later
      if Rails.env.heroku_review_app?
        deliver_now
      else
        super
      end
    end
  end
end

Orma v4.2.0 の Relation#upsert() の設計

https://github.com/gfx/Android-Orma

Orma v4.2.0 で Relation#upsert() を実装しました。これは、モデルのインスタンスを渡すとその状態に応じて INSERT または UPDATE を実行するというメソッドです。

モデル同士の関連もよしなにしてくれるので、とりあえず #upsert() で突っ込むといい感じに保存されるという便利メソッドです。

ただひとつ注意点があって、primary key の自動採番モード(デフォルトの挙動)のときに #upsert() 後にそのモデルを参照する場合は、#upsert() の戻り値を使わなければいけません。というのも、Ormaは どんなモデルでもimmutableであるという仮定 を置いており、自動採番したprimary keyをモデルのフィールドに代入したりはしないからです。

つまり、次のようなモデルクラスがあったときに:

@Table
public class Todo {

    @PrimaryKey
    public long id;

    @Column(indexed = true)
    public String title;

#upsert() により次のような状態になります。

Todo todo = new Todo();
todo.title = "foo";

Todo newTodo = todoRelation.upsert(todo);

assert todo.id == 0; // todo.idは変化なし

assert newTodo.id > 0; // newTodoのほうは割り当てられたidを持っている

newTodo.title = "bar";

todoRelation.upsert(newTodo); // 変化する要素がないので戻り値は不要

associationについても同様です。

少し煩雑ですが、実は Inserter#execute() も渡されたモデルを変更しないという意味では同じで、モデルをimmutableと見なす設計です。

というわけで、ちょっとクセはありますが便利だと思いますので使ってみてください。