読者です 読者をやめる 読者になる 読者になる

日経BP テクノロジー・ロードマップ 2016-2025 医療・健康・食農編

私が一部執筆した書籍が出版されました。

ec.nikkeibp.co.jp

Highchartsでタイトルを非表示にする方法

Javascript

Highchartsのタイトルを非表示することがありました。以下のURLに記載がありました。

text: String
The title of the chart. To disable the title, set the text to null. Defaults to Chart title.

以下のようにtextにnullを渡して非表示にすることができました。

title: {
    text: null
}

stackoverflow.com

zshrcのプロンプトのシンプルな設定 (2015年1月版)

現在、.zshrcのプロンプトの設定は以下のようにしています。

PROMPT='[%n@%m]$ '
RPROMPT='%d %*'

以下のようなプロンプトになります。

[kaoru@server]$                      /Users/kaoru 11:01:34

SidekiqをHerokuで動作させるための設定

Sidekiq Heroku Rails

開発環境では、すぐにSidekiqを動作させることができたのですが、それをHeroku上のRailsで動作させるためには、いくつかの設定が必要でした。

Heroku Redisを有効にします。

$ heroku addons:create heroku-redis:hobby-dev


次に以下のファイルを作成します。

  • config/initializers/sidekiq.rb
if Rails.env.production?
  Sidekiq.configure_server do |config|
    config.redis = { url: ENV['REDIS_URL'] }
  end

  Sidekiq.configure_client do |config|
    config.redis = { url: ENV['REDIS_URL'] }
  end
end

Procfileにworkerの起動コマンドを設定します。

  • Procfile
web: bin/rails server -p $PORT -e $RAILS_ENV
worker: bundle exec sidekiq

以上の設定で Heroku上でSidekiqが動作するようになりました。

場合によっては、以下の設定も必要かもしれません。

Herokuの環境変数のREDIS_PROVIDERにREDIS_URLの値を設定します。

$ heroku config:set REDIS_PROVIDER=$(heroku config:get REDIS_URL)

github.com

RubyGemsを作成していてcannot load such fileエラーが発生した際の対処

Ruby

最近はFitbitのAPIにアクセスするプログラムを書いたりしていますが、FitbitのOAuth2に対応したRubyライブラリがないこともあり、自分でライブラリを作ってRubyGemsに登録しています。

プログラムを複数ファイルで管理しようとすると、gemのビルドは成功するものの、cannot load such fileというエラーが発生しました。しばらく原因がわからなかったのですが、.gemspecファイルを見ていたら、以下の記述がありました。

spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }

ファイル構成については、ファイルシステムではなくて、Gitリポジトリを参照しているようです。さきほどエラーが発生したコードを、git addとgit commitしてからビルドして実行すると、正常に動作するようになりました。

OAuth 2.0を利用してFitbitアカウントとDeviseのomniauthableを連携する方法

Fitbit Rails

FitbitではOAuth 1.0とOAuth 2.0の両方のインターフェースが用意されていますが、OAuth 2.0のほうが利用できるデータも多いですし、Fitbitの公式ドキュメントもOAuth 2.0を前提とした記述になっているようです。

以前にDeviseのomniauthableを利用して、FitbitのOAuth 1.0を利用した認証とAPIのアクセスをしました。

kaorumori.hatenadiary.com

kaorumori.hatenadiary.com

kaorumori.hatenadiary.com

これをOAuth 2.0でやっていきたいと思います。omniauth-fitbit-oauth2を利用します。

github.com


Gemfileに以下の記述を追加します。

gem 'devise'
gem 'omniauth-fitbit-oauth2'
$ bundle
$ rails g devise:install
$ rails g devise User
$ rails g devise:views

db/migrate以下にあるxxxxxxxxxxxxxx_devise_create_users.rbにカラムを追加します。

## Omniauthable
t.string :uid
t.string :provider

config/initializers/devise.rbにOAuth 2.0 Client IDとClient (Consumer) Secretを指定します。また、scopeに操作するデータを指定します。

config.omniauth :fitbit_oauth2, "CLIENT_ID", "CLIENT_SECRET", scope: 'heartrate'

これらの値は、Fitbitの場合は以下のサイトでアプリケーションを登録して取得することになります。CLIENT_IDはOAuth 1.0とOAuth 2.0で違ったものになります。

dev.fitbit.com

また、Callback URLを指定する必要があります。例えばRailsの開発環境で動作させるためには、以下のように指定します。

http://localhost:3000/users/auth/fitbit_oauth2/callback

app/models/user.rbにomniauthableオプションを追加します。

devise :omniauthable, omniauth_providers: [:fitbit_oauth2]

config/routes.rbにdeviseのルーティングを設定します。

devise_for :users, controllers: { omniauth_callbacks: 'users/omniauth_callbacks' }

OmniAuthのコールバックのためのコントローラーを作成します。

$ rails g controller users/omniauth_callbacks

app/controllers/users/omniauth_callbacks_controller.rbに以下の記述を追加します。

class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
  def fitbit_oauth2
    # You need to implement the method below in your model (e.g. app/models/user.rb)
    @user = User.from_omniauth(request.env["omniauth.auth"])

    if @user.persisted?
      sign_in_and_redirect @user, :event => :authentication #this will throw if @user is not activated
      set_flash_message(:notice, :success, :kind => "Fitbit") if is_navigational_format?
    else
      session["devise.fitbit_data"] = request.env["omniauth.auth"].except("extra")
      redirect_to new_user_registration_url
    end
  end
end

request.env["omniauth.auth"].except("extra")としているのは、request.env["omniauth.auth"]のままだと、Cookieのサイズの問題でエラーが発生してしまうためです。

app/models/user.rbに以下のメソッドを追加します。その際、emailについてはuidを利用したものを仮想的に入力するように指定します。これは、DeviseではUserのemailがユニークな必要があるためです。

def self.from_omniauth(auth)
  where(provider: auth.provider, uid: auth.uid).first_or_create do |user|
    if auth.provider == 'fitbit_oauth2'
      user.email = "#{auth.uid}@fitbit.com"
    else
      user.email = auth.info.email
    end
    user.password = Devise.friendly_token[0,20]
    # user.name = auth.info.name   # assuming the user model has a name
    # user.image = auth.info.image # assuming the user model has an image
  end
end

DeviseとOmniAuth関係の基本的な設定はこれで完了です。

$ rails g controller welcome index

app/controllers/welcome_controller.rbを以下のように編集します。

class WelcomeController < ApplicationController
  before_action :authenticate_user!

  def index
  end
end

app/views/welcome/index.html.erbを以下のように編集します。

<h1>Welcome#index</h1>
<p>Find me in app/views/welcome/index.html.erb</p>

<% if user_signed_in? %>
  Signed in as <%= current_user.email %>.
  <%= link_to "Sign out", destroy_user_session_path, :method => :delete %>
<% else %>
  <%= link_to "Sign up", new_user_registration_path %> or
  <%= link_to "Sign in", new_user_session_path %>
<% end %>

config/routes.rbにrootを指定します。

root 'welcome#index'

これで、OAuth 2.0を利用してFitbitアカウントとDeviseのomniauthableオプションを利用した認証が動作するようになりました。

f:id:kaorumori:20151005171512j:plain