Freelance Orgsin Official Site

ごゆっくりしていって下さい

【Ruby】モジュール(Module)のインクルード(Include)しないメソッドの呼び方

Moduleに存在するメソッドの分類

Moduleに定義したメソッドを任意のクラスのメソッドからインクルードをせず呼び出す方法を書いておきます(使うタイミングはあまりないですが)

結論から書くとinstance_methodをBindすることでほとんどのメソッドを呼び出せます.

と言いながら,それ以外の呼び方もあるのでタイプ毎に分けました.

Moduleの直下にそのままメソッド定義

最もポピュラーのメソッド定義ではないでしょうか.

module A
  def hoge
    'hoge'
  end
end
区分け
  1. instance_method
  2. public_instance_method
# 1
A.instance_method(:hoge).bind('').call
# 2
A.public_instance_method(:hoge).bind('').call

self使う

シングルトンでpublicなメソッドを作り出す.やり方が二通りある.

module A
  def self.hogehoge
    'hogehoge'
  end
end

module A
  class << self
    def hogehoge
      'hogehoge'
    end
  end
end
区分け
  1. singleton_method
  2. public_method
# 1
A.singleton_method(:hogehoge).call
# 2
A.public_method(:hogehoge).call
A.hogehoge

module_function

privateなインスタンスメソッドも作り出す.

module A
  module_function

  def fuga
    'fuga'
  end
end
区分け
  1. private_instance_method
  2. singleton_method
  3. public_method
# 1
A.instance_method(:fuga).bind('').call
# 2
A.singleton_method(:fuga).call
# 3
A.public_method(:fuga).call
A.fuga

Moduleにインスタンスメソッド定義

module A
  extend self

  def piyo
    'piyo'
  end
end
区分け
  1. instance_method
  2. public_instance_method
  3. public_method
  4. singleton_method
# 1
A.instance_method(:piyo).bind('').call
# 2
A.public_instance_method(:piyo).bind('').call
# 3
A.piyo

Moduleにprivateメソッド定義

module A
  private
  def foo
    'foo'
  end
end
区分け
  • private_instance_method
A.instance_method(:foo).bind('').call

Moduleにprivate特異メソッド定義

module A
  module_function

  def bar
    'bar'
  end
  private_class_method :bar
end
区分け
  • private_instance_method
  • private_method
A.instance_method(:bar).bind('').call

最後に

ミスっているところがあるかもしれません.その時は教えていただけると助かります.すぐに修正します.

2018年の目標

2018年

戌年.そして自分にとってもキリの良い年.

達成したいこと

インプット
  • 英語論文(AI系)を12本以上読むこと
  • テーマの情報を足でも収集すること
    • 実際に赴く
アウトプット
  • 新しい技術を実際に自分のサービスに組み込む.以下は例,論文読むとまたちゃんとしたジャンルに絞れるかも.
    • AI系
    • AR/VR
    • 暗号通貨
ビジネス
  • 事業を大きくすること
    • 具体的には,自分の働くウェイトをシフトさせ,サービスに稼いでもらうように
  • 請負案件を増やし,常駐案件を削減すること
    • 現在は請負2:常駐5 → 今年は請負4:常駐3へ
  • パッケージソフトウェアの種類を増やす
    • 自分が常に働いているという状態を減らすことが重要 → これができないと破滅する
  • 起業を視野に入れること
  • 投資
    • アンテナを張る → 実際にこれ以上新しい投資先が見つからなくても情勢把握は大切

今年必ず達成しなくてはならないこと

自分が常に働いているという状態を減らす

なぜかというと,働く==金を得るため,という方程式が成り立つからだ.我々技術者にとって,大切なことは探究心・好奇心を絶やすことなく,常に新しい技術を追い求め,検証し,アイデアに繋げ,可能性を生み出すことであるが,そんなことは言うまでもない.

ただし,上記の事を働く中で達成し続けるのは非常に困難である.それは,利益の追求がレールの先にあるかどうか中々見えないからだ.当然,ビジネスをする上で利益を出すことだけが重要ではないが,エンドユーザのためのUI/UXであれ,利便性の高い仕組みや高度な技術を提供することであれ,利益が発生しないのなら誰も金を出そうとはしない.

私は技術より,科学の方向へ指針を持ちたいという気持ちが強いらしいが,大学院の頃それをはき違えておりそのような素直に技術というより科学,という考えに至れず博士課程に進むことは断念したのだが,今なら分かる.結局技術者といいながら,科学への道を諦めきれないという葛藤を常に抱えており,それが原因だとわかった.

そのため,科学研究を続けるためには,働くだけでは難しいのだ.数多くの技術探索を続けるだけでなく,科学研究も引き続きやっていきたい.今年は,そのウェイトを増やしていくことが大切.

