Rails - Still the Best Framework for Bootstrapping

Rails - Still the Best Framework for Bootstrapping

This year we launched a new product in 6 weeks - from initial commit to accepting customers. We could have used a number of languages to build KBSimple, but we chose Rails to bootstrap it. The reason is simple: Rails is still the best framework for bootstrapping new web applications.

In this talk I'll go through the 6 week evolution of the product, talk about the various gems and techniques that were essential in reducing the amount of time it took to launch, and talk about some of the challenges we faced along the way.

31254903db793bf6f84bbd607fe092fd?s=128

Anthony Eden

October 04, 2013
Tweet

Transcript

  1. Rails: Still the Best Framework for Bootstrapping Anthony Eden Founder

    of DNSimple Sunday, October 6, 13
  2. 2001 http://www.flickr.com/photos/84518681@N00/22752982 Sunday, October 6, 13 Built a framework. Quite

    extensible And it grew to be over-architected
  3. 2005 Sunday, October 6, 13 Java frameworks became unwieldy Came

    full circle with Servlets and JSP Simplify
  4. 2006 http://www.flickr.com/photos/30784280@N05/4338666833 Sunday, October 6, 13 First RailsConf Feels all

    brand new Rails development cuts time to market significantly Testing is baked in This framework is opinionated Antidote to the complexity of Java
  5. 2013 http://www.flickr.com/photos/9491236@N03/2844346957 Sunday, October 6, 13 Time to market is

    even better thanks to gems and established techniques This framework is still opinionated Antidote to the problem of too many choices and over engineering
  6. Why Isn’t It Stale? http://www.flickr.com/photos/26406919@N00/4511498998 Sunday, October 6, 13

  7. Libraries http://www.flickr.com/photos/37921614@N00/510243975 Sunday, October 6, 13

  8. Documentation http://www.flickr.com/photos/7424779@N05/2964294812 Sunday, October 6, 13

  9. Community http://www.flickr.com/photos/48973657@N00/2149309015 Sunday, October 6, 13

  10. It’s still MVC http://www.flickr.com/photos/57884042@N00/4563162714 Sunday, October 6, 13

  11. Model your problem http://www.flickr.com/photos/36317426@N00/3580987940 Sunday, October 6, 13

  12. Control the flow http://www.flickr.com/photos/36317426@N00/3580145091 Sunday, October 6, 13

  13. View the outcome http://www.flickr.com/photos/36317426@N00/3580207475 Sunday, October 6, 13

  14. Keys to Success http://www.flickr.com/photos/48888605@N03/6141822934 Sunday, October 6, 13 How do

    you bootstrap successfully with Rails
  15. Have Problem. Solve Problem. http://www.flickr.com/photos/57503924@N07/5368461966 Sunday, October 6, 13

  16. Cut the cruft http://www.flickr.com/photos/14316700@N08/3210447964 Sunday, October 6, 13

  17. Don’t cut the tests http://www.flickr.com/photos/24029425@N06/8139290608 Sunday, October 6, 13

  18. Feature flags http://www.flickr.com/photos/68977046@N00/2221278307 Sunday, October 6, 13

  19. Launch http://www.flickr.com/photos/24662369@N07/8464918661 Sunday, October 6, 13

  20. SaaS = speed to launch http://www.flickr.com/photos/9549598@N02/768973472 Sunday, October 6, 13

  21. Billing http://www.flickr.com/photos/29468339@N02/4634443529 Sunday, October 6, 13 Stripe or Chargify

  22. Error Notification http://www.flickr.com/photos/16013376@N00/3053460290 Sunday, October 6, 13 BugSnag HoneyBadger

  23. Logging http://www.flickr.com/photos/41964203@N00/301191575 Sunday, October 6, 13 Papertrail

  24. Customer Support http://www.flickr.com/photos/73932893@N00/5774597743 Sunday, October 6, 13 Intercom.io

  25. So you’re sold... http://www.flickr.com/photos/68751915@N05/6757871357 Sunday, October 6, 13

  26. ...but http://www.flickr.com/photos/47854931@N00/3205277810 Sunday, October 6, 13

  27. When should you not use Rails? http://www.flickr.com/photos/12348847@N00/2536358399 Sunday, October 6,

    13 And why
  28. When resource usage matters http://www.flickr.com/photos/22470474@N03/2954044975 Sunday, October 6, 13 Golang

  29. When you want low- latency soft-realtime systems http://www.flickr.com/photos/57578461@N00/4733385644 Sunday, October

    6, 13 Erlang
  30. Go Sunday, October 6, 13

  31. API-first Web Service Sunday, October 6, 13 Sinatra or Rack

    Golang
  32. package main import ( "net/http" "code.google.com/p/go.net/websocket" ) Sunday, October 6,

    13
  33. /* Zone and record representations */ type ZoneNotification struct {

    Name string `json:"name"` " Sha string `json:"sha"` " Url string `json:"url"` " Action string `json:"action"` } Sunday, October 6, 13
  34. type hub struct { broadcast chan string " connections map[*connection]bool

    " register chan *connection " unregister chan *connection } Sunday, October 6, 13
  35. var h = hub{ " broadcast: make(chan string), " connections:

    make(map[*connection]bool), " register: make(chan *connection), " unregister: make(chan *connection), } Sunday, October 6, 13
  36. func (h *hub) run() { for { select { case

    c := <-h.register: h.connections[c] = true case c := <-h.unregister: delete(h.connections, c) close(c.send) case m := <-h.broadcast: for c := range h.connections { select { case c.send <- m: default: delete(h.connections, c) close(c.send) go c.ws.Close() } } } } } Sunday, October 6, 13
  37. Erlang Sunday, October 6, 13

  38. Authoritative DNS Sunday, October 6, 13

  39. -module(erldns_packet_cache). -behavior(gen_server). % API -export([start_link/0, get/1, put/2, sweep/0, clear/0]). %

    Gen server hooks -export([init/1, handle_call/3, " handle_cast/2, " handle_info/2, " terminate/2, " code_change/3 ]). -define(SERVER, ?MODULE). -define(SWEEP_INTERVAL, 1000 * 60 * 10). % Every 10 minutes -record(state, {ttl, tref}). Sunday, October 6, 13
  40. %% Public API start_link() -> gen_server:start_link({local, ?SERVER}, ?MODULE, [], []).

    get(Question) -> gen_server:call(?SERVER, {get_packet, Question}). put(Question, Response) -> gen_server:call(?SERVER, {set_packet, [Question, Response]}). sweep() -> gen_server:cast(?SERVER, {sweep, []}). clear() -> gen_server:cast(?SERVER, {clear}). Sunday, October 6, 13
  41. init([]) -> init([20]); init([TTL]) -> ets:new(packet_cache, [set, named_table]), {ok, Tref}

    = timer:apply_interval(?SWEEP_INTERVAL, ?MODULE, sweep, []), {ok, #state{ttl = TTL, tref = Tref}}. Sunday, October 6, 13
  42. handle_call({get_packet, Question}, _From, State) -> case ets:lookup(packet_cache, Question) of [{Question,

    {Response, ExpiresAt}}] -> {_,T,_} = erlang:now(), case T > ExpiresAt of true -> lager:debug("Cache hit but expired"), {reply, {error, cache_expired}, State}; false -> lager:debug("Time is ~p. Packet hit expires at ~p.", [T, ExpiresAt]), {reply, {ok, Response}, State} end; _ -> {reply, {error, cache_miss}, State} end; Sunday, October 6, 13
  43. handle_call({set_packet, [Question, Response]}, _From, State) -> {_,T,_} = erlang:now(), ets:insert(packet_cache,

    {Question, {Response, T + State#state.ttl}}), {reply, ok, State}. Sunday, October 6, 13
  44. handle_cast({sweep, []}, State) -> lager:debug("Sweeping packet cache"), {_, T, _}

    = erlang:now(), Keys = ets:select(packet_cache, [ {{'$1', {'_', '$2'}}, [{'<', '$2', T - 10}], ['$1']} ]), lager:debug("Found keys: ~p", [Keys]), lists:foreach(fun(K) -> ets:delete(packet_cache, K) end, Keys), {noreply, State}; handle_cast({clear}, State) -> ets:delete_all_objects(packet_cache), {noreply, State}. Sunday, October 6, 13
  45. Clojure Sunday, October 6, 13

  46. (ns cbe.functions (:use [clojure.test])) ;Anonymous function (let [f (fn [x]

    (+ x 1))] (is (= 3 (f 2)))) ;Define a function (def add-fn (fn [a b] (+ a b))) (is (= 3 (add-fn 1 2))) ;Define a function with defn macro (defn add-defn [a b] (+ a b)) (is (= 3 (add-defn 1 2))) Sunday, October 6, 13
  47. (ns cbe.functions (:use [clojure.test])) ;Anonymous function (let [f (fn [x]

    (+ x 1))] (is (= 3 (f 2)))) ;Define a function (def add-fn (fn [a b] (+ a b))) (is (= 3 (add-fn 1 2))) ;Define a function with defn macro (defn add-defn [a b] (+ a b)) (is (= 3 (add-defn 1 2))) JUST KIDDING! Sunday, October 6, 13
  48. http://learnyousomeerlang.com http://tour.golang.org/ Sunday, October 6, 13

  49. Conclusion http://www.flickr.com/photos/59707463@N00/1312379342 Sunday, October 6, 13

  50. Rails is good http://www.flickr.com/photos/95394384@N00/2616644625 Sunday, October 6, 13

  51. Go and Erlang are good Sunday, October 6, 13

  52. Even Clojure is good Sunday, October 6, 13

  53. Go forth and learn http://www.flickr.com/photos/27482959@N08/3154841718 Sunday, October 6, 13

  54. Go forth and build http://www.flickr.com/photos/33049952@N08/9902960523 Sunday, October 6, 13

  55. Launch! http://www.flickr.com/photos/38021965@N00/14473233 Sunday, October 6, 13

  56. And above all... Sunday, October 6, 13

  57. Have fun! http://www.flickr.com/photos/46084814@N04/5678412190 Sunday, October 6, 13

  58. Rails: Still the Best Framework for Bootstrapping Anthony Eden Founder

    of DNSimple Sunday, October 6, 13