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

Androidはワンツーパンチ 三歩進んで二歩下がる

Android卵プログラマーの記録ブログ

超うっかりで落胆。freeeを退会しようとしてネットで手続きしたけど、営業時間内でないと再申し込みしないといけないのを忘れて会費を引き落とされた。

私が忘れたのがいけないのですが、共有しておけば誰かの役に立つかもしれないので書いておきます。
フリーランス青色申告に役立つ会計アプリケーションのfreeeってありますよね。

www.freee.co.jp

今までこれを使って便利だったのですが訳あって解約することにしました。
退会する方法はこれですね。

freeeから退会する – freee ヘルプセンター

で画面の指示に従って「お支払い停止手続きに進む」を押したのですが、次のような画面が表示されました。
画像は公式サイトからです。

f:id:sakura_bird1:20170410150243p:plain

ちゃんと読めば書いてあるんだけど、どうも当時の私は向こうから電話がかかってくるんだなと思って忘れてしまいました。
手続きのリンクを踏んだことでとりあえず退会の申し込みはしたような気になってしまいました。
それで電話を待てばいいのだろうとのんきに構えていました。

当然何事も起こらず電話もかかってくることなくばっちり会費を引き落とされていました。
f:id:sakura_bird1:20170410150743p:plain

あーもったいない。
ぼんやりしすぎな自分に対する怒りがこみ上げてなんだか落ち込みました。
受付できませんでしたとか自動配信メールくれてもいいのに、とかちょっと思いましたが、
退会はどこもわかりにくかったり面倒くさいことが多いので気を引き締めていかなければなりませんね。

さっきあらためて停止手続きをしたのですが、確認の自動配信メールとか何も来ていないです。
あと、公式サイトにある「お支払い停止リクエストフォーム」が表示されなかったのですが、
チャットで質問したほうがいいのかどうか迷いますが、これから電話かかってくると思うのでその時に聞いてみようと思います。
こういうものなのでしょうかね。







ポケット糖質量にスマホ向けAPIを追加

こんにちは。さくらです。
www.pockettoushituryou.com

ポケット糖質量でスマホのクライアントアプリを作りたいなと思っています。

サイトの横幅を縮めると下の画像のように縦長で間延びして見辛い印象です。

f:id:sakura_bird1:20170408191353p:plain

とりあえずAndroid版を作って(iOS版も作りたいけどスキルがないのだった)みようと思っています。


今日はそれ用のAPIを追加しました。
最初grapeというgemを使ってAPIを書こうと思っていたのですが、自分のアプリにはいらない気がしてrailsデフォルトのまま作っています。

/api/v1/kinds
のような形でアクセスできるようにnamespaceをこのように定義しています。

config/routes.rb

Rails.application.routes.draw do

  namespace :api, format: 'json' do
    namespace :v1 do
      resources :kinds, :foods
    end
  end

フォルダはこのような構成です。
f:id:sakura_bird1:20170408192005p:plain


コントローラーはこんな感じです。
app/controllers/api/v1/kinds_controller.rb

module Api
  module V1
    class KindsController < ApplicationController
      include Authentication

      before_action :authenticate

      def index
        @kinds = Kind.all
        j = @kinds.to_json(only: [:id, :name, :type_id])
        render json: j
      end
    end
  end
end

include Authentication としているのは、上のフォルダの構成の画像で言えば
app/controllers/concerns/authentication.rb
のAuthentication Moduleになります。
HTTPヘッダーに付加するトークンで認証処理をしています。
こちらを参考にさせていただきました。ありがとうございます。
qiita.com

ソースはこんな感じです。

app/controllers/concerns/authentication.rb

module Authentication
  # you might need to include:
  # include ActionController::HttpAuthentication::Token::ControllerMethods

  def authenticate
    authenticate_token || render_unauthorized
  end

  def authenticate_token
    authenticate_with_http_token do |token, options|
      token == ENV['HTTP_HEADER_TOKEN']
    end
  end

  def render_unauthorized
    # render_errors(:unauthorized, ['invalid token'])
    obj = { message: 'token invalid' }
    render json: obj, status: :unauthorized
  end

end

これで特定のトークン文字列がヘッダーに付加されていなかったらアクセス拒否されます。

確認はコマンドラインから次のように叩きます。成功するとJsonが表示されます。

curl -X GET -H 'Authorization: Token hogehoge' -H 'Content-Type:application/json' http://localhost:3000/api/v1/kinds