つまり「 自分が常に働いているという状態を減らす 」である.

本心では,働きたくないというわけではない.ただ,このまま働いてfiatに利確し続けたと思っていても,それは利確なのか損切りなのかもはや判断がつかないほどやりたいことへのフラストレーションが増大してしまう気がしている.これではストレスで精神的におかしくなってしまう可能性も高い.それを防ぐためには,2018年という年を無駄に過ごしてはならない.春.春が限界だと思っている.それを過ぎてなおそのような働き方をしているのであれば,もう決して科学という戯言を宣うべきではない.

なぜ,自分が本当にやりたいことを捨てることができるのか?そんな生き方は生き様として最悪である.誰に何と言われようと,自分の道を誤ってはいけない.

2019年に,この記事を見て,私は笑っていられるだろうか.そう思いながら記録として残しておく.

iPad Pro で ソフトウェアの開発はできるのか

目的

ソフトウェアの開発を外で手軽にしたい.長時間ならばMacBook Proを使用すれば事足りるが,毎日の通勤電車の中だったりランチの約1時間中に開発をするといった個人的な目的を達成するためにはやや重量に限界を感じる.

メイン開発端末スペック

  • MacBook Pro
    • 13インチ
    • 2.4 GHz Intel Core i7
    • 16 GB 1867 MHz LPDDR3

「Macを買うなら…」でおなじみの、秋葉館オンラインショップ
もちろん話題のiPodも本体を含め関連商品充実!

重さ

MacBook Proは,13インチでも「1.58kg」これってどれだけ重いかって言うと,例えば八百屋さんに行き.そこで焼きそばの材料買うとすると同じぐらいの重さになる.キャベツ1玉と人参,もやし,麺ね,ここらへんをスーパーの袋に入れたものを持ってると想像するとわかるけど,軽くランチに出かける時に持ち歩くような重量ではないことが分かる.

ここでiPad Proに白羽の矢が立ったわけです.10インチに関して,これの重さって言うと,500mlのコカ・コーラより軽い.コンビニでちょっとペットボトル買うことって多いのだが,それより軽いっていうのは非常に安心感がある.ランチの時に持ち運んでも違和感がないぐらい軽い.

www.apple.com

今回はApple製品だけを考えているが,持ち運びという意味ではSurface Proもあるが,これの重さはキーボードとかを付けるとMacBook Proと重さがほぼ変わらない.それならWindows限定の作業じゃない限りMacBook Proを使う.

できること

何ができるかってのを考えると,以下である.ちなみにiPhoneでもストレスなくできそうなものは省いた(メールやチャットなど)

  • 書類編集
    • ワード編集
    • エクセル編集
    • パワポ編集
  • 画像編集
    • 要件を考える時に図を書いたりする
    • 絵を書いて頭をクリアにする
    • クライアントへ説明する時にすぐ絵をかける
    • アイコンやデザインをさっと少し修正する
  • プログラミング
    • HTML/CSS/JSや簡単なプログラムであればWebのサービスを使ったり代用できるアプリを使用すれば可能
  • その他
    • MacBook Proをデュアルディスプレイにできる(※別の使用法)

実装やインフラ作業をすることは難しいが,それ以外の工程であれば作業できそうだ.

また,最後のデュアルディスプレイというのは長時間作業をするときにも力を発揮できそうだと思いこれは別件で記載.重量が2kgちかくなるというのはきついが,ガッツリやるときならあり.

Service Objectについて <uninitialized constant の対応>

Service Objectとは

DDDで言うところのDomain層のビジネスロジックの責務を抜き出したものだという認識.Railsで言えば,app/models配下の依存するモデルにロジックを記述して,肥大化しそうならQuery Objectパターンを使って切り出すリファクタリングをするだろう.それに近しいがもう少し柔軟なかたちで定義できる. 例えば,Query Objectはあくまでもクエリに興味があるものであるが,Service Objectはそれ以外のビジネスロジックが含まれていても問題はない.

実際のコード

ユーザ情報を保存する.ただし,条件によってデータを入れ替えたりするのでロジックが多くなりがち

# app/controllers/user_controller.rb
class UserController < ApplicationController

  def save
    user = User.new
    user.lastname = @lastname if @lastname.present?
    user.firstname = @firstname if @firstname.present?
    user.set_birthday(@year, @month, @day) # モデル側で誕生日を格納
    user.set_type # モデル側で特定の条件の時に対象タイプを格納
    # 省略
    user.save
    user
    # 省略
  end
end
# app/controllers/user_controller.rb
class UserController < ApplicationController
  def save
    UserService.new(params).call
    # 省略
  end
end

