LoginSignup
110
109

More than 5 years have passed since last update.

Mastodonを支えるgems

Last updated at Posted at 2017-04-19

Mastodonのコードを読んでみることにしました。

知らないgemが一杯あったのでまずは調べてみることにしました。標準添付ライブラリ、Railsにデフォルトで含まれているものは除きます。また、group :developmentとか、group指定ありのは疲れたのでまた今度。

今回確認したGemfile

実際のコードに目を通しながら調べましたが、勘違いなどあればご指摘頂けるとうれしいです。

hamlit-rails

hamlit-rails provides generators for Rails 4.

Railsのジェネレータが生成するビューテンプレートをHaml化するhaml-railshamlit版のようです。Hamlという点では同じですがhaml gemへの依存をなくせますね。

pg

Pg is the Ruby interface to the PostgreSQL RDBMS.

RubyのPostgreSQLインタフェース。

pghero

A performance dashboard for Postgres

スロークエリのチェックやインデックスの状態などPostgreSQLの管理に役立つダッシュボードを提供するEngineのようです。
mastodonではDeviseのauthenticated routesを使ってマウントすることで管理者がアクセスできるようにしているようですね。
https://github.com/tootsuite/mastodon/blob/fe1ddc3b9614380367fa55f13df033e21c96747e/config/routes.rb#L11

authenticate :user, lambda { |u| u.admin? } do
  mount Sidekiq::Web, at: 'sidekiq', as: :sidekiq
  mount PgHero::Engine, at: 'pghero', as: :pghero
end

dotenv-rails

Autoload dotenv in Rails.

.env ファイルに環境変数を書いておくと自動的に環境変数ENV に読み込んでくれるようです。読み込みのタイミングはbefore_configurationなので、configで使いたいときはそれより前にDotenv::Railtie.load とする必要があるようです。
https://github.com/tootsuite/mastodon/blob/fe1ddc3b9614380367fa55f13df033e21c96747e/config/application.rb#L13

Dotenv::Railtie.load

paperclip

Easy upload management for ActiveRecord

RailsのActiveRecordでファイルアップロード機能を書くのによく使われるgem
。最近はshrineなど後発のものに押されてる感ありますがよく見ますね。
https://github.com/tootsuite/mastodon/blob/e09ab2c0bdc0822886fa98b0019d4a447a2ee0d6/app/models/account.rb#L15

# Avatar upload
has_attached_file :avatar, styles: ->(f) { avatar_styles(f) }, convert_options: { all: '-quality 80 -strip' }

paperclip-av-transcoder

Audio/Video Transcoder for Paperclip using FFMPEG/Avconv

Paperclipでアップロードした動画をFFmpegやlibav(avconv)を使って変換するためのようです。
mastodonではContent-Typeをみて使うprocessorを切り換えるようにして使っていました。
https://github.com/tootsuite/mastodon/blob/bfbc2ca0d8dcef47f8581585b42f13b6b4c933d9/lib/paperclip/video_transcoder.rb
https://github.com/tootsuite/mastodon/blob/bfbc2ca0d8dcef47f8581585b42f13b6b4c933d9/app/models/media_attachment.rb#L88

def file_processors(f)
  if f.file_content_type == 'image/gif'
    [:gif_transcoder]
  elsif VIDEO_MIME_TYPES.include? f.file_content_type
    [:video_transcoder]
  else
    [:thumbnail]
  end
end

aws-sdk

The official AWS SDK for Ruby. Provides both resource oriented interfaces and API clients for AWS services.

公式のRuby AWS SDKですね。
mastodonではアップロードファイルの保管先としてS3を使うときぐらいでしょうか。
https://github.com/tootsuite/mastodon/blob/6c83fec9715340bd178de0a8ba595bb4ad10eb1a/config/initializers/paperclip.rb#L10

addressable

Addressable is a replacement for the URI implementation that is part of Ruby's standard library.

標準ライブラリのURIのようにパースしたり、名前解決を行ってくれたり、正規化したりしてくれるようです。
mastodonではURLのバリデーションに使っているようです。
https://github.com/tootsuite/mastodon/blob/b330d1f000ef354a856c43aeaa27e079c89fc822/app/validators/url_validator.rb#L11

