How long does it take to build an app with RoR?

YARORA in x minutes and n easy steps

x = 15;

n = ?;

"Club bouncer app"

(prototype/mvp/whatever)

  • facebook login
  • user can create a party
  • user can invite other users to the party
  • invited users can see other guests
  • not invited users can log in and see the party,
  • not invited users can’t see the party details unless someone invites them
  • heroku deployment

Rails & config

$ gem install rails --version 4.0.3
$ rails new rapid-app --database postgresql
$ cd rapid-app && vim config/database.yml
$ rake db:create
$ rails server
$ open http://localhost:3000

Scaffold nice users

# in gemfile
gem "therubyracer"
gem "less-rails"
gem "twitter-bootstrap-rails"
$ bundle install
$ rails generate bootstrap:install less
$ rails generate bootstrap:layout application fluid
$ rails generate scaffold User name:string email:text
$ rake db:migrate
$ rails g bootstrap:themed Users

Authentication!

Gems, user migration, routes

gem "omniauth"
gem "omniauth-facebook"
add_column :users, :uid, :string
add_column :users, :provider, :string
get '/auth/:provider/callback' => 'sessions#create'
get '/signin' => 'sessions#new', :as => :signin
get '/signout' => 'sessions#destroy', :as => :signout
get '/auth/failure' => 'sessions#failure'

Authentication!

such app/models/user.rb

def self.create_with_omniauth(auth)
  create! do |user|
    user.provider = auth['provider']
    user.uid = auth['uid']
    if auth['info']
       user.nickname = auth['info']['nickname'] || ""
       user.name = auth['info']['name'] || ""
       user.email = auth['info']['email'] || ""
    end
  end
end

Authentication!

such sessions_controller.rb

def new
  redirect_to '/auth/facebook'
end

def create
  auth = request.env["omniauth.auth"]
  user = User.where(:provider => auth['provider'],
                    :uid => auth['uid'].to_s).first || User.create_with_omniauth(auth)
  reset_session
  session[:user_id] = user.id
  redirect_to root_url, :notice => 'Signed in!'
end

Authentication!

such application_controller.rb

private

def current_user
  begin
    @current_user ||= User.find(session[:user_id]) if session[:user_id]
  rescue Exception => e
    nil
  end
end

def user_signed_in?
  return true if current_user
end

500

Ok ok...

rake db:migrate
helper_method :current_user, :user_signed_in?

Signed in

Awesome!

Parties

I've been to one - once.

$ rails generate scaffold Party title:string description:text user:belongs_to
$ rake db:migrate
$ rails g bootstrap:themed Parties

That sucks.

Sucks

Easy fix!

# app/views/parties/_form.html.haml
= f.select :user_id, User.all, :class => 'text_field'

Almost.

Sucks2

Easy fix!

# app/models/user.rb
def to_s
  email
end

TIME'S UP.

n =~ 16

Summary

  • working application
  • with external provider login
  • app users can create their parties with description

Another 60 minutes to finish, following Rails Way

total 75 minutes

Not bad

Awesome

say it with me

3...

say it with me

2...

say it with me

1...

say it with me

No

Did you just go excited about scaffolds?

Few things that went wrong - dissection

1) I was bit slow at this

got better after doing it a few times

2) Few errors on the way

process got harder towards the end

3) Tests were surprisingly tricky

def new
  redirect_to '/auth/facebook'
end

def create
  auth = request.env["omniauth.auth"]
  user = User.where(:provider => auth['provider'],
                    :uid => auth['uid'].to_s).first || User.create_with_omniauth(auth)
  reset_session
  session[:user_id] = user.id
  redirect_to root_url, :notice => 'Signed in!'
end
Tricky

So far so good...

# app/models/invite.rb
after_create :send_email

def send_email
  InvitesMailer.invite(self).deliver!
end

This fires all the time...

# app/models/invite.rb
after_create :send_email, unless: :creator_invite

def send_email
  InvitesMailer.invite(self).deliver!
end

private

def creator_invite
  user == party.user
end

This fires all the time...

# app/models/invite.rb
validate :feeling_lonely

private

def feeling_lonely
  errors.add(:invited_id, "Please don't invite yourself to the party...") if invited == user
end

This whole Rails Way thing has issues!

Code is coupled, so it's hard

  • to maintain
  • to develop
  • to read
  • to test...
Pidgeon Captain

It's 2014, year of the Horse

We know that already.

Logic


http://thinkrelevance.com/blog/2007/06/05/ruby-vs-java-myth-4-it-is-easy-to-copy-rails-good-ideas

3 years old

Gpa

9 months old

Low gpa

6 weeks old

Lower gpa

Something is going on.

X minutes Ruby on Rails  legacy  application

in n easy steps

Rails Way is awesome, RoR Core Team is awesome

Awesome for startups

Awesome for beginners

A good foundation

For the framework you need

It's working!

We are failing :/

Complicated graph to prove it.

RoR community structure

Graph

I don't have a solution

But you do!

Teach'em all!

  • do a talk on your local RUG
  • do a talk on a conference
  • organize workshops
  • talk to the little ones...
Cake
That was my

"15 minutes Ruby on Rails legacy application - the cake is a lie"

talk

Thank you!

Marcin Stecki, cto at netguru.co

@madsheepPL, madsheep.pl