# app/services/user_service.rb
class UserService
  def initialize(params)
    lastname = params[:lastname]
    firstname = params[:firstname]
    @user = User.new
    @user.lastname = lastname if lastname.present?
    @user.firstname = firstname if firstname.present?
    @user.set_birthday(params[:year], params[:month], params[:day])
  end

  def call
    return if @user.birthday.nil?
    user_params
    save_user
    @user
  end

  private

  def user_params
    @user.set_type
    @user.set_sample_type
    # 省略
  end


  def save_user
    @user.save if @user.type != 'NONE'
    logger.info("【登録】ユーザ #{@user.inspect}")
  end
end

起動するとエラーが出た

NameError in UserController#save
uninitialized constant UserControlle::UserService
パスを見てみる

app/servicesディレクトリは読み込まれていたが,該当サービスクラスがrequireされていない

> ActiveSupport::Dependencies.autoload_paths.grep(/services/)
=> ["xxxxxxxxxxxxxxx/orgsin/app/services"]

> $LOADED_FEATURES.grep(/user_service/)
=> []

解決策1

依存ファイルを該当コントローラ内で直接requireする
※毎回指定するのは面倒

# app/controllers/user_controller.rb
require_dependency 'app/services/user_service.rb'
class UserController < ApplicationController; end

解決策2

初期化時にapp/serviceディレクトリ直下を全requireする(個別のファイルを指定しても問題ない)

# config/initializers/dependencies.rb
Dir[Rails.root.join("app/services/**/*.rb")].sort.each { |f| require f }

朝の4:30に書いてしまうほど悩んでいる

物事はそんなに効率的にならない。そういうことを考えることが最近多い。

 

例えば、何か特定の技術の開発を請け負ったとして、それを自宅でガリガリとコード書いていても固いアーキテクトにならざるを得ないし、運用保守を無視した提案なんてできない。本来技術を向上させるためにプログラマとして仕事をしているわけなのだが、結局そうなっていないのが現実的な話。分かりやすくプログラミングだけの話で言えば、自分が目指す綺麗な書き方、イケてる書き方をしたくても中々そうはいかない、例えばrubyでメタプロを駆使したくてもそれは難しいように。それは、自分の開発したファイルの全てがexcludeすることなしにコードチェックでwarningが出なかったとしても同じことだ。コードレビューの時間がかかるんじゃないかとか現場のレベル感を考慮してコーディングするのは避けられないし、それを無視した仕事を金の対価として納品するわけにもいかない。

 

結局、ソロでプログラマ名乗っててもなんらかの組織に従属した形になってしまう実態があるし、そういう働き方をしなかったとしても、引き継ぎの時に面倒なことはなるべく省きたい。

 

というわけで、物事はそんなに効率的にならない。技術向上や、ソロでプログラマやる!みたいな心意気は大事だが、そんな簡単な話じゃない。

また、技術をアピールしていても、上には上がいるわけで恥ずかしい思いもしたくないというダサいプライドもなかなか捨てきれない。

 

なぜ、最近そこまで深く考えるかというと、本質的ではない忖度というものに振り回されることが多いためだ。人の信頼は大切だし、誰がプロジェクトの事実上のボスかということも分かっているから簡単に自分のスキルシートの見栄えだけの為に技術を行使した話を提案するわけにもいかない。

 

ゴールはみんなそれぞれ違うと思うが、自分が何をゴールと定めるのかをしっかりと見出してプログラマやってないと今後仕事なんてできないだろう。そんなことを朝の4:30に書いてしまうほど悩んでいる。

竜は、飛ぶ時に羽を必要としない。

割と空気が澄んでいた。ただ、少し肌寒く薄着で外に出てしまったのを後悔した。嫌な予感は常につきまとっていたが、まさか竜を飼うことになろうとは思いもしなかった。

 

少し歩いた丘の先で僕はのんびりと休憩していた。2人ぐらい座れる古ぼけたベンチに座りながら、ただただ時間を消費することを楽しんでいた。

そんな時、空を見上げると割と小さめなゴールデンレトリバーぐらいのサイズの竜がいた。竜と言えば、トレーラーより大きいサイズをイメージしていたが、これがリアルの竜なのかということを知った。それは、まさに漆黒のドラゴンと呼べるに等しかった。よく見ると、そんな竜は傷を負っていたし、他の人間たちに攻撃されていた。気づいたら僕はその竜の方向へ走っていた。僕は竜を助けることにして、その人間たちを言葉巧みに誘導して竜と引き離した。人間は、竜のことを神聖な生き物だと思っているため、なぜ攻撃しているのかも結局わからなかったが、僕は真っ先に竜を助けることを選んだ。

