Translate

ラベル Rails の投稿を表示しています。 すべての投稿を表示
ラベル Rails の投稿を表示しています。 すべての投稿を表示

2018/11/29

ServiceObject じゃなくて、ActiveInteraction を使おう(^^)

Fat Controller の対策としてよく話題になる ServiceObject。でも、実際使ってみるとあんまりしっくりこなかったです。

感想:
・そもそも、使い方があいまい。#call ? #run ?  #perform?
・複数のクラスを操作する場合は、Facardになるの?
・外部APIの操作もServiceObjectでいいの?
・インターフェースの記述ルールが定まらない。

ServiceObject(サービス層)についての説明:
https://techracho.bpsinc.jp/hachi8833/2017_10_16/46482
https://qiita.com/joooee0000/items/369fd4676cd9dfb1f6eb
https://techracho.bpsinc.jp/hachi8833/2017_12_07/48363

ServiceObjectをアンチパターンとする記事:
https://techracho.bpsinc.jp/hachi8833/2018_04_16/55130

次の一歩

ブログ記事などを漁るなかで、こちらで紹介されている ActiveInteraction を使ってみることにしました。


○ 使ってみてよかった点:
・Gemの使い方として、ファイル構成やインターフェースが定義されていて、迷いがない。
・Validationも使える。さらに、多言語化をしやすい。
・Facard としても、Formとしても使えるし、外部API操作も実装しやすい。

☓ 良くない点:
・#run か #run! で戻り値が変わるので、それに応じた使い分けが必要。
・インターフェースの記述を覚える必要がある。

これから

1年くらいちょこちょこ使ってみたところ、少なくとも ServiceObjectよりは長期的な運用に耐えられると思いました。今後もありがたく継続して使っていく予定ですが、ブログを書いている中で改善したいところを思い出したので、本家にフィードバックしていこうと思います(^o^)

2016/06/17

Webサイトの決済に、Amazon Paymentsを実装した。 そうRuby On Railsで。

仕事でAmazon Paymentsを使って決済機能を開発したので、そのまとめ。

まとめ

報告書は最初に結論が大事。ということで、早速まとめ。
  • Amazonが提供しているDocumentやサンプルが豊富でとても助かった。
  • サーバーサイドとフロントエンド(JavaScript)の両方で実装する必要があったので、他の決済と比べると理解に時間がかかった。
  • 仕様はオープンだが、ネットでの実装事例はなくて、完成イメージを持てずに苦労することもあった。
    →この記事がその助けになったら嬉しい。
  • サイトのUXはすごく向上したと思う。個人的にAmazonをよく使っていることもあり、Amazonログイン→支払いはとにかく簡単。
  • Amazon Paymentsのアカウント開設前に、すぐに使えるテスト環境はないため、事前の技術検証がほぼできなかった。Ruby SDKをAPI通信をスタブして、コードはかろうじて動かせた。これが改善されたら、もっと導入するところが増えると思う。他の決済サービスは準備されていることが多いらしい。
    (もちろん、サンドボックス環境はある)
  • 決済サービスってどれを選べばいいの?って決めるまでは全然決められなかった。考えれば考える程、どれでも同じなような。でもとにかくAmazonログインのUXを優先して決めてよかったと思う。Paypal, WebPayとかは導入はいいと思う(事例やドキュメントが多い)けど、UXの向上は見込みないので。

決済機能とは?

有名なのはPaypal、その他にも最近はいろいろあって、結構群雄割拠。

去年くらいまではPaypalっぽい専門の決済サービスが多かったようだが、大手ECサイト(Amazon / 楽天 / Line ?)が参画して、今後はこっちに流れていくような気がする。

理由は、既にアカウント持っている人が多ければ、その人はすぐに支払いができるから。
ユーザーには、決済のUIはあんまり重要じゃないと思う。
また、使っているサービスで支払いできた方が安心感もある。Amazonはそれを謳ってもいる。

Amazon Paymentsって?

って動画を見ても、あんまり理解できないと思う。
要は、Amazonでログインボタン、Amazonでお支払いボタンを自サイトに埋め込んで、Amazonアカウントで支払いができるということ。

決めた理由:
  • UXの向上
    →Amazonでログインは効果があるはず
  • 支払い手数料
    →競合と比較して大体同じ
  • 運営者の使い勝手
    →Amazon Seller Centralという、Amazonマーケットプレイスと同じプラットフォームで、安定
  • 定期支払い
    →会員年会費の支払いに使いたかったので、必須

サービス名がところどころ、Amazon ログイン&ペイメント とかってなっていてよくわからなくなるけど、多分世界的に共通な名称がAmazon Paymentsで、日本のサービス名がAmazon ログイン&ペイメントってことのよう。

大差ないが、APIはログインとペイメントで分かれているので、一応気にしておく必要はある。Ruby SDKは同じような名前のメソッドだけど。

Documentが豊富

amazon.co.jpでは問い合わせしないとDocumentがもらえない(なのでここで公開することは適切でないと思う)
しかし、amazon.comでは普通に公開されているので、こちらを参照するといい。
Forumもあって、質問すれば、1日くらいで回答きた。

実装

動線がすごくわかりにくいけど、こんな素晴らしいモックが用意されていて、これにかなりお世話になった。
使ったRuby SDK(gem)はこちら。

詳細はインテグレーションガイドを参照してもらうとして、概要はこんな感じ。
  1. JS(JavaScript)でログインボタンと支払いボタンを実装。
  2. ボタンを押すと、AmazonのJSがアカウントを認証し、指定したコールバックURLにリダイレクト、クエリパラメータでアクセストークンがついてくる。
  3. アクセストークンを使って、ユーザー情報を取得したり、支払い処理を実行する。
今回は、調べながらで2週間くらいで基本的な実装はできた。
Ruby SDKを使ったモックを自分でも作ったので、参考にしてもらえるとうれしい。
HerokuでPreviewも提供していて(Readme参照)、実際にはログインできないが、Amazonのログインウィンドウが出てくるところまでは見ることができる。

おまけ

Ruby SDKを使わせてもらったけど、日本のサンドボックス環境のEnd pointが間違っていたので、Forkして修正した。よかったら、こちらをどうぞ。

あと、細かいハマりポイントなども、質問されればなるべく回答しますので、お気軽にコメントどうぞ〜

2016/06/13

Elasticsearch をRuby On Railsで。

タイトルのとおり、Elasticsearch をRailsで実装したので、そのまとめ。

やったこと


  1. RakeタスクでcsvなどのファイルからElasticsearchにIndexを作成
  2. 作成したIndexをModelで検索

コア部分のソースコード

https://github.com/Samemura/Elasticsearch-rails-example

解説

だいたいのことは、Githubを見ればわかるので、ここでは検索まわりを中心に紹介する。
今回はAmazon Elasticsearch Service を使ったが、基本はこちらの記事で全てまかなえた。
bool: { term: { 検索対象 => 検索する値 }} 
term を繰り返して、検索対象を追加する。

OR検索

bool: { should: { 検索対象 => 検索する値 }} 
should を繰り返して、検索対象を追加する。

NOT検索

bool: { must_not: {bool: { should: { 検索対象 => 検索する値 }}}
should を繰り返して、検索対象を追加する。

RANGE検索

range: {検索対象: {lte: 値}}
lte は以下。
この時にDateの値の場合は、きちんとフォーマットを定義しないと、範囲チェックできない。
        type: date
        analyzer: standard
        format: yyyy/MM/dd

ページング

{size: 件数},
{from: 開始件数}

ソート

{sort: {ソート対象: desc} }
desc は降順

集計

aggregations: {agg_hits: {terms: { field: 集計対象, size: サイズ } # size = 0 means Integer.MAX_VALUE. https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-bucket-terms-aggregation.html#_size
集計結果を取得できる最大件数を指定する。0は無制限。よく使うのはTop10とか。

AWS認証

AWSのIAM認証でアクセスしたい場合は、こちらのGemを使えば簡単にできた。意外と情報は少なかったので、ハマった。

2016/05/02

Twitter API, favoritesのレスポンスの考察

RailsでTwitterAPIを使ってfavoriteを取得する処理を実装したけど、表示が遅かったので、調査してみた。

前提:
gem Twiiter

コード:
client.favorites(count:200)
clientは別途初期済み

計測:
MiniProfiler gem を使って計測。導入が簡単でかなり助かった。
http://yachibit.hatenablog.jp/entry/2013/05/29/004756

count:200

API getで合計500msくらいかかっていて、これは厳しい。
他のリソース使ったことないけど、favoriteは特別遅い気がする。
以下、いくらか処理を変えてみたけど、変化なし。

結論:
バックグランドで取得する。
取得件数・検索範囲を変えても効果ないので。

count:10
since_idを付加して、直近のツイートから検索。

2016/04/13

Ruby On Rails でTwitter連携アプリのプラクティス

Webでも記事が多い情報になりますが、実際にきちんと運用できるレベルの実装をするとそれなりにポイントがあったので、ブログとしてまとめてみます。
また、最後にTwitter gemを使ったベストプラクティスとして、モジュール化したコードを載せておきます。これはWeb上にもなかなかないので、ぜひ参考になれば幸いです。

参考:
https://syncer.jp/twitter-api-matome
https://takuyokomizo.com/ruby-twitter-api/

Twitter認証

gem omniauth を使いました。https://github.com/intridea/omniauth
使い方は、wikiが詳しいです。特に難しいことはなし。
以降は、情報が少ないものに絞って列挙しておきます。

TokenをSessionに保存

    auth = request.env['omniauth.auth']
    session[:access_token]        = auth['credentials']['token']
    session[:access_token_secret] = auth['credentials']['secret']
    session[:username]            = auth['extra']['raw_info']['screen_name']
    session[:profile_image_url]   = auth['extra']['raw_info']['profile_image_url_https']
このときに、なるべく情報を保持しておくと、API回数制限を少しでも回避できる。
使える情報は、こちらから。https://github.com/arunagw/omniauth-twitter

テスト

wikiどおりで基本はOK.
 @auth_resp = {
      provider: 'twitter',
      uid: '123456',
      info: {
        nickname: 'johnqpublic',
        name: 'John Q Public',
        location: 'Anytown, USA',
  。。。
    OmniAuth.config.test_mode = true
    OmniAuth.config.mock_auth[:twitter] = OmniAuth::AuthHash.new(@auth_resp)

authのテストデータは、TwitterAPIのExampleレスポンスを基にするとよい。

認証失敗のテストは、バグがあってWikiどおりにはできない。
OmniAuth.config.mock_auth[:twitter] = :invalid_credentials
これをやっても、Failureのパスには飛んでくれない。
通常のパスに飛んで、CredentialsがInvalidになるだけ。

Twiter API

client

gem 'twitter' を使った。使い方は、参考URLが詳しい。
テストなどに使うデータは、Twitter APIのページを見ると例がのっているので、それを流用すると簡単。

update profile image

このAPIを使用したところ、レスポンスでくるprofile_image_urlは更新前の情報になることがあった。これは、Twitter側でデータを更新するタイミングで発生していると思われ、その時によって、発生頻度はまちまち。頻発するときもあれば、出ない時もある。
対策は、レスポンスを使わずに、自サーバーで保持しているデータを使うことにした。
本質的な解決とはいえない気もする。
APIで取得しなおすと、レートリミットに+1されてしまうので。

APIレートリミット(回数制限)

こちらも既にWebで情報があるので、簡単に。
https://dev.twitter.com/rest/public/rate-limiting
15分に15回のAPIのアクセス制限あるよということ。世のアプリも結構引っかかることが多いらしい。
今回とった施策は、
・認証時のレスポンスをなるべく使う。
・既に持っているデータはなるべく取得しない。

TwitterアイコンのdefaultイメージはCORS

defaultイメージ(卵アイコン)は、URLのドメインが通常とは異なり、CORSが許可されない。つまり、直接HTMLに画像をURLで埋め込むことはできない。
対策:
予めdefaultイメージを保存しておいて、ドメインが変わったらそちらを使う。
defaultイメージは、7種類あって0からの連番だった。(自分が確認した時点で)
使用した正規表現 regex = /http.*default_profile_images\//

その都度、wgetでローカルに保存してそれを使うこともできたが、実装のインパクトが大きかったので、上記方法を採用した。

CORS(Cross-Origin Resource Sharing)は、その名の通り、ブラウザがオリジン(HTMLを読み込んだサーバのこと)以外のサーバからデータを取得する仕組みです。http://dev.classmethod.jp/cloud/cors-cross-origin-resource-sharing-cross-domain/

Twitter client module

https://github.com/Samemura/twitter-client-practice


2016/02/05

Rails TutorialでPort 3000がロックされた

ローカル環境でPort 3000をオープンしようと思ったら、できなくなっていた。

どうやら、SSLの設定をWEBrickにすると、ロックすることがあるらしい。

http://d.hatena.ne.jp/seinzumtode/20120501/1u335886009

対策:

MacのNetwork utility でPortscan でチェックする。ポート確認。

ブラウザのキャッシュをクリア。

$ lsof -i:3000
$ kill プロセス番号

Port:3000をひらけるようになった。

2016/02/01

VMをVagrantで作って、CentOSにRails をインストールする(Mac)

以下サイトを参考に、VagrantでのRoR環境を構築。

全てインストールしたところで、Vagrant起動するとエラー発生。
ChefのURLでエラーが起きているが、簡単にできそうになく、Chefを使わずVagrantのみでVM起動するようにしてみる。(Officialのページに従い)

使用したのは、CentOS/7。Atlasから探した。

Vagrant は起動できるようになった。そこから、今度はRailsを準備、公式に従って。

Cent OSは、yum でインストールする。
yum install git
yum install -y openssl-devel readline-devel zlib-devel

以前の記事に従い、rbenvをインストール。

次にようやく、gemを入れる。
git clone https://github.com/rubygems/rubygems.git ~/.rubygems
ruby .rubygems/setup.rb


Ruby 公式はこれ。

gemが入って、Railsがようやく入った。

blogを作ってみる。Bundleでインストールする。
bundle install --path vendor/bundle

sqliteのエラー。
SQliteをインストール。

therubyracerのエラー。
sudo yum install gcc-c++
こちらのサイトがとても助かった。

ようやくRails sができた。
bundle exec rails s -b 0.0.0.0
IPアドレスの指定が必要。

ホストOSでブラウザ表示できない。
ポートの設定が必要。Vagrantfile:
  config.vm.network "forwarded_port", guest: 3000, host: 3000
(その他の設定も参考になる。)

で、ようやくBlogが表示された。

2015/10/13

Windows でRuby、そしてRails

インストールして、Railsまでいれてみた。

gemによるRailsのインストールがうまくいかない。
Proxyの設定が必要らしい。

>set http_proxy=http://proxy.alps.intra:8080
>set https_proxy=https://proxy.alps.intra:8080

うまくいったので、環境変数に設定しておく。

あと、gem を最新にした。
gem update --system




からのRails入門

rails new blog
で作成して、そのままとりあえず、
Rails server
あえなく、エラー。やはりDBの設定が必要っぽい。と思ったら、Default のSQLite3がインストールされていなかったみたい。
gem install sqlite3

それでも、だめ。`require': cannot load such file – sqlite3 となる。
多分、RailsからのSqliteのバージョンの問題。

bundle update sqlite3
これで。sqliteはOKになった。

今度はNokogiriが参照できない。調べると、使用しているRuby 2.2.3 (Windows)ではNokogiriが対応されていないらしい。
しょうがないので、プログラムの追加と削除からRubyをアンイストールして、RaisInstallerから安定バージョンを使う。

今度は、AWSでインストーラーがダウンロードできない。しょうがないので、まとめサイトと同じバージョンにする。Ruby2.0、Rails4.1
ようやくできた。




ちなみに、RailsのDefaultサーバーはWebrick。
サーバーはこちらの説明を参照。要は、ローカルのフォルダ共有でHTMLを見ているのを、安全にHTTPとしてやってくれるってこと?

Webrickは実装時に手軽で役立つらしい。DeployはApacheとかなのかな。






Railsの仕組み解説