def compliant?(url)
  parsed_url = Addressable::URI.parse(url)
  !parsed_url.nil? && %w(http https).include?(parsed_url.scheme) && parsed_url.host
end

bootsnap

Boot large ruby/rails apps faster

Ruby/Railsアプリの起動高速化するgem。
Kernel#loadKernel#requireを書き換えてパス探索を高速化したり、コンパイル結果をキャッシュしたりするようです。

Adds bootsnap. Faster boot time #3176

cld3

Compact Language Detector v3 (CLD3) is a neural network model for language identification.

CLDというオープンソースの言語解析ライブラリのRubyバインディングのようです。

mastodonではトゥートの言語の自動検出に利用しています。

Language improvements, replace whatlanguage with CLD

Use CLD3 #2949

class LanguageDetector
  attr_reader :text, :account

  def initialize(text, account = nil)
    @text = text
    @account = account
    @identifier = CLD3::NNetLanguageIdentifier.new(1, 2048)
  end

# (snip)

@identifier.find_language(text_without_urls)

    ApplicationRecord.transaction do
      status = account.statuses.create!(text: text,
                                        thread: in_reply_to,
                                        sensitive: options[:sensitive],
                                        spoiler_text: options[:spoiler_text] || '',
                                        visibility: options[:visibility],
                                        language: detect_language_for(text, account),
                                        application: options[:application])
      attach_media(status, media)
    end
  def detect_language_for(text, account)
    LanguageDetector.new(text, account).to_iso_s
  end

devise

Flexible authentication solution for Rails with Warden

認証機能の手抜きによく使われる(僕もよく使ってしまう)そしてブラックボックスが嫌われがちなgemです。手早く一般的な機能を実装するのには便利だと思います。

devise-two-factor

Barebones two-factor authentication with Devise

Deviseで二段階認証(二要素認証)に対応する最小限の実装とのことです。Google Authenticatorなどに簡単に対応できるそうです。
https://github.com/tootsuite/mastodon/blob/93c13fe691750e8c7f0c90091bca2564b97ccba7/app/models/user.rb#L8

doorkeeper

Doorkeeper is an OAuth 2 provider for Rails and Grape.

OAuth2プロバイダの実装のようで、このあたりの記事が参考になりそうです。
mastodonのAPI認可に利用しているようです。
Search: doorkeeper

fast_blank

Provides a C-optimized method for determining if a string is blank

Cで書かれた高速なString#blank? で置き換えるようです。

goldfinger

A Webfinger utility for Ruby

WebFingerクライアントのRuby実装のようです。
mastodonでは別のサーバー(mastodonインスタンス)のアカウントのフォローに利用しているようです。
https://github.com/tootsuite/mastodon/blob/0687ab8ae3c2573ba2aa1d37f62e3583d0c7ab01/app/controllers/remote_follow_controller.rb#L18

if @remote_follow.valid?
  resource          = Goldfinger.finger("acct:#{@remote_follow.acct}")
  redirect_url_link = resource&.link('http://ostatus.org/schema/1.0/subscribe')

hiredis

Ruby wrapper for hiredis (protocol serialization/deserialization and blocking I/O)

RedisのCクライアントhiredisのRubyラッパーライブラリのようで、これ単体でも利用できるようですが、redis-rbとあわせて使うことでredis-rbの高速化が望めるようです。

htmlentities

A module for encoding and decoding (X)HTML entities.

文字実体参照や数値文字参照のエンコード・デコードができます。

http_accept_language

Find out which locale the user preferes by reading the languages they specified in their browser

ブラウザが送出したAccept-Languageヘッダーの扱いを簡単にします。リストアップした中から互換性のある言語を取り出したりできます。
mastodonではI18n.available_locales の中から使えそうなlocaleを選ぶのに使っています。
https://github.com/tootsuite/mastodon/blob/f5cd1383231af6922dbab4f54b7d29eacfec9d9e/app/controllers/concerns/localized.rb#L35

def user_supplied_locale
  http_accept_language.language_region_compatible_from(I18n.available_locales)
end

httplog

