とーますメモ

Ruby on Rails / Goなどの学習メモ

【Go入門】デプロイツール「sup」の使い方

自分用メモ。

RailsならCapistranoが有名だが、Goでも同じようなツールがないか調べてみたところ
このツールが検索に引っかかったので、使い方を調べてみた。

ツール名は「sup」。
github.com

特徴は、YAML形式の設定ファイルに対象ホストやコマンドを自分で記述して
デプロイを行うこと。また1回のコマンドで複数ホストにデプロイすることも可能。

使用方法は以下。

インストール

$ go get -u github.com/pressly/sup/cmd/sup

動作確認

$ sup -v

使い方

$ sup [OPTIONS] NETWORK COMMAND [...]

NETWORKに、設定ファイルに記述した「ネットワーク名」を指定し
COMMANDに、設定ファイルに記述した「コマンド名」を指定する。

設定ファイルを作成

Supfile」という名前ファイルをルートに作成。
envの箇所で環境変数を設定。
例ではPRODUCTION_DSTはデプロイ先のディレクトリを指定し、
hosts:ではホスト毎の情報(USER@HOST:PORT)を設定する。

以下設定例。

version: 0.4

env:
  # Environment variables for all commands
  NAME: example
  PRODUCTION_DST: /home/xxx/go_deploy

networks:
  # Groups of hosts
  dev:
    hosts:
      - localhost
  staging:
    hosts:
      - USER@HOST:PORT
  production:
    hosts:
      - USER@HOST:PORT

commands:
  start-echo:
    desc: start message
    run: echo [START] $NAME HOST[$SUP_NETWORK]

  end-echo:
    desc: ending message
    run: echo [END] $NAME HOST[$SUP_NETWORK]

  # Named set of commands to be run remotely
  ping:
    desc: Print uname and current date/time.
    run: uname -a; date

  pre-build:
    desc: Initialize directory
    run: mkdir -p $PRODUCTION_DST

  upload:
    desc: Upload dist files to all hosts
    upload:
      - src: ./
        dst: $PRODUCTION_DST

targets:
  deploy:
    - start-echo
    - pre-build
    - upload
    - end-echo

上記の例では
targetsに「deploy」を設定し
一括で処理したいショートカットを設定している。

なので以下のようにコマンドを打つと、一気に4つの処理が同時に走る。

$ sup production deploy

この状態だけだと、ただデプロイしてるだけなので
ビルドから実行までのタスクも次回は書きたい。

【Github】コミット時に登録される自分のEmailアドレスを削除したい!

自分用メモ。

Githubはコミッターの判別に、登録されているメールアドレスを用いている。

GitHub uses the email address set in your local Git configuration to associate commits pushed from the command line with your GitHub account.

Setting your commit email address in Git - User Documentationより


そのためPUSHすると登録されているメールアドレスがコミット内容と共にGitに登録されてしまう。

つまり、自分のアドレスが色んな人に見えてしまうということ。
自分のアドレスを世の中に晒したくない場合は以下の設定を行えば良い。

設定ページのEmail内で、以下の設定にチェックを入れる。
1)Keep my email address private
2)Block command line pushed that expose my email.

1)にチェックを入れると、下画像の位置に「noreplyアドレス」が表示されるので
f:id:Thoames1212:20180108052832p:plain

それをローカルgitのEmailに割り当てればよい。

$ git config --global user.email "XXXXXXXX@users.noreply.github.com"

以上の設定をすることで、コミットしてもプライベートなメールアドレスが
コミット内容と共に登録されることはなくなる。

[参考]
qiita.com
stackoverflow.com
qiita.com

【Shopify × Rails】ShopifyAppに手動でログインする方法

自分用メモ。

shopify_appを使用しているなら通常は
未ログイン状態の場合、ログイン画面に遷移し、omniauthを通じた認証が行われる。

認証後はセッションにShopify情報にアクセスするためのセッションが保存される。

ただ自分の場合、Activeadminと組み合わせて使用する。
その場合、ShopifyApp::AuthenticatedControllerを継承したコントローラをActiveadminでは
作れないっぽいので、どうにかしてShopifyログイン経由でActiveadminのコントローラにアクセスしたい。