その後竜は、僕にお礼を言い、僕は仲良くなることで竜の背中に乗せてもらった。竜の背中は意外と捕まりやすくて安定していた。僕は何度も君は羽を広げなくていいのかい?と聞いた。どうやら竜は羽を広げずに飛ぶことができるらしい。羽は威嚇のためだけに使う、とそう教えてくれた。

僕たちは天上の崖と呼ばれる場所まで行き、そこの小屋でその竜を飼うことにした。竜は、なぜか僕のペットになることを決めたらしい。僕が困っている時には一緒に戦いたい、そう言った。

その少し前、僕と竜は天空で他の竜と交戦し勝利を収めていた。竜の炎は熱く敵の竜の鱗を溶かしていった。

その時も竜は、僕が一緒にいてくれると元気が出ると嬉しいことを言ってくれた。

この後のことはあまりに悲劇であり、僕も思い出したくもないのでここで幕を閉じることにする。

【AWS】サーバレス導入・基礎編(お名前ドットコム・SES・S3・CloudFront・Certification Manager)

当記事について

最近サーバレスの相談をよく受けることもあって,せっかくなので自分のサイトも簡単にサーバレス構成にしようと思い立った.

実際S3の独自ドメインは基本行うとしても,それをHTTPS化したり,CDN化したりといったところまでは業務以外ではやらなかったのでちょうど良い機会だった.

この記事は,サーバレスの基礎編.これに今後LambdaやCognito,DynamoDBとのRelayを入れていく.その記事はまた今度書くことにする.

構成図

f:id:sinsinchang:20170717223408p:plain 構成は,お名前ドットコムで取得したドメインをSESを利用して,Certification Managerで申請したドメインで,HTTPS通信をしてCloudFrontでCDN化したS3の静的ページを表示させるというもの.

AWSの利用サービス

  • S3: S3
  • CloudFront: CF
  • Certification Manager: CM
  • SES: SES
  • Route53(今回は,お名前ドットコムのドメイン設定で代用): R

手順

  1. R: 任意のドメインを購入する(例として, example.com を買ったとする)
  2. SES: ドメインを登録する(us-east-1)(example.com)
  3. R: MX(example.com),TXT(_amazonses.example.com)レコードを登録する dig example.com mx
  4. SES: Active Rule Setを設定する(us-east-1)→Verification statusがVerifiedになればMXレコードが正常に設定されている
  5. S3: メール受信用のバケットを作成し,IAMのポリシーを設定する(グローバル)
  6. admin@example.com などにメールが届くことを確認する
  7. CM: ドメインのSSLを申請する(us-east-1)→s.example.comなどを登録する
  8. S3: 該当の場所へメールが届くので中身にあるURLにアクセスして承諾する.これは,https://us-west-2.certificates.amazon.com/approvals?code={CODE}&context={CONTENT} というURLになる.
  9. S3: 新規でバケットを作成し(Certification Managerで定義したルールと同様の名前にする),何らかの静的ページを配置する.
  10. CF: 該当のバケットと,SSLを指定する
  11. R: CloudFrontのDomainNameをCNAMEで設定する
  12. CF: StatusがIn ProgressからDeployedに変わったら完了.結構時間がかかった. dig example.com cname

※説明がわかりづらいのでもっと詳細について書いたほうがいいかも.

S3

注意点としては,一般的にS3をサイトとして公開する時のように Web Site Endpointを利用するとSSL通信ができない ということ.CNAMEをこのエンドポイントで設定するだけで,独自ドメインにできるため便利なのだが,思わぬ落とし穴であった.

docs.aws.amazon.com

公式が言っているので間違いないのだが,HTTPS化したいのならば通常のREST API エンドポイントにするしかない.

docs.aws.amazon.com

Amazon S3 バケットがウェブサイトエンドポイントとして構成されている場合、オリジンとの通信に HTTPS を使用するように CloudFront を構成することはできません。

Amazon S3 はその構成で HTTPS 接続をサポートしていないためです。

こちらでも明記されている.

REST APIエンドポイントは以下にあるので参考にしたい. docs.aws.amazon.com

Certification Manager,CloudFront

CloudFrontはus-east-1などのSSLしか受け付けていないので,SSLも同様の場所で申請する必要がある.

また, S3は元々バケットとドメインがイコール でないと表示できないという制約があるため,CloudFrontでCDN化する時もその点に注意して作成する必要がある.

例えば,cf.example.comというドメインで表示させたいなら,S3のバケットもcf.example.comという名前で作成する.

さいごに

待ちが発生する事が多いため,手順をミスると大幅な時間がかかってしまうので注意.特に先に述べたWeb Site Endpointは使わないことや,S3は元々バケットとドメインがイコールであることには注意. 今回は単純なものであるが,普通に一般的なS3のサイトにも応用できそうだったのでまとめておく.料金がいくらかかったかは,また1ヶ月後にでも追記しようと思う.