Log outgoing HTTP requests made from your application.

アプリケーションからの外部HTTP通信のログを記録してくれるので、たとえばAPI呼び出しの追跡などに役立つようです。

kaminari

Kaminari is a Scope & Engine based, clean, powerful, agnostic, customizable and sophisticated paginator for Rails 4+

ページネーションを実装する時にはまず使う、そんなgemです。
ActiveRecordだけでなく、Arrayなども同じようにページングできるのもよいです。

link_header

Converts conforming link headers to and from text, LinkHeader objects and corresponding (JSON-friendly) Array representations, also HTML link elements.

HTTPのLinkヘッダのパースや生成を簡単にするgemのようです。
mastodonではAPIでページネーションを実装するにあたり、前後のパスをクライアントに伝える際などに使っているようです。
https://github.com/tootsuite/mastodon/blob/e2a1b574ab4ec5dd07dbc5c317bcc3718f13c19b/app/controllers/api_controller.rb#L63

def set_pagination_headers(next_path = nil, prev_path = nil)
  links = []
  links << [next_path, [%w(rel next)]] if next_path
  links << [prev_path, [%w(rel prev)]] if prev_path
  response.headers['Link'] = LinkHeader.new(links)
end

nokogiri

Nokogiri (鋸) is an HTML, XML, SAX, and Reader parser.

XMLビルダー、パーサーを提供します。
mastodonではどちらの用途としても使っているようです。
https://github.com/tootsuite/mastodon/blob/137100dcf38c0da0fe7044a4c92aa06eae02c420/app/views/well_known/webfinger/show.xml.ruby#L1

Nokogiri::XML::Builder.new do |xml|
  xml.XRD(xmlns: 'http://docs.oasis-open.org/ns/xri/xrd-1.0') do
    xml.Subject @canonical_account_uri
    xml.Alias TagManager.instance.url_for(@account)
    xml.Link(rel: 'http://webfinger.net/rel/profile-page', type: 'text/html', href: TagManager.instance.url_for(@account))
    xml.Link(rel: 'http://schemas.google.com/g/2010#updates-from', type: 'application/atom+xml', href: account_url(@account, format: 'atom'))
    xml.Link(rel: 'salmon', href: api_salmon_url(@account.id))
    xml.Link(rel: 'magic-public-key', href: "data:application/magic-public-key,#{@magic_key}")
    xml.Link(rel: 'http://ostatus.org/schema/1.0/subscribe', template: "#{authorize_follow_url}?acct={uri}")
  end
end.to_xml

xml = Nokogiri::XML(body)
xml.encoding = 'utf-8'

if xml.root.name == 'feed'

oj

The fastest JSON parser and object serializer.

高速なJSONライブラリ。

ostatus2

Toolset for interacting with the OStatus2 suite of protocols

PubSubHubbubを使ってフィードの更新通知したり、Salmon(サーモン)Protocolでフィードにコメントを付けたりするのに使えるようです。
コメント分散問題は“サーモン・プロトコル”で解決!? - @IT
Mastodon OStatus API の叩き方
mastodonではgoldfingerとあわせて別のサーバー(mastodonインスタンス)のユーザーのfollow/unfollow/like/unlikeなどの実装に使っているようです。
https://github.com/tootsuite/mastodon/blob/6d6a429af8fe4bd92ed497f401676353fdc603e0/app/services/favourite_service.rb#L16
https://github.com/tootsuite/mastodon/blob/f722bd2387df9163760014e9555928ec487ae95f/app/workers/notification_worker.rb#L9
https://github.com/tootsuite/mastodon/blob/50660d54e8cabd08fee649a6abc26f35a8d7a82c/app/services/send_interaction_service.rb

# Send an Atom representation of an interaction to a remote Salmon endpoint
# @param [String] Entry XML
# @param [Account] source_account
# @param [Account] target_account
def call(xml, source_account, target_account)
  envelope = salmon.pack(xml, source_account.keypair)
  salmon.post(target_account.salmon_url, envelope)
end

ox

A fast XML parser and object serializer that uses only standard C lib.