ブラウザから確認する場合はChrome Extensionなどのツールでヘッダーを付加できるツールがあるので活用しつつURLのところに
http://localhost:3000/api/v1/kinds
と入力します。私は教えてもらったModHeaderを使用しました。下の画像のように入力します。

f:id:sakura_bird1:20170409003942p:plain


サーバーにHTTP_HEADER_TOKENの環境変数を設定するのを忘れないようにします。

私の使っているサーバーはherokuなのでこのようなコマンドになります。

$ heroku config:set HTTP_HEADER_TOKEN="hogehoge" --remote staging

$heroku config:set HTTP_HEADER_TOKEN="hogehoge" --remote production

あとはデプロイしてstaging,productionのドメインでテストします。



2017/04/17追記
jsonを作る箇所をこのように定義していましたが、これだと思ったようなJsonの形にならないので変更しました。

        @kinds = Kind.all
        j = @kinds.to_json(only: [:id, :name, :type_id])
        render json: j

結果は↓のように、配列には名前が付いていません

[{"id":1,"name":"穀類","type_id":1}
,続く]

↓のように配列にkindsという名前を付けたいのでした。

{"kinds":[{"id":1,"name":"穀類","type_id":1},続く]}

このように変更して望みどおりになりました。

        kinds = Kind.select('id, name, type_id')
        hash = { :kinds => kinds }
        render :json => hash



>Ruby on Rails 5アプリケーションプログラミング [ 山田 祥寛 ]

価格:3,888円
(2017/4/9 00:57時点)
感想(0件)



>Ruby on Rails 5 超入門 [ 掌田津耶乃 ]

価格:2,916円
(2017/4/9 00:55時点)
感想(0件)



>実践Ruby on Rails 4 [ 黒田努 ]

価格:3,780円
(2017/4/9 01:01時点)
感想(0件)



>パーフェクトRuby on Rails [ すがわらまさのり ]

価格:3,110円
(2017/4/9 01:00時点)
感想(0件)



>はじめての「Ruby on Rails」5 [ 清水美樹 ]

価格:2,484円
(2017/4/9 01:00時点)
感想(0件)

Ruby on Rails初心者ですがWebアプリケーション「ポケット糖質量」をリリースいたしました!

Ruby on Rails初心者ですがWebアプリケーション、「ポケット糖質量」をリリースいたしました!
よろしければ使ってみていただけるとうれしいです。

www.pockettoushituryou.com

現在こんな見た目です。

f:id:sakura_bird1:20170405210037p:plain


f:id:sakura_bird1:20170405210122p:plain




前提

一応Androidアプリを作ることが出来ます。
ここのところRailsを勉強しています。
ドットインストールRailsチュートリアルを一度やっただけなので、まだまだ初心者です。

何故Webアプリ(ミニWebサービス?)を作ったのか

  • まずは勉強目的です。一人でWebアプリが作れることを実感したかったし、これをきっかけに個人開発を加速させたかったのです。
  • 糖質量を検索できるアプリは体重を支える技術にとって必要なので、最悪ユーザーが一人(自分)確保出来ているので失敗してもまあいいかと思えました。
  • ウェブサイトの運営は未知の領域ですがやってみたいと思っていました。今後もメンテナンスをして少しでも収益を出せたらいいなと考えています。

「ポケット糖質量」について

これがどんなアプリなのかといいますと、非常にシンプルです。

  • メニューから選択すると糖質量が一覧表示出来る。
  • 検索フォームから検索すると糖質量が一覧表示出来る。

以上であります(*^_^*)
初期データはcsvファイルから投入しております。全て手入力のデータです。

それだけなんですが、Rails及びRuby及びWebフロントエンド及びサーバー運用及びサイト運営初心者の私には恐ろしく勉強になりました。
というか、Web開発は範囲がやたら広くてどこに行っても無知の海が広がっていてめっちゃ大変でした。
これぐらいのミニアプリが修行にはちょうど良かったです。
もっと複雑なユーザー管理などを最初から作り込もうとしていたら挫折してた気がします。

開発期間は2ヶ月ほどなのですが、Railsでコードを書いている時間は以外と短く、大量の糖質量データの入力とWebページの見た目作り(とRailsの連携)に時間がかかりました。

