『RailsとiPhoneではじめるアプリケーション開発』を進める時の注意点・ハマったこと Chapter 010

引き続き、『RailsiPhoneではじめるアプリケーション開発』を進めてみようと思います。

RailsとiPhoneではじめるアプリケーション開発

RailsとiPhoneではじめるアプリケーション開発

Chapter 01 -> 03
『RailsとiPhoneではじめるアプリケーション開発』を進める時の注意点・ハマったこと Chapter 03まで - diceK66のブログ
Chapter 04 -> 06
『RailsとiPhoneではじめるアプリケーション開発』を進める時の注意点・ハマったこと Chapter 06まで - diceK66のブログ
Chapter 07
『RailsとiPhoneではじめるアプリケーション開発』を進める時の注意点・ハマったこと Chapter 07 - diceK66のブログ
Chapter 08 -> 09
『RailsとiPhoneではじめるアプリケーション開発』を進める時の注意点・ハマったこと Chapter 08 -> 09 - diceK66のブログ

重要事項

エラーが起きたらコンソールをじっくり読みましょう

特に自分が作成or編集したファイルがログに出てきたら、必ず正しくソースが書けているか等をチェックしましょう

いつの間にTPLoginContollerなんて作った?

p.228のサンプルソースに、さも当然のようにTPLoginControllerが登場します。
頭にTPがついているので、travelphotoプロジェクトのクラスだと思うのですが、今まで作った記憶がありません。
とりあえず、Impress Japan: RailsとiPhoneではじめるアプリケーション開発ここで配布されているサンプルソースを見ると、どうやら「QuickDialogController」のサブクラスのようなので、TPLoginControllerクラスを新たに作ります。
これで、TPAppDelegate.hの方は記述できると思います。

ただし、TPAppDelegate.mの方は、QRootElementが見つからず、エラーが出ます。
以下のコードを、travelphoto-Prefix.pchに追記してください。

#import <QuickDialog/QuickDialog.h>

これで、p.228のコードがエラー無く実装できると思います。

p.229 TPShowLoginをTPConstantsクラスに追記

p.229下段のソースを記述していくと、TPShowLoginがエラーになると思います。
以下のリンクを参考に、TPConstantsクラスに定数を追記してください。
Objective-C - RailsとiPhoneではじめるアプリケーション開発をiOS7向けに読み進めるときの注意・修正点 - Qiita

p.232 TPRegistControllerでエラー

こちらも、突然知らないクラスが当然のごとく登場します。
配布されているサンプルコードによると、QuickDialogControllerのサブクラスのようなので、TPRegistControllerを新しく作成します。
更に、TPLoginController.hでインポートします。

#import "TPRegistController.h"

これで、p.232上段のコードはエラーがなくなると思います。

p.242〜p.244の実装

このままLoginControllerの実装をはじめると、「TravelPhotoAPI」が見つからずにエラーになるため、以下のコードを、travelphoto-Prefix.pchに追記してください。

#import "TravelPhotoAPI.h"

また、ナチュラルに今まで実装していないメソッドが書かれていますので、そこもエラーになります。
TPUserInfo.hに追記します。

#import <Foundation/Foundation.h>
#import "LUKeychainAccess.h"

@interface TPUserInfo : NSObject
@property(nonatomic, strong) NSString *auth_token; //追記

+ (TPUserInfo *)sharedInstance;

- (NSString *)loadEmail;
- (void)saveEmail:(NSString *)email;
- (NSString *)loadPassword;
- (void)savePassword:(NSString *)password;
- (NSString *)loadAuthToken; //追記
- (void)saveAuthToken:(NSString *)auth_token; //追記

@end

ついでに、TPUserInfo.mの最後の@endの前に以下2つのメソッドを入れます。

- (NSString *)loadAuthToken {
    NSString *email = [[LUKeychainAccess standardKeychainAccess] objectForKey:@"auth_token"];
    return email;
}

- (void)saveAuthToken:(NSString *)auth_token{
    [[LUKeychainAccess standardKeychainAccess] setObject:auth_token forKey:@"auth_token"];
    _auth_token = NULL;
}

やっとRailsとつながった! が、当然のようにエラーw