Cだけで書かれたlibxmlなどに依存しない、高速なXMLパーサ&オブジェクトシリアライザのようです。
XMLパーサとしてNokogiriより2倍以上高速で、&オブジェクトシリアライザとしてMarshal.dumpより最大6倍高速で、SAXではNokogiriよりも40倍、LibXMLよりも13倍高速という謳い文句です。
mastodonではAtomの生成に利用しているようです。
https://github.com/tootsuite/mastodon/blob/15ec4ae07b17821625bd2ca1088a7573a7ed128c/app/lib/atom_serializer.rb#L8

document = Ox::Document.new(version: '1.0')
document << element
('<?xml version="1.0"?>' + Ox.dump(element, effort: :tolerant)).force_encoding('UTF-8')

rabl

General ruby templating with json, bson, xml and msgpack support

API応答をDSLで柔軟に書けるというテンプレートシステムのようです。JSONだけでなくXML、MessagePackなど複数のフォーマットに対応しています。
mastodonでもAPI応答など利用されています。
Search: extension:rabl

rack-attack

A rack middleware for throttling and blocking abusive requests

ミドルウェアレベルでセーフリスト、ブラックリスト、スロットリングなど不正なリクエストからの防御を実装できるようです。
mastodonではAPIや、ログイン、ユーザー登録などのレート制限の実装に利用しているようです。
https://github.com/tootsuite/mastodon/blob/ff5baa5349ca7a5391cfa9e283d2f5e653f876ee/config/initializers/rack_attack.rb

# Rate limits for the API
throttle('api', limit: 300, period: 5.minutes) do |req|
  req.ip if req.path =~ /\A\/api\/v/
end

# Rate limit logins
throttle('login', limit: 5, period: 5.minutes) do |req|
  req.ip if req.path == '/auth/sign_in' && req.post?
end

now        = Time.now.utc
match_data = request.env['rack.attack.throttle_data']['api']

response.headers['X-RateLimit-Limit']     = match_data[:limit].to_s
response.headers['X-RateLimit-Remaining'] = (match_data[:limit] - match_data[:count]).to_s
response.headers['X-RateLimit-Reset']     = (now + (match_data[:period] - now.to_i % match_data[:period])).iso8601(6)

rack-cors

Middleware that will make Rack-based apps CORS compatible.

ミドルウェアレベルでHTTPアクセス制御(CORS: Cross-Origin Resource Sharing)を実装できるようです。
mastodonではAPIのクロスオリジンアクセスの許可や、ヘッダのホワイトリストの指定などに利用しているようです。
https://github.com/tootsuite/mastodon/blob/0a1b0246003e19e80241d8711276db790a88235d/config/application.rb#L58

config.middleware.insert_before 0, Rack::Cors do
  allow do
    origins  '*'

    resource '/api/*',       headers: :any, methods: [:post, :put, :delete, :get, :options], credentials: false, expose: ['Link', 'X-RateLimit-Reset', 'X-RateLimit-Limit', 'X-RateLimit-Remaining', 'X-Request-Id']
    resource '/oauth/token', headers: :any, methods: [:post], credentials: false
  end
end

rack-timeout

Rack middleware which aborts requests that have been running for longer than a specified timeout.

ミドルウェアレベルでリクエストを受け取ってから結果を返すまでの待機時間や、POSTデータを受け取る際の受信待ち時間などを設定できるようです。
mastodonではproductionでのみサービスタイムアウトを設定しているようで、これにより長時間応答が返せない場合に処理を中断することができます。
https://github.com/tootsuite/mastodon/blob/5b12624847f6a599e1bbb3b24fc87c3b222e6716/config/initializers/timeout.rb#L5

Rack::Timeout::Logger.disable
Rack::Timeout.service_timeout = false

if Rails.env.production?
  Rack::Timeout.service_timeout = 90
end

rails-i18n

A set of common locale data and translations to internationalize and/or localize your Rails applications.

Railsのデフォルト文字列を翻訳した辞書一式のようです。使いたい言語だけを選ぶこともできます。

rails-settings-cached

This is improved from rails-settings, added caching.