そのためには、一度ShopifyApp::AuthenticatedControllerを継承したコントローラにアクセス後
リダイレクトして飛ばしてやればよい。
また各Activeadminコントローラに以下の設定をすれば
セッション切れを起こしてもログイン画面に遷移し、ログイン認証を再び行える。

  controller do
    include ShopifyApp::LoginProtection

    before_action :login_again_if_different_shop
    around_action :shopify_session

    def index
      super
    end
    ...
  end

[参考]
https://github.com/Shopify/shopify_app/blob/b22824003af168298d727f639a49503d29ca2ac6/app/controllers/shopify_app/authenticated_controller.rb https://github.com/Shopify/shopify_app/blob/53b2807fed4c45590b3feb5445d05c702af6524b/lib/shopify_app/controller_concerns/login_protection.rb

【Google Home】IFTTT(イフト)との連携

f:id:Thoames1212:20180104074227p:plain

IFTTT(イフト)とは、
複数のサービスを連携させることができる「仲介サービス」のこと。ちなみに無料。
名前の由来は、「IF THIS THEN THAT」の頭文字をつなげたものだが
連携させるサービスもこの名前の様式通り、

"これ"をしたら、"あれ"をする。と言った具合に
2つの異なるサービス同士を連携できるといったものになる。

例えば
・写真を取ったら、Facebookに自動投稿する。
・Youtubeの"後で見る"を押すと、それがEvernoteに自動保存される・
・明日の天気が雨なら、メールで知らせる。

何ていうことが簡単にできる。

一からサービスを作成することも凄い簡単にできるが、
既に色んなサービスが予め登録されているので、それをそのまま使うこともできる。
※ほとんど英語。

アカウント作成

Gmailがあればすごい簡単に出来た。
f:id:Thoames1212:20180104074952p:plain

サービス検索

ログイン後、「Search」をクリック
f:id:Thoames1212:20180104075241p:plain

いろんなサービスがある。
f:id:Thoames1212:20180104075419p:plain

次回は何か自分のサービスを作ってみる。

【Activeadmin超入門】CanCanCanの設定 〜その2〜

前回の【Activeadmin超入門】インストール・環境設定 〜その1〜 - とーますメモに続けて、権限管理を行うためのCanCanCanの設定を書いていく。

前の記事にも書いたとおり、CanCanCanはCanCanの後継プロジェクトであり、
設定の仕方はCanCanと同じように記述できるっぽい。(違ったら教えて。)

ちなみに権限を設定する場合、以下の2つのケースがあると思う。

1)1ユーザに、1つの権限を付与
2)1ユーザに、複数の権限を付与

それぞれの場合で、どのように設定するかをメモ書き。
また権限は「admin」と「manager」の2つとする。

1)1ユーザに、1つの権限を付与

①DB変更

まずは下準備に、権限を保存するカラムをdeviseが作成する"admin_users"テーブルに追加する。権限を保存するカラムとして、roleを追加する。このカラムの値のバリエーションはそこまで沢山無いため、データ型はEnumにする。

$ bundle exec rails g migration add_role_to_admin_users role:integer

生成されたマイグレーションファイルに「null: false, default: 2, :after => :encrypted_password」を追加。
自分はカラムの位置も気にするので、encrypted_passwordの後にroleカラムを配置。

class AddRoleToAdminUsers < ActiveRecord::Migration[5.1]
  def change
    add_column :admin_users, :role, :integer, null: false, default: 2, :after => :encrypted_password
  end
end

そしてマイグレーション

$ bundle exec rake db:migrate

②Enum設定

models/admin_user.rbで「enum role: { admin: 1, manager: 2 }」を追加

class AdminUser < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable,
         :recoverable, :rememberable, :trackable, :validatable

  enum role: { admin: 1, manager: 2 }
end

③Abilityクラスの生成

CanCanCanでは権限設定をこのAbilityクラスで行う。

生成方法は以下

$ bundle exec rails g cancan:ability

生成されたability.rbに[admin]と[manager]の権限設定を行う。
以下の例はadminには全権限を与え、
managerには、dashboardページには全権限を与え、
AdminUserページには読込権限のみを与える設定。

app/models/ability.rb

class Ability
  include CanCan::Ability

  def initialize(admin_user)
    admin_user ||= AdminUser.new
    if admin_user.admin?
      can :manage, :all
    elsif admin_user.manager?
      can :manage, ActiveAdmin::Page, :name => "Dashboard"
      can :read, AdminUser
    end
  end
end