NameError (undefined local variable or method `build_resource' for #<Api::SessionsController:0x007f955dccade0>):

こんなエラーがコンソールに出力されています。
どうもDeviseのバージョンがあがって、build_resourceがなくなった事が原因のようです。
これを超丁寧に解説してくれている神サイトを見つけましたので、ご参考になさってください。
Deviseでbuild_resourceがない。 - よしそぶろぐ

新規会員登録画面の「登録」ボタンのイベントが書かれていない

どうやらp.246に書いてある情報を参考にして、p.242からのonLoginメソッドをうまい事コピペして作ってね、という事らしいです。
こちらのメソッドを実装なさっているページがありました。
RailsとiPhoneではじめるアプリケーション開発 の動かないところ

p.248 SVWebViewControllerは'0.1'を指定

Podfileで新たにSVWebViewControllerを追記しますが、最新版はiOS7向けなので、古いタグを指定します。0.2と0.1があるようですが、本に乗っているログを見ると、0.1が使われているようなので、0.1を指定しました。

pod 'SVWebViewController', '0.1'

p.248 sendPasswordUrlは、TravelPhotoAPI.hにも追加

TravelPhotoAPI.hは、以下のような感じになると思います。

- (NSString *)signInPath;
- (NSString *)signUpPath;
- (NSString *)sendPasswordUrl;

@end

p.248 (void)clearUserInfoは、ヘッダーファイルにも追加

もうナチュラルにヘッダーファイルに追記するという指示はなくなりました。
著者も後半に入ってバテてきたのかもしれません。

- (void)clearUserInfo;

これをTPUser.hにも追加してください。
ところで、本文中のファイル名に「TP」というプレフィックスを付ける気は、もう無いのでしょうか。

p251下段のコードはTPAppDelegete.mへ

どこにサンプルソースを書けばよいか全く言及されていませんが、TPAppDelegate.mを編集してください。

p.252TPSettingController.mはQuickDialogControllerのサブクラスでした

こいつだけ、UITableViewControllerのサブクラスではないので、ご注意ください。
もしも私のようにUITableViewControllerのサブクラスとしてTPSettingControllを作っていた場合は、ヘッダーファイルのimportを書き換えればOKです。

#import "QuickDialogController.h"

ログインできない!

ここまでで、ユーザーの登録はできるようになったと思います。
ただ、実際にRails側につないでみると、登録はできてもログインができないと思います。

Started POST "/api/users/sign_in" for 127.0.0.1 at 2014-03-30 00:34:52 +0900
Processing by Api::SessionsController#create as */*
  Parameters: {"user"=>{"email"=>"aaaa@example.com", "password"=>"[FILTERED]"}}
WARNING: Can't verify CSRF token authenticity
  User Load (0.4ms)  SELECT `users`.* FROM `users` WHERE `users`.`email` = 'aaaa@example.com' LIMIT 1
   (0.1ms)  BEGIN
   (0.1ms)  COMMIT
Completed 401 Unauthorized in 241ms

Unauthorizedと出ていているので、思いつくのは、Userモデルの:confirmableが有効になっていること。
rails cでコンソールを呼び出し、以下のような感じでconfirm!してみます。

user = User.find_by_email('aaaa@example.com')
user.confirm!

するとエラーの内容が変わりました。

NoMethodError (undefined method `reset_authentication_token!' for #<User:0x007f955de08d38>):
  app/controllers/api/sessions_controller.rb:12:in `create'

で、これはおそらく、先日なんか起きたら対応すると書いた「:token_authenticatableが無い!」というやつの問題です。
『RailsとiPhoneではじめるアプリケーション開発』を進める時の注意点・ハマったこと Chapter 06まで - diceK66のブログ

すんません、正直、まともな対策を考えずに進みました。
ここまでこられた方ならわかると思いますが、もう既にかなりこの本に疲れてますw
とりあえず、ローカルでテストするだけなら、何か適当に文字列を返せばOKそうです。
私の場合は、session_controller.rbでメアドを返して強引に突破ちゃいました。
絶対に本番で使っちゃダメですよ!!
:auth_token => resource.email,

上のやり方は、疲れていると言っても絶対やっちゃだめですよ!w
他の方法で実装するやり方をまとめました。
:token_authenticatableが削除されたので他の方法で実装してみた - diceK66のブログ

所感

ネットの力はすごいですね。
いろいろな方がこの本についての解説サイトを作っていらっしゃいます、本当に助かりました。
これらが無ければどうなっていた事か・・・。

そして、今回から公式にWebで配布されているサンプルソースを参照しはじめましたが、これらにも実装されていないメソッドやコンパイルエラー、動かない箇所等が多数あります。
気づいてはいましたが、やはり著者の方は、一通りプログラムを書いただけで、テストや実際に動かしたりはしていないように思います。