アプリケーション設定をドットファイルなどではなくデータベースに記録し、変更できるようにしたいとき簡単に実装できるgemです。
mastodonでは「サイト名」や「自由にユーザー登録できるようにするか」などの設定に利用しているようです。
https://github.com/tootsuite/mastodon/blob/d87ee1167e0f11d94a20e70e9228a3398e202bc8/app/controllers/auth/registrations_controller.rb#L32

redis

A Ruby client library for Redis

Key-Value StoreのひとつRedisのRubyクライアントライブラリで、Redis APIと1対1で対応するようです。hiredisと組み合わせて使うことで高速化するようです。
mastodonではsidekiqのバックエンドとして非同期処理の他、ActionCable(これは設定だけかも)、Node.jsによるStreaming APIなどに利用しているようです。
https://github.com/tootsuite/mastodon/blob/323671a653e22704f0d50be13d67bf6fe6ee3a2a/app/services/fan_out_on_write_service.rb#L61

def deliver_to_hashtags(status)
  Rails.logger.debug "Delivering status #{status.id} to hashtags"

  status.tags.pluck(:name).each do |hashtag|
    Redis.current.publish("timeline:hashtag:#{hashtag}", @payload)
    Redis.current.publish("timeline:hashtag:#{hashtag}:local", @payload) if status.local?
  end
end

redis-namespace

Adds a Redis::Namespace class which can be used to namespace calls to Redis. This is useful when using a single instance of Redis with multiple, different applications.

Redisキーにnamespaceを使用できるようになるgemのようです。複数のアプリから1つのRedisサーバを使う場合など役立ちそうです。

namespace = ENV.fetch('REDIS_NAMESPACE') { nil }

if namespace
  Redis.current = Redis::Namespace.new(namespace, redis: redis_connection)
else
  Redis.current = redis_connection
end

rqrcode

rQRCode is a library for encoding QR Codes.

QRコード生成のライブラリのようです。
mastodonでは二段階認証(二要素認証)の際にスマートフォンに読み取らせるQRコードを生成するのに利用しているようです。
https://github.com/tootsuite/mastodon/blob/a8e1afc30a1f843943bb29e7385b8611ea3c29f4/app/controllers/settings/two_factor_auths_controller.rb#L50

ruby-oembed

oEmbed for Ruby

URLから埋め込み用コードを取得できるoEmbedという仕様のRuby実装のようです。oEmbedクライアントとしては、任意のoEmbedプロバイダのURLを指定するだけで、サムネイルや埋め込み用HTMLなどを取得できるようです。また、独自のoEmbedプロバイダを作るのにも使えるようです。
mastodonでは現在のところGemfileにはあるものの使われていなさそうでした。
個別のトゥートページのLinkタグで示されるapplication/json+oembed はありますが、
https://github.com/tootsuite/mastodon/blob/389f8f824909d60b7560248465416bd4bed92b6b/app/views/stream_entries/show.html.haml#L3

- content_for :header_tags do
  %link{ rel: 'alternate', type: 'application/atom+xml', href: account_stream_entry_url(@account, @stream_entry, format: 'atom') }/
  %link{ rel: 'alternate', type: 'application/json+oembed', href: api_oembed_url(url: account_stream_entry_url(@account, @stream_entry), format: 'json') }/

その実装は、rablで書かれていました。
https://github.com/tootsuite/mastodon/blob/389f8f824909d60b7560248465416bd4bed92b6b/app/views/api/oembed/show.json.rabl

# frozen_string_literal: true
object @stream_entry

node(:type) { 'rich' }
node(:version) { '1.0' }
node(:title, &:title)
node(:author_name) { |entry| entry.account.display_name.blank? ? entry.account.username : entry.account.display_name }
node(:author_url) { |entry| account_url(entry.account) }
node(:provider_name) { site_hostname }
node(:provider_url) { root_url }
node(:cache_age) { 86_400 }
node(:html) { |entry| "<iframe src=\"#{embed_account_stream_entry_url(entry.account, entry)}\" style=\"width: 100%; overflow: hidden\" frameborder=\"0\" width=\"#{@width}\" height=\"#{@height}\" scrolling=\"no\"></iframe>" }
node(:width) { @width }
node(:height) { @height }

