0

I have taken the Rails 3 Tutorial app by Michael Hartl and have expanded on it in several areas. However, I kept the login and session handling the same. I would like to interface with an iphone app, but am not sure how. I've looked at RestKit and Objective Resource, but thought I would roll my own. I've been testing it out with cURL, but have had no luck so far. I've been using this command

curl -H 'Content-Type: application/json'   -H 'Accept: application/json'   -X POST http://www.example.com/signin   -d "{'session' : { 'email' : 'email@gmail.com', 'password' : 'pwd'}}"   -c cookie

As in the Rails 3 tutorial, I'm using Sessions.

These are the routes:

match '/signin', :to => 'sessions#new'
match '/signout', :to => 'sessions#destroy' 

This is the controller:

class SessionsController < ApplicationController
def new
@title = "Sign in"
end

def create
user = User.authenticate(params[:session][:email],
                         params[:session][:password])
if user.nil?
    flash.now[:error] = "Invalid email/password combination."
    @title = "Sign in"
    render 'new'
else
    sign_in user
    redirect_back_or user
end
end

def destroy
sign_out
redirect_to root_path
end
end 

There is no model and you sign in with a form. Here is the html for the form:

<h1>Sign In</h1>
<%= form_for(:session, :url => sessions_path) do |f| %>
<div class="field">
<%= f.label :email %></br>
<%= f.text_field :email %>
</div>
<div class="field">
<%= f.label :password %></br>
<%= f.password_field :password %>
</div>
<div class="actions">
<%= f.submit "Sign in" %>
</div>
<% end %>

<p> New user? <%= link_to "Sign up now!", signup_path %></p> 

Sorry if this is too much information, I wanted to give as much as possible.

Basically, I would like to be able to access my Rails database from a native iphone app. If someone has good advice on how to sign in, store a session, and then make other calls to the website, I would greatly appreciate it.

However, if this isn't possible, a working cURL request would probably get me going in the right direction. Thanks!

NSchulze
  • 179
  • 1
  • 5
  • 19

1 Answers1

1

I was facing a similar situation, which led me to draw up this stackoverflow post:

[http://stackoverflow.com/questions/7997009/rails-3-basic-http-authentication-vs-authentication-token-with-iphone][1]

Basically, you can use basic http authentication with rails to simplify things.

Here's an example of the controller:

 class PagesController < ApplicationController  

  def login
    respond_to do |format|
      format.json {
        if params[:user] and
           params[:user][:email] and
           params[:user][:password]
          @user = User.find_by_email(params[:user][:email])
          if @user.valid_password?(params[:user][:password])
            @user.ensure_authentication_token!
            respond_to do |format|
              format.json {
                render :json => {
                    :success => true,
                    :user_id => @user.id,
                    :email => @user.email
                  }.to_json
              }
            end
          else
            render :json => {:error => "Invalid login email/password.", :status => 401}.to_json
          end
        else
          render :json => {:error => "Please include email and password parameters.", :status => 401}.to_json
        end
      }
    end
  end

Then on the iphone/objective-c side of things, you can use the ASIHTTPRequest library and JSONKit library:

http://allseeing-i.com/ASIHTTPRequest/

https://github.com/johnezang/JSONKit/

Once you have all the aforementioned installed in xcode, then accessing the rails controller, getting the response as json, and handling it in objective-c is simple:

NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"http://%@/pages/login.json", RemoteUrl]];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request addRequestHeader:@"Content-Type" value:@"application/json"];
[request setRequestMethod:@"POST"];
[request appendPostData:[[NSString stringWithFormat:@"{\"user\":{\"email\":\"%@\", \"password\":\"%@\"}}", self.emailField.text, self.passwordField.text] dataUsingEncoding:NSUTF8StringEncoding] ];
[request startSynchronous];

//start
[self.loginIndicator startAnimating];

//finish
 NSError *error = [request error];
[self setLoginStatus:@"" isLoading:NO];

if (error) {
    [self setLoginStatus:@"Error" isLoading:NO];
    [self showAlert:[error description]];
} else {
    NSString *response = [request responseString];

    NSDictionary * resultsDictionary = [response objectFromJSONString];


    NSString * success = [resultsDictionary objectForKey:@"success"];


    if ([success boolValue]) {
        ....

I just finished a rails/iphone application with tons of calls to Rails, so it's definitely doable and a learning experience.

DivineDesert
  • 6,924
  • 1
  • 29
  • 61
JohnMerlino
  • 3,900
  • 4
  • 57
  • 89
  • This may be a dumb question, but I'm still relatively new to Rails. What exactly does format.json do? Does that allow me to send the parameters as JSON? If mine if format.js right now, will changing it to format.json screw anything up? – NSchulze Aug 01 '12 at 18:27
  • Yes, it sends the parameters as JSON. Json is a subset of JavaScript, although not all JavaScript responses are json responses. Json is readable by javascript and it's a quick and effective way to pass data from server to javascript. – JohnMerlino Aug 01 '12 at 18:31
  • Cool. So is the reason my cURL command wasn't working because it was format.js? Or am I way off base there? – NSchulze Aug 01 '12 at 21:14
  • When using curl, make sure to add the headers: curl -H 'Content-Type: application/json' \ > -H 'Accept: application/json' \ > -X POST http://localhost:3000/users/sign_in \ > -d '{"remote": "true", "commit": "Sign in", "utf8": "✓", "user": {"remember_me": "1", "password": "123456", "email": "email@email.net"}}' – JohnMerlino Aug 02 '12 at 00:02
  • I absolutely will. I'm just having trouble getting it to work. Could you explain to me what exactly causes the controller to respond to a post with the JSON format? I think that is where I'm getting hung up. Thanks! – NSchulze Aug 10 '12 at 05:18