ロールに付与できる権限の基本は5つ。
「create、read、update、destroy、manage」
manage以外は、名前の通りの意味。

manageは「CRUD全て」という意味ではないらしく、
独自で設定した権限も含めての全権限という意味らしい。。。(あってるかな?)
詳細は以下のサイト様より。
How to use CanCan / CanCanCan - Qiita

また権限設定は順番が大事で、競合する設定がある場合
最後に適用されたほうが有効になるっぽい。


ちなみに権限にはエイリアスも設定できる。デフォルトでは以下の設定がされている。

alias_action :index, :show, :to => :read
alias_action :new, :to => :create
alias_action :edit, :to => :update

一行目の例で行くと、:indexや:showという権限も:readとして使用できるということだろう。

※[Note] ちなみにactiveadminで作成できるページの種類は、以下の2つ。

1)モデルに紐付いたページ(例:AdminUserページ)
2)モデルに紐付いていない独立したカスタムページ(例:Dashboard)

④current_ability関数のオーバーライド

Abilityクラスのinitializeはコントローラ上に定義された
current_abilityメソッドによって呼び出されるため、
必要に応じて適切な設定をする必要がある。

CanCanCanはcurrent_abilityのデフォルト処理では
現在ログインしているユーザ情報を"current_user"から取得する設定になっているが
activeadminインストール時に、deviseを一緒にインストールすると
ユーザを管理するモデルがAdminUserになるため、現在ログインしているユーザ情報は
"current_user"ではなく"current_admin_user"に入っている。

そのため、current_abilityメソッドの中身を以下のように変更する必要がある。

class ApplicationController < ActionController::Base
  protect_from_forgery with: :exception

  def current_ability
    # before
    # @current_ability ||= Ability.new(current_user)

    # after
    @current_ability ||= Ability.new(current_admin_user)
  end

⑤CanCanCanの有効化し、認証されたかった場合のメソッド定義

active_adminの設定ファイル内でCanCanCanを有効化する。

ActiveAdmin.setup do |config|
  ...
  config.authorization_adapter = ActiveAdmin::CanCanAdapter
  config.cancan_ability_class = "Ability"
  config.on_unauthorized_access = :access_denied
  ...
end

1行目でCanCanCanを有効化し、
2行目でCanCanCanの権限管理クラス名を指定し
3行目で認証されなかった場合の処理を行うメソッドを指定する。

認証されたかった場合のメソッド定義(access_denied)は、application_controller.rbに記述

def access_denied(exception)

    # 権限がなくてアクセスできないページはダッシュボードへ飛ばしてメッセージを表示
    # 認証が切れてアクセスできない場合はログイン画面を表示
    if current_admin_user
      redirect_to admin_root_path, alert: I18n.t('active_admin.access_denied.message')
    else
      redirect_to new_admin_user_session_path, alert: exception.message
    end
  end

⑥AdminUserのindex及びformブロックにrole情報を入れる

自分は以下のように設定した。
app/admin/admin_user.rb

ActiveAdmin.register AdminUser do
  permit_params :email, :password, :password_confirmation, :role

  index do
    selectable_column
    id_column
    column :role
    column :email
    column :current_sign_in_at
    column :sign_in_count
    column :created_at
    actions
  end

  filter :email
  filter :current_sign_in_at
  filter :sign_in_count
  filter :created_at

  form do |f|
    f.inputs "Admin Details" do
      f.input :email
      f.input :password
      f.input :password_confirmation
      f.input :role, as: :radio, :collection => [
        ['Admin', 'admin'],
        ['Manager', 'manager']
      ]
    end
    f.actions
  end

end

具体的に追加したのは、
(1)permit_paramsに:roleを追加
(2)indexブロックにcolumn :roleを追加
(3)formブロックにf.input :role...を追加


以上でユーザの追加・編集及び権限管理もできるようになる。

[参考記事]
How to use CanCan / CanCanCan - Qiita
【Rails】ActiveAdmin+CanCanCanで権限毎に色々したい - Qiita
CanCanCanを使ってみる - Qiita
Rails4でCanCanCanによる権限管理 [俺の備忘録]


2)1ユーザに、複数の権限を付与

CanCanCanの設定は1)と似ているが
それ以外が結構違う。

詳細は以下のサイトさんが詳しいので参照されたし。

blog.hello-world.jp.net
sessan.hatenablog.com