これによりoEmbedに対応したサービスでmastodonのトゥートのURLを貼り付けると、特別な設定をせずとも埋め込み表示されます。
たとえばはてなブログなどは対応しています。

sanitize

Sanitize is a whitelist-based HTML and CSS sanitizer. Given a list of acceptable elements, attributes, and CSS properties, Sanitize will remove all unacceptable HTML and/or CSS from a string.

ホワイトリスト方式のサニタイズができるgem。許可する要素や属性など細かく設定できるようです。

mastodonでは用途ごとにサニタイズ設定を用意し、ヘルパーやサービスクラスで使い分けているようです。

    MASTODON_OEMBED ||= freeze_config merge(
      RELAXED,
      elements: RELAXED[:elements] + %w(audio embed iframe source video),

      attributes: merge(
        RELAXED[:attributes],
        'audio'  => %w(controls),
        'embed'  => %w(height src type width),
        'iframe' => %w(allowfullscreen frameborder height scrolling src width),
        'source' => %w(src type),
        'video'  => %w(controls height loop width),
        'div'    => [:data]
      ),

card.html   = Formatter.instance.sanitize(response.html, Sanitize::Config::MASTODON_OEMBED)

sidekiq

Simple, efficient background processing for Ruby.

非同期処理を実現するgemです。
Rails 4.2以上ではActive Jobというフレームワークが導入され、Sidekiqもそのバックエンドとして選択できるという扱いになりましたが、mastodonの場合はSidekiqをそのまま利用しているようです。
https://github.com/tootsuite/mastodon/blob/389f8f824909d60b7560248465416bd4bed92b6b/app/workers/after_remote_follow_request_worker.rb#L4

class AfterRemoteFollowRequestWorker
  include Sidekiq::Worker

  sidekiq_options queue: 'pull', retry: 5

  def perform(follow_request_id)
    follow_request  = FollowRequest.find(follow_request_id)
    updated_account = FetchRemoteAccountService.new.call(follow_request.target_account.remote_url)

if target_account.local?
  NotifyService.new.call(target_account, follow_request)
else
  NotificationWorker.perform_async(build_follow_request_xml(follow_request), source_account.id, target_account.id)
  AfterRemoteFollowRequestWorker.perform_async(follow_request.id)
end

sidekiq-scheduler

Light weight job scheduling extension for Sidekiq that adds support for queueinga jobs in a recurring way.

SidekiqでCRONなどのような定期処理を実装するgemです。
複数のサーバインスタンスがあるとき、多重実行されるのかどうか?そのケアは必要か?はちょっと試してないのでよくわかりません。(誰か詳しい方教えてください…)

https://github.com/tootsuite/mastodon/blob/58bcd50f7f8c187f8c0bd4a1d52aecafd76979fc/config/sidekiq.yml#L8
yaml
:schedule:
subscriptions_scheduler:
cron: '0 5 * * *'
class: Scheduler::SubscriptionsScheduler

# frozen_string_literal: true
require 'sidekiq-scheduler'

class Scheduler::SubscriptionsScheduler
  include Sidekiq::Worker

  def perform
    logger.info 'Queueing PuSH re-subscriptions'

    expiring_accounts.pluck(:id).each do |id|
      Pubsubhubbub::SubscribeWorker.perform_async(id)
    end
  end

  private

  def expiring_accounts
    Account.expiring(1.day.from_now).partitioned
  end
end

sidekiq-unique-jobs

Handles various types of unique jobs for Sidekiq

Sidekiqで同じジョブが同時に複数実行されないようにできるようです。
mastdonの場合は、2週間ぶりにログインしたユーザーのメンションをDBから探すという重めの処理について1回だけ実行したい、ということで利用しているようです。
https://github.com/tootsuite/mastodon/blob/5d710b1139b34f2ed6bd556f448fa7248354e758/app/controllers/application_controller.rb#L44

# If the sign in is after a two week break, we need to regenerate their feed
RegenerationWorker.perform_async(current_user.account_id) if current_user.last_sign_in_at < 14.days.ago

class RegenerationWorker
  include Sidekiq::Worker

  sidekiq_options queue: 'pull', backtrace: true, unique: :until_executed

simple-navigation

A ruby gem for creating navigations (with multiple levels) for your Rails, Sinatra or Padrino applications. Render your navigation as html list, link list or breadcrumbs.

ナビゲーションやパンくずリストを簡単に作れるgemのようです。
mastodonでは管理画面のナビゲーションに利用しているようです。
https://github.com/tootsuite/mastodon/blob/55e150352204bc790345cf81ef02bfcb1d7e0594/config/navigation.rb
https://github.com/tootsuite/mastodon/blob/0d83569899155e5d5c17fff0c69e533df2f34d42/app/views/layouts/admin.html.haml#L11

simple_form

Forms made easy!

Railsのフォームをスッキリ書けるDSLを提供するgemのようです。
mastodonではログインページ等各種フォームで利用しているようです。
https://github.com/tootsuite/mastodon/blob/23b997ae55655ccae6a9a9e424a3596c9165a481/app/views/auth/sessions/new.html.haml#L4

= simple_form_for(resource, as: resource_name, url: session_path(resource_name)) do |f|
  = f.input :email, autofocus: true, placeholder: t('simple_form.labels.defaults.email'), required: true, input_html: { 'aria-label' => t('simple_form.labels.defaults.email') }
  = f.input :password, placeholder: t('simple_form.labels.defaults.password'), required: true, input_html: { 'aria-label' => t('simple_form.labels.defaults.password') }

  .actions
    = f.button :button, t('auth.login'), type: :submit

statsd-instrument

A StatsD client for Ruby apps.

StatsDののRubyクライアントで、アプリケーションのメトリクスの取得と計測を行えるようです。
mastodonではActiveSupport::Notificationsを使ってActionControllerの処理を時間を計測しているようです。
https://github.com/tootsuite/mastodon/blob/f6a5977f0b2986b15ca8254123053e1a59647cd1/config/initializers/statsd.rb

    ActiveSupport::Notifications.subscribe(/performance/) do |name, _start, _finish, _id, payload|
      action      = payload[:action] || :increment
      measurement = payload[:measurement]
      value       = payload[:value]
      key_name    = clean_name("#{name}.#{measurement}")

      StatsD.send(action.to_s, key_name, (value || 1))
    end

ActiveSupport::Notifications.subscribe(/process_action.action_controller/) do |*args|
  event      = ActiveSupport::Notifications::Event.new(*args)
  # (snip)

  ActiveSupport::Notifications.instrument :performance, action: :measure, measurement: "#{key}.total_duration", value: event.duration
  ActiveSupport::Notifications.instrument :performance, action: :measure, measurement: "#{key}.db_time", value: event.payload[:db_runtime]
  ActiveSupport::Notifications.instrument :performance, action: :measure, measurement: "#{key}.view_time", value: event.payload[:view_runtime]
  ActiveSupport::Notifications.instrument :performance, measurement: "#{key}.status.#{status}"
end

twitter-text

A gem that provides text handling for Twitter

TwitterにツイートするテキストのURL自動リンク、文字数の正確なカウントなどの面倒をみてくれるようです。
mastodonではトゥートの自動リンクに利用しているようです。
https://github.com/tootsuite/mastodon/blob/70891a99a97bc1ca14a8ded13a5cd45b648b92b3/app/lib/formatter.rb
https://github.com/tootsuite/mastodon/blob/70891a99a97bc1ca14a8ded13a5cd45b648b92b3/spec/lib/formatter_spec.rb

webpacker

Use Webpack to manage app-like JavaScript modules in Rails

アセット管理をSprockets/BrowserifyからWebpackに切り替えたことで追加されました。

Webpacker gemについて調べる時間がなかったのでとりあえずほかの記事

今は支えていないgems

記事作成時点で使われていたけど、その後Gemfileから消えたgemはここに残しておきます。

font-awesome-rails

I like font-awesome. I like the asset pipeline. I like semantic versioning. If you do too, you're welcome.

font-awesomeとAsset Pipelineとセマンティック・バージョニングが好きな人に。

アセット管理をSprockets/BrowserifyからWebpackに切り替えた影響で削除したようです。

best_in_place

A RESTful unobtrusive jQuery Inplace-Editor and a helper as a Rails Gem

編集したいところをページ遷移なしにそのまま編集できる機能を簡単に実現できるようにするEngineのようです。mastodonでは管理画面のサイト設定で使っているようです・・・が、そのうち無くなる気がします。
https://github.com/tootsuite/mastodon/blob/d90d23699ca611f05d8def40109505251507fa46/app/views/admin/settings/index.html.haml#L15

%td= best_in_place @settings['site_contact_username'], :value, url: admin_setting_path(@settings['site_contact_username']), place_holder: t('admin.settings.contact_information.username')

autoprefixer-rails

Parse CSS and add vendor prefixes to CSS rules using values from the Can I Use website.

CSSベンダープレフィックスを付与してくれるAutoprefixerを、Sprocketsで使ってくれるようになるようです。

react-rails

Render components in views or controller actions.

RailsのViewとReact Componentの橋渡しをしてくれます。
mastodonでは、app/assets/javascripts/components/containers/mastodon.jsxをホームのViewに置くことでRails View内にTweetDeckっぽいSPAを置いています。react-rails単体でもJSXのプリコンパイルも対応しているはずですが、それについてはbrowserify-railsで行っていました。
https://github.com/tootsuite/mastodon/blob/0d83569899155e5d5c17fff0c69e533df2f34d42/app/views/home/index.html.haml#L6

- content_for :header_tags do
  %script#initial-state{:type => 'application/json'}!= json_escape(render(file: 'home/initial_state', formats: :json))

  = javascript_include_tag 'application', integrity: true, crossorigin: 'anonymous'

= react_component 'Mastodon', default_props, class: 'app-holder', prerender: false

browserify-rails

Browserify + Rails = CommonJS Heaven

SprocketsでCommonJSを使えるようにする方法の1つです。
mastodonではBabelifyと組み合わせてBabelのes2015とreactのプリセットを利用しているようです。
https://github.com/tootsuite/mastodon/blob/0a1b0246003e19e80241d8711276db790a88235d/config/application.rb#L71

config.browserify_rails.source_map_environments << 'development'
config.browserify_rails.commandline_options   = '--transform [ babelify --presets [ es2015 react ] ] --extension=".jsx"'
config.browserify_rails.evaluate_node_modules = true

const Mastodon = React.createClass({
  # (snip)
});

export default Mastodon;

//= require_tree ./components

window.Mastodon = require('./components/containers/mastodon');

アセット管理をSprockets/BrowserifyからWebpackに切り替えた影響で削除したようです。

whatlanguage

WhatLanguage rapidly detects the language of a sample of text

文字列からどの言語で書かれているか検出できるそうです。
mastodonではトゥートの内容から言語を検出するのに利用しているようです。
https://github.com/tootsuite/mastodon/blob/297c11dba2864b20992cd3f98282f5ce35d5d144/app/lib/language_detector.rb#L12

def to_iso_s
  WhatLanguage.new(:all).language_iso(text) || default_locale.to_sym
end

https://github.com/tootsuite/mastodon/blob/297c11dba2864b20992cd3f98282f5ce35d5d144/app/services/post_status_service.rb#L22
https://github.com/tootsuite/mastodon/blob/297c11dba2864b20992cd3f98282f5ce35d5d144/app/services/post_status_service.rb#L56

def call(account, text, in_reply_to = nil, options = {})
  media  = validate_media!(options[:media_ids])
  status = account.statuses.create!(text: text,
                                    thread: in_reply_to,
                                    sensitive: options[:sensitive],
                                    spoiler_text: options[:spoiler_text] || '',
                                    visibility: options[:visibility],
                                    language: detect_language_for(text, account),
                                    application: options[:application])
  # (snip)
end


def detect_language_for(text, account)
  LanguageDetector.new(text, account).to_iso_s
end

検出精度の低さが問題になってCLDというオープンソースの言語解析ライブラリベースのcld2gemに置き換えられ、その後さらにcld3gemに置き換えられたようです。

Language improvements, replace whatlanguage with CLD

Use CLD3 #2949

110
109
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
110
109