Railsは便利なgemやメソッドがたくさんあってコードが非常に短く書けたりするのですが、そこに至るまでひたすら調べ物をするという感じでした。
この程度のアプリでは「プログラミング」はほとんど必要がなく、RailsAPIRubyのgemやたまにRubyの構文を勉強すれば大体まかなえました。

少し脱線しますがプログラミングの初学者であれば、Railsをいきなり勉強するよりじっくりRubyを勉強した方が絶対いいと思います。
私はAndroidの開発をやる前はプログラミング自体初心者だったので、Javaの勉強を半年ぐらいやって、OracleのJava6の認定試験を取ったりしましたが、今思うと正解だったなと思います。
この過程がなかったら今よりもっとコピペウーマンであったことでしょう。




学習方法

学習サイト

実のところ学習サイト、本ともに完走してません。
Railsチュートリアルは最後の章をやってないのですが、Railsの知識がほぼゼロでも解説が詳しく、実際にサーバーにアプリをデプロイするので大変勉強になりました。
またRailsチュートリアル本ではありませんが、
「Webを支える技術 ── HTTP,URI,HTML,そしてREST」
を事前に読んだのが大変良かったです。RESTって?みたいなRailsで当たり前の概念が解説されています。





作った感想

  • 出せて嬉しい♡
  • まだまだわからないことだらけ。もうぜーんぜんわかってない。
  • Railsすごい。噂通り素早く開発ができる。
  • サーバーにデプロイすると上手くいかなかったり思ってもいないことが起きる。サービスを動かし続けるって大変なんだろうなあ。
  • いっぱいぐぐった中で知見を提供してくださった見知らぬ方々への尽きない感謝の気持ちがむくむく湧いた。
  • 実際にリリースすると色々やることがある。すごく時間かかる。




出来てないこと&今後

  • RubyRailsやフロントエンドの勉強。
  • テンプレートエンジンにERBを使っているけど、slimかhamlにしたい。
  • テストを書く
  • レスポンシブになっているもののスマフォから見辛い。ネイティブアプリが欲しい。
  • スマフォアプリに向けてAPIを開発
  • サイト自体にもう少し記事などコンテンツが欲しい

システムの構成

スペシャルThanks

もくもく会でお会いする方々。
一人開発だと怠けてしまって一向に進まないので、外に出て刺激をもらうことが後押しになりました。





Herokuデプロイ後にdb:migrateが失敗した時の状況とやったこと

Rails勉強中です。Heroku使用経験もほとんどありません。
トラブル時に途中で混乱して手順を忘れてしまっている部分が多いのですが、
よい勉強になりましたので作業のメモを残しておきます。

全体のまとめ

Herokuにデプロイする前に
Gemfile.lockの中身を消してから
$ bundle install

変更をcommit

$ git push heroku master

$ heroku run rake db:migrate
すればよかったです。
Gemfile.lockを消してbundle install する箇所はbundle updateを実行することでもよいと思います。

前提

Rails5.0.1使用
作業時に使用していたOSはMac OS/X 10.11.6

状況

最新のソースをcommit → $ git push heroku master でデプロイ後、
データベースをmigrateするため、次のコマンドを叩いたらエラーが発生しました。

$ heroku run rake db:migrate

エラーメッセージは次のとおりです。今思えば全て取っておけば良かったのですが、最初の一部だけです。

Running rake db:migrate on ⬢ myapp... up, run.9784 (Free)
rake aborted!
Gem::LoadError: Specified 'postgresql' for database adapter, but the gem is not loaded. Add `gem 'pg'` to your Gemfile (and ensure its version is at the minimum required by ActiveRecord).

対策

公式サイトの導入ガイド
「Getting Started with Rails 5.x on Heroku」 に従ってちゃんと設定を出来ているか(特にdb関連)確認してみました。

Gemfileの確認

公式で「gem 'sqlite3' To this: gem 'pg'」とあるようにHerokuではPostgreSQLSaas形態で提供されているため、gemはpgを使用する必要があります。
ここで私はproduction環境向けに「gem 'pg'」を指定するのを忘れていましたので、指定しました。

Gemfile

 group :production do
  gem 'pg',             '0.15.1' 
  gem 'rails_12factor'
 end

database.ymlの確認

公式で、databaseのadapterはpostgresql を使うように等々ありましたので見直しました。
データベース名やらユーザー名やらは
$ heroku config
でも確認出来るのですが、Web上で見た方がわかりやすいと思います。
Herokuにログイン→アプリを選択→Add-onsにあるHerokuPostgresをクリック→Database CredentialsのView Credentialsボタンをクリックで参照出来ます。

config/database.yml

# SQLite version 3.x
#   gem install sqlite3
#
#   Ensure the SQLite 3 gem is defined in your Gemfile
#   gem 'sqlite3'
#
default: &default
  adapter: postgresql
  encoding: utf8
  # For details on connection pooling, see rails configuration guide
  # http://guides.rubyonrails.org/configuring.html#database-pooling
  pool: 5

# SQLite version 3.x
#   gem install sqlite3
development:
  adapter: sqlite3
  database: db/development.sqlite3
  pool: 5
  timeout: 5000

# Warning: The database defined as "test" will be erased and
# re-generated from your development database when you run "rake".
# Do not set this db to the same as development or production.
test:
  adapter: sqlite3
  database: db/test.sqlite3
  pool: 5
  timeout: 5000

#
production:
  <<: *default
  database: d8c7clp3dmvv4u
  username: ENV['DATABASE_USER']
  password: ENV['DATABASE_PASSWORD']
  host: ec2-23-23-222-147.compute-1.amazonaws.com
  port: 5432

変更をcommitして再度デプロイしましたがエラーが発生しました。
エラーメッセージは次のとおりです。

Running rake db:migrate on ⬢ myapp... up, run.9233 (Free)
rake aborted!
Gem::LoadError: Specified 'postgresql' for database adapter, but the gem is not loaded. Add `gem 'pg'` to your Gemfile (and ensure its version is at the minimum required by ActiveRecord).
/app/vendor/bundle/ruby/2.2.0/gems/activerecord-5.0.0.1/lib/active_record/connection_adapters/connection_specification.rb:176:in `rescue in spec'
/app/vendor/bundle/ruby/2.2.0/gems/activerecord-5.0.0.1/lib/active_record/connection_adapters/connection_specification.rb:173:in `spec'
/app/vendor/bundle/ruby/2.2.0/gems/activerecord-5.0.0.1/lib/active_record/connection_handling.rb:53:in `establish_connection'
/app/vendor/bundle/ruby/2.2.0/gems/activerecord-5.0.0.1/lib/active_record/railtie.rb:125:in `block (2 levels) in <class:Railtie>'
/app/vendor/bundle/ruby/2.2.0/gems/activesupport-5.0.0.1/lib/active_support/lazy_load_hooks.rb:38:in `instance_eval'
/app/vendor/bundle/ruby/2.2.0/gems/activesupport-5.0.0.1/lib/active_support/lazy_load_hooks.rb:38:in `execute_hook'
/app/vendor/bundle/ruby/2.2.0/gems/activesupport-5.0.0.1/lib/active_support/lazy_load_hooks.rb:28:in `block in on_load'
/app/vendor/bundle/ruby/2.2.0/gems/activesupport-5.0.0.1/lib/active_support/lazy_load_hooks.rb:27:in `each'
/app/vendor/bundle/ruby/2.2.0/gems/activesupport-5.0.0.1/lib/active_support/lazy_load_hooks.rb:27:in `on_load'
/app/vendor/bundle/ruby/2.2.0/gems/activerecord-5.0.0.1/lib/active_record/railtie.rb:121:in `block in <class:Railtie>'
/app/vendor/bundle/ruby/2.2.0/gems/railties-5.0.0.1/lib/rails/initializable.rb:30:in `instance_exec'
/app/vendor/bundle/ruby/2.2.0/gems/railties-5.0.0.1/lib/rails/initializable.rb:30:in `run'
/app/vendor/bundle/ruby/2.2.0/gems/railties-5.0.0.1/lib/rails/initializable.rb:55:in `block in run_initializers'
/app/vendor/bundle/ruby/2.2.0/gems/railties-5.0.0.1/lib/rails/initializable.rb:54:in `run_initializers'
/app/vendor/bundle/ruby/2.2.0/gems/railties-5.0.0.1/lib/rails/application.rb:352:in `initialize!'
/app/config/environment.rb:5:in `<top (required)>'
/app/vendor/bundle/ruby/2.2.0/gems/activesupport-5.0.0.1/lib/active_support/dependencies.rb:293:in `require'
/app/vendor/bundle/ruby/2.2.0/gems/activesupport-5.0.0.1/lib/active_support/dependencies.rb:293:in `block in require'
/app/vendor/bundle/ruby/2.2.0/gems/activesupport-5.0.0.1/lib/active_support/dependencies.rb:259:in `load_dependency'
/app/vendor/bundle/ruby/2.2.0/gems/activesupport-5.0.0.1/lib/active_support/dependencies.rb:293:in `require'
/app/vendor/bundle/ruby/2.2.0/gems/railties-5.0.0.1/lib/rails/application.rb:328:in `require_environment!'
/app/vendor/bundle/ruby/2.2.0/gems/railties-5.0.0.1/lib/rails/application.rb:448:in `block in run_tasks_blocks'
/app/vendor/bundle/ruby/2.2.0/gems/rake-12.0.0/exe/rake:27:in `<top (required)>'
/app/vendor/bundle/ruby/2.2.0/gems/bundler-1.13.7/lib/bundler/cli/exec.rb:74:in `load'
/app/vendor/bundle/ruby/2.2.0/gems/bundler-1.13.7/lib/bundler/cli/exec.rb:74:in `kernel_load'
/app/vendor/bundle/ruby/2.2.0/gems/bundler-1.13.7/lib/bundler/cli/exec.rb:27:in `run'
/app/vendor/bundle/ruby/2.2.0/gems/bundler-1.13.7/lib/bundler/cli.rb:332:in `exec'
/app/vendor/bundle/ruby/2.2.0/gems/bundler-1.13.7/lib/bundler/vendor/thor/lib/thor/command.rb:27:in `run'
/app/vendor/bundle/ruby/2.2.0/gems/bundler-1.13.7/lib/bundler/vendor/thor/lib/thor/invocation.rb:126:in `invoke_command'
/app/vendor/bundle/ruby/2.2.0/gems/bundler-1.13.7/lib/bundler/vendor/thor/lib/thor.rb:359:in `dispatch'
/app/vendor/bundle/ruby/2.2.0/gems/bundler-1.13.7/lib/bundler/cli.rb:20:in `dispatch'
/app/vendor/bundle/ruby/2.2.0/gems/bundler-1.13.7/lib/bundler/vendor/thor/lib/thor/base.rb:440:in `start'
/app/vendor/bundle/ruby/2.2.0/gems/bundler-1.13.7/lib/bundler/cli.rb:11:in `start'
/app/vendor/bundle/ruby/2.2.0/gems/bundler-1.13.7/exe/bundle:34:in `block in <top (required)>'
/app/vendor/bundle/ruby/2.2.0/gems/bundler-1.13.7/lib/bundler/friendly_errors.rb:100:in `with_friendly_errors'
/app/vendor/bundle/ruby/2.2.0/gems/bundler-1.13.7/exe/bundle:26:in `<top (required)>'
/app/bin/bundle:3:in `load'
/app/bin/bundle:3:in `<main>'
Gem::LoadError: can't activate pg (~> 0.18), already activated pg-0.15.1. Make sure all dependencies are added to Gemfile.
/app/vendor/bundle/ruby/2.2.0/gems/bundler-1.13.7/lib/bundler/rubygems_integration.rb:346:in `block (2 levels) in replace_gem'
/app/vendor/bundle/ruby/2.2.0/gems/activerecord-5.0.0.1/lib/active_record/connection_adapters/postgresql_adapter.rb:2:in `<top (required)>'
/app/vendor/bundle/ruby/2.2.0/gems/activesupport-5.0.0.1/lib/active_support/dependencies.rb:293:in `require'
/app/vendor/bundle/ruby/2.2.0/gems/activesupport-5.0.0.1/lib/active_support/dependencies.rb:293:in `block in require'
/app/vendor/bundle/ruby/2.2.0/gems/activesupport-5.0.0.1/lib/active_support/dependencies.rb:259:in `load_dependency'
/app/vendor/bundle/ruby/2.2.0/gems/activesupport-5.0.0.1/lib/active_support/dependencies.rb:293:in `require'
/app/vendor/bundle/ruby/2.2.0/gems/activerecord-5.0.0.1/lib/active_record/connection_adapters/connection_specification.rb:174:in `spec'
/app/vendor/bundle/ruby/2.2.0/gems/activerecord-5.0.0.1/lib/active_record/connection_handling.rb:53:in `establish_connection'
/app/vendor/bundle/ruby/2.2.0/gems/activerecord-5.0.0.1/lib/active_record/railtie.rb:125:in `block (2 levels) in <class:Railtie>'
/app/vendor/bundle/ruby/2.2.0/gems/activesupport-5.0.0.1/lib/active_support/lazy_load_hooks.rb:38:in `instance_eval'
/app/vendor/bundle/ruby/2.2.0/gems/activesupport-5.0.0.1/lib/active_support/lazy_load_hooks.rb:38:in `execute_hook'
/app/vendor/bundle/ruby/2.2.0/gems/activesupport-5.0.0.1/lib/active_support/lazy_load_hooks.rb:28:in `block in on_load'
/app/vendor/bundle/ruby/2.2.0/gems/activesupport-5.0.0.1/lib/active_support/lazy_load_hooks.rb:27:in `each'
/app/vendor/bundle/ruby/2.2.0/gems/activesupport-5.0.0.1/lib/active_support/lazy_load_hooks.rb:27:in `on_load'
/app/vendor/bundle/ruby/2.2.0/gems/activerecord-5.0.0.1/lib/active_record/railtie.rb:121:in `block in <class:Railtie>'
/app/vendor/bundle/ruby/2.2.0/gems/railties-5.0.0.1/lib/rails/initializable.rb:30:in `instance_exec'
/app/vendor/bundle/ruby/2.2.0/gems/railties-5.0.0.1/lib/rails/initializable.rb:30:in `run'
/app/vendor/bundle/ruby/2.2.0/gems/railties-5.0.0.1/lib/rails/initializable.rb:55:in `block in run_initializers'
/app/vendor/bundle/ruby/2.2.0/gems/railties-5.0.0.1/lib/rails/initializable.rb:54:in `run_initializers'
/app/vendor/bundle/ruby/2.2.0/gems/railties-5.0.0.1/lib/rails/application.rb:352:in `initialize!'
/app/config/environment.rb:5:in `<top (required)>'
/app/vendor/bundle/ruby/2.2.0/gems/activesupport-5.0.0.1/lib/active_support/dependencies.rb:293:in `require'
/app/vendor/bundle/ruby/2.2.0/gems/activesupport-5.0.0.1/lib/active_support/dependencies.rb:293:in `block in require'
/app/vendor/bundle/ruby/2.2.0/gems/activesupport-5.0.0.1/lib/active_support/dependencies.rb:259:in `load_dependency'
/app/vendor/bundle/ruby/2.2.0/gems/activesupport-5.0.0.1/lib/active_support/dependencies.rb:293:in `require'
/app/vendor/bundle/ruby/2.2.0/gems/railties-5.0.0.1/lib/rails/application.rb:328:in `require_environment!'
/app/vendor/bundle/ruby/2.2.0/gems/railties-5.0.0.1/lib/rails/application.rb:448:in `block in run_tasks_blocks'
/app/vendor/bundle/ruby/2.2.0/gems/rake-12.0.0/exe/rake:27:in `<top (required)>'
/app/vendor/bundle/ruby/2.2.0/gems/bundler-1.13.7/lib/bundler/cli/exec.rb:74:in `load'
/app/vendor/bundle/ruby/2.2.0/gems/bundler-1.13.7/lib/bundler/cli/exec.rb:74:in `kernel_load'
/app/vendor/bundle/ruby/2.2.0/gems/bundler-1.13.7/lib/bundler/cli/exec.rb:27:in `run'
/app/vendor/bundle/ruby/2.2.0/gems/bundler-1.13.7/lib/bundler/cli.rb:332:in `exec'
/app/vendor/bundle/ruby/2.2.0/gems/bundler-1.13.7/lib/bundler/vendor/thor/lib/thor/command.rb:27:in `run'
/app/vendor/bundle/ruby/2.2.0/gems/bundler-1.13.7/lib/bundler/vendor/thor/lib/thor/invocation.rb:126:in `invoke_command'
/app/vendor/bundle/ruby/2.2.0/gems/bundler-1.13.7/lib/bundler/vendor/thor/lib/thor.rb:359:in `dispatch'
/app/vendor/bundle/ruby/2.2.0/gems/bundler-1.13.7/lib/bundler/cli.rb:20:in `dispatch'
/app/vendor/bundle/ruby/2.2.0/gems/bundler-1.13.7/lib/bundler/vendor/thor/lib/thor/base.rb:440:in `start'
/app/vendor/bundle/ruby/2.2.0/gems/bundler-1.13.7/lib/bundler/cli.rb:11:in `start'
/app/vendor/bundle/ruby/2.2.0/gems/bundler-1.13.7/exe/bundle:34:in `block in <top (required)>'
/app/vendor/bundle/ruby/2.2.0/gems/bundler-1.13.7/lib/bundler/friendly_errors.rb:100:in `with_friendly_errors'
/app/vendor/bundle/ruby/2.2.0/gems/bundler-1.13.7/exe/bundle:26:in `<top (required)>'
/app/bin/bundle:3:in `load'
/app/bin/bundle:3:in `<main>'
Tasks: TOP => db:migrate => environment
(See full trace by running task with --trace)

ここで色々調べまくってherokuのプロジェクトを一度消してからやり直したり、
Managing Gems with Bundler | Heroku Dev Centerにあるように開発環境のgemをインストールしないようにしたり、
dotenvを使って環境変数からユーザー名とパスワードを指定しているところを直接書いたりしてみましたが状況が変わることはありませんでした。

エラーメッセージの中に
「Gem::LoadError: can't activate pg (~> 0.18), already activated pg-0.15.1. Make sure all dependencies are added to Gemfile.」
とあるので関係があるかもしれないと思い

 gem 'pg',             '0.15.1'

としていたところを

 gem 'pg'

に変更して、production内に書いているだけではダメかもしれないと、デフォルトのところにも指定してみましたが状況は変わりませんでした。

そこで何となくGemfile.lockをのぞくと
pg (0.15.1)
となっていました。pgのバージョンを指定するのをやめたのに昔のものが残っているのか?と思い内容を全部消去してから

$ bundle install 

してから変更をcommitし、あらためてHerokuにデプロイし

$ heroku run rake db:migrate

しますと出来ました!

Running rake db:migrate on ⬢ myapp... up, run.5276 (Free)
   (54.7ms)  CREATE TABLE "schema_migrations" ("version" character varying PRIMARY KEY)
   (10.7ms)  CREATE TABLE "ar_internal_metadata" ("key" character varying PRIMARY KEY, "value" character varying, "created_at" timestamp NOT NULL, "updated_at" timestamp NOT NULL)
   (1.7ms)  SELECT pg_try_advisory_lock(4611527472350007090);
  ActiveRecord::SchemaMigration Load (1.3ms)  SELECT "schema_migrations".* FROM "schema_migrations"
Migrating to CreateTypes (20170228141646)
   (1.1ms)  BEGIN
== 20170228141646 CreateTypes: migrating ======================================
-- create_table(:types)
(中略)

試してませんが、Gemfile.lockを消してbundle install する箇所はbundle updateを実行することでもよいと思います。

まとめ

  • pg (0.15.1)のままであったとしても何故エラーになるのかがはっきりとはわかりませんでしたが、現時点(2017/03/28)でサーバー側のPostgresSQLは0.19.0が最新のようなので明らかに古いので問題があっとということだと解釈しました。
  • 違う環境にデプロイする時はGemfile.lockに注意する必要があることを学習しました。
  • 今回の件には関係ありませんが、push時にHeroku側で毎回bundle installしているみたいなのですが、これは省略出来ないのだろうか、できたらいいのにと感じました。やり方はあるのかもしれないのですが、発見できませんでした。

DropboxのPublicフォルダをjsonファイル置き場にしてたが2017年3月15日で廃止したので代替としてFC2ホームページを使うことにした

DropboxのPublicフォルダにはWebホスティング機能があり、そこにファイルを置いて置くだけで世界に公開できるという便利なものだったのですが、
無料ユーザーはとうとう廃止になってしまいました。
私はjsonファイルを置いて検証用のサーバーみたいな使い方をしていたんですが、今回の変更でこの使い方は出来なくなってしまいました。
代替としてブログでおなじみのFC2のサービスの中から「ホームページ」のサービス(「ブログ」ではありませんよ)を使ってjson置き場にすることにしました。

jsonファイルをアップロードして開くとブラウザのURLのBOXのところにURLが表示されるのでそれを使います。

fc2.com


1Gフリースペースがあるので私みたいな使い方なら余裕です。






Material Design Lite for SassでRailsアプリケーションにGoogleのMaterial Design LiteとMaterial IconsとRobotoフォントを導入する

Google製のマテリアルデザインとマテリアルアイコンとRobotoフォントをRubyアプリケーションで使うための「Material Design Lite for Sass」というgemを使います。

github.com

このgemはgoogle製Material Design LiteのSaasバージョンです。

github.com

導入

Gemfileに次のように記述します。

gem 'material_design_lite-sass'

bundle install しておきます。

/app/assets/stylesheets/application.scss に次のように記述します。

@import 'material';

Attention! デフォルトでは.cssの拡張子でファイルが作成されます。.scssに変更し、*= require_tree . と *= require_selfを削除する必要があります。
オリジナルのapplication.cssをそのままにしたい場合、同じフォルダにcustom.scssを作成し@import 'material'する方法もあります。

app/assets/javascripts/application.js に次のように記述します。

//= require material

TurbolinksについてはMaterial Design Liteはサポートしてないので、READMEを見て下さい。

デフォルトではマテリアルデザインの全てのコンポーネントがimportされていますが、個別に指定する方法もあります。

Material Iconの使い方

<i class="material-icons">info</i>

上の例では"info"のところにマテリアルアイコンの名前を入れます。
マテリアルアイコンの名前は↓のリストにあるものです。
material.io

Saasバージョンで使える変数はこちら↓
material_design_lite-sass/_variables.scss at master · rubysamurai/material_design_lite-sass · GitHub

変数の内容をoverrideする場合は、@importする前に記述する必要があります。↓が例です。

$layout-header-bg-color: rgb(128,128,128) !default;
@import 'material';


ransackでRailsアプリケーションに検索機能をつける

Railsを勉強中です。

ransackというgemを使用して、検索機能を実装する一連の処理をメモします。

github.com

下準備

サンプルのアプリケーションを新しく作ります。
railsのバージョンは5.0.1です。

$ rails new _5.0.0.1_ new exm-ransack
$ cd exm-ransack

以前書いたエントリーと同じモデルを作り、同じデータを投入します。
↓以前のエントリ
sakura-bird1.hatenablog.com

サンプルデータ(csvデータ)をdbフォルダに入れておきます。
postal_code_tokyo_with_header.csv - Google ドライブ

今回はscaffoldでアプリケーションのひな型を作ります。

$ rails g scaffold PostalCode local_goverment_code:integer postal_code_old:integer postal_code:integer prefecture_katakana:string ward_katakana:string town_katakana:string prefecture:string ward:string town:string

$ rails db:migrate

db/seeds.rb に次のように記述します。

require 'csv'

PostalCode.delete_all

csv_data = CSV.read('db/postal_code_tokyo_with_header.csv', headers: true)
csv_data.each do |data|
  PostalCode.create!(data.to_hash)
end

$ rails db:seed
を実行します。
$ rails s
を実行します。
http://localhost:3000/postal_codes
にアクセスするとうまくデータが投入できているのがわかります。

f:id:sakura_bird1:20170301155738p:plain

検索機能を実装する

Gemfileに以下を追加する

gem ‘ransack'

$ bundle install
を実行します。

controllerのindexを次のように書き換えます。
postal_codes_controller.rb

# GET /postal_codes
# GET /postal_codes.json
def index
  # 検索フォームの入力内容で検索する
  @q = PostalCode.search(params[:q])

  # 重複を排除
  @postal_codes = @q.result(distinct: true)
end

viewに検索フォームを付けます。
app/views/postal_codes/index.html.erb

<%= search_form_for @q do |f| %>
    <%= f.label :town_cont %>
    <%= f.search_field :town_cont %>

    <%= f.submit %>
<% end %>

search_form_forというヘルパーメソッドが用意されており、検索フォームを生成してくれます。
:town_cont というのはtownフィールドに含まれている(contain)ものを検索するという意味です。

http://localhost:3000/postal_codes
にアクセスすると検索フォームが上の方に出来ていることがわかります。

f:id:sakura_bird1:20170301160124p:plain



検索フォームを次のようにフィールド名を_or_でつなげて書いたとすると、このフィールドのどこかで検索文字を含むものを結果に表示します。
フィールド名1_or_フィールド名2_(中略)_cont

<%= search_form_for @q do |f| %>
    <%= f.label :prefecture_katakana_or_ward_katakana_or_town_katakana_or_prefecture_or_ward_or_town_cont %>
    <%= f.search_field :prefecture_katakana_or_ward_katakana_or_town_katakana_or_prefecture_or_ward_or_town_cont %>

    <%= f.submit %>
<% end %>

f:id:sakura_bird1:20170301161459p:plain

以上です。