SlideShare a Scribd company logo
1 of 110
Single Page Applications
Use cases with CoffeeScript, DCI, AOP, TDD



  Andrzej Krzywda
Kto lubi pisać w JavaScript?
Agenda

• Frontend - Zmiana sposobu myślenia
• Single Page Application
• Frontend - architektura
Zmiana sposobu
   myślenia
Dumny
programista
backendów
(2007 - 2008)



     “JavaScript?
  My zajmujemy się
poważnymi projektami”
Rails consulting since 2007
“OK, zrobimy
autocompletion”
“Znajdźmy jakiś plugin
  railsowy, który to
generuje i nie patrzmy
      do środka”
“Czy ceny mogą
się zmieniać bez
przeładowania?”
“Renderujmy JavaScript
 po stronie serwera”
“Pokazywanie słówek
 bez przeładowania”
Backendy - Ruby
Frontendy - Coffee
Social games for brands

(gierki i konkursy na FB i strony firmowe)
“Gra w kółko i
krzyżyk, potem wybór
      nagrody”
Hybryda
Pierwsza wersja naszej
platformy tak działała.
Platforma GameBoxed
           ==
     jeden backend,
   wiele frontendów
        market
Gdzie renderujemy
      html?
Cały html na
frontendzie, serwer
tylko zwraca JSON.
HTML na frontendzie
nie różni się od HTML
     na backendzie
<p>
W tej sesji gry niesamowite umiejętności
strzeleckie
pozwolily Ci osiągnąć nowy rekord:<br>
<b>{{playerMaxScore}} punktów.</b>
</p>

<a class="button ok_button">DALEJ</a>


                    handlebar
Rewolucja
Frontend to osobna aplikacja
Market 2.0
Pusher

web sockets
Pusher
Zmiana sposobu myślenia
      W której fazie jest Twój projekt?

• Faza 1: No JavaScript
• Faza 2: JQuery explosion
• Faza 3: Page/Widget object
• Faza 4: Single Page Application
Single Page Application

   Gmail, Twitter, Facebook, Trello
CoffeeScript
 better JS
Class oriented language
Same zalety
JS == assembler
Coffee > Ruby
underscore.js
GameBoxed używa
 tylko Coffee do
   frontend’ów
Polecamy!
Single Page Application



Architektura
Trygve
MVC, DCI
Zapomnijmy o MVC z
    backendu!
Nie ma MVC na
  backendzie
Nie ma View na
  backendzie
Prawdziwe MVC
  (w uproszczeniu - zmiana w modelu
powoduje automatyczną zmianę w GUI)

  (Rails, Struts, Spring - nie są MVC!)
GUI - model
Modele
•   Game

•   Player

•   GameSession

•   Round

•   Prize

•   Friend (Invitation)

•   Life (LifeRequest...)

•   Team
Views

• PrizeComponent
• FriendsComponent
• GameArea
• Popups
Pierwsze podejście
Popupy


• Wyświetl popup z zespołem gracza
• Po naciśnięciu OK, wyświetl popup z
  nagrodami
Callbacks
triggerActionsAfterMove: (move, callback) =>
  @getBonusWhenStartCrossed(move)
  @getBonusWhenLandedOnCellWithFriends(@board.currentCell())
  @pickCardAndNotifyIfAny(@board.currentCell(), callback)
pickCardAndNotifyIfAny: (cell, callback) =>
  console.debug "pickCardAndNotifyIfAny #{cell.position}"
  card = @drawCard(cell)
  if not card
    console.debug "no card picked"
    callback?()
    return
  console.debug "card found: #{card.identifier}"
  card.onPicked(@) if card.onPicked?
  @eventBroker.trigger("player:picked_card:#{card.identifier}", card, callback)
  @eventBroker.trigger("player:picked_card", card)
class engine.monopoly.controllers.CardItemBargainContoller
  constructor: (@services, @game) ->
    @helper = new CardHelperForUsecases(@services)

  setup: =>
    @services.eventBroker.bind('player:picked_card:CardItemBargain', @execute)

  execute: (card, callback) =>
    @popup = @helper.showCardGenericPopupAndBindOnOK(
	   	   (=> @applyFormDataToBargain(card, callback)), null)
    @popup.bind("popup:opened", => @popup.find('input').focus())



  applyFormDataToBargain: (card, callback) =>
    offer = @popup.find('input').val()
    new CardItemBargain(@services, @game).execute(card, offer, callback)
Eventy
class engine.shooter.components.StageResultWon

  constructor: (@eventBroker) ->
    _.extend(@, Backbone.Events)
    super()
    @templateId = "stage_result_won"

  addMeToScreen: (root, me) =>
    $("#gameArea").append(me)



  configureElement: (me) =>
    me.find('.okButton').mousedown (event) =>
      @hide()
      @eventBroker.trigger('stage:result:shown')
class engine.shooter.models.Game

    constructor: (@serverSide, @eventBroker) ->
      super(@eventBroker)
      @levels = []
      @guns = []

    registerEvents: (eventBroker) =>
      eventBroker.bind('game:start:requested', @start)

      eventBroker.bind("player:clicked:inside-target", @playerTriggeredShotInsideTarget)
      eventBroker.bind("player:clicked:magazine:reload", @playerWantsToReload)

      eventBroker.bind("stage:start:clicked", @startStageClicked)
      eventBroker.bind('countdown:stage:finish', @finishCurrentStage)


	    eventBroker.bind("stage:result:shown", @loadNextStageOrFinishGame)
Wymagana duża
  dyscyplina
Gdzie jest główne flow?
Use cases
UsecaseController
      DCI
Piotrek
Game Designer
Tomek - programista
 (praca zdalna w praktyce)
class engine.invite_and_win.GameUseCase
  constructor: (@game, @player) ->
    ObjectHelper.addRole(@player, engine.shared.models.PlayerWithFriends)

    @facebookHQ = new engine.invite_and_win.FacebookHQ()

 tryToEnterGameArea: () =>
   if @amIEnteringGameFirstTime()
     if @amICommingFromInvitation()
       @tellPlayerHeIsPartOfTeam(@facebookHQ.friendsInviting)

      @teachPlayerHowToPlay()



   else #n-th time...
     if @amICommingFromInvitation()
       @tellPlayerHeIsPartOfTeam(@facebookHQ.friendsInviting)

   if not @playerLikesFanpage()
     @askPlayerToLikeFanpage()

   if @haveNotYetPickedFavPizzaCountry()
     @askPlayerToDeclareHisFavCountry()
Use case używa
  dziedzinę
Ani use case, ani
dziedzina, nie wiedzą
     nic o GUI
Ani use case, ani
dziedzina, nie wiedzą
  nic o persistence
Use case’y mogą działać
 z innym GUI i innym
      persistence
Gdzie jest DCI?
Data Context Interaction

                Trygve
Dane pozostają w
   obiektach
      Data
Obiekty są dosyć
   “cienkie”
class engine.shared.models.Player
  constructor: () ->
    @rank = null
    @maxScore = 0
Use case to zachowanie
         Context
Obiekty mają
wstrzykiwane role
     Interaction
Role są dodawane
    runtime!
class engine.invite_and_win.GameUseCase
  constructor: (@game, @player) ->
    ObjectHelper.addRole(@player, engine.shared.models.PlayerWithFriends)

 tryToEnterGameArea: () =>
   if @amIEnteringGameFirstTime()
     if @amICommingFromInvitation()
       @tellPlayerHeIsPartOfTeam(@facebookHQ.friendsInviting)
                                                                            rola
      @teachPlayerHowToPlay()



   else #n-th time...
     if @amICommingFromInvitation()
       @tellPlayerHeIsPartOfTeam(@facebookHQ.friendsInviting)

   if not @playerLikesFanpage()
     @askPlayerToLikeFanpage()

   if @haveNotYetPickedFavPizzaCountry()
     @askPlayerToDeclareHisFavCountry()
OOP != COP
class engine.shared.models.PlayerWithFriends extends Mixin
  setup: =>
    @friends = []
    @invitedFriends = []
    @acceptedFriends = []

  setInvitedFriends: (facebookUids) =>
    for facebookUid in facebookUids
      friend = new Friend({facebookUid: facebookUid})
      @invitedFriends.push(friend)

  setFriends: (friends) =>
    @friends = friends

  addFriend: (friend) =>
    existing = @getFriendByFacebookUid(friend?.facebookUid)
    if not existing?
      @friends.push(friend)
class engine.invite_and_win.GameGuiConfiguration
  constructor: (@gameUseCase, @game, @gui, @services, @sharedComponents) ->

  execute: () =>
    Around(@gameUseCase,   'tryToEnterGameArea',                  @checkFbInvitation)
    After (@gameUseCase,   'tryToEnterGameArea',                  @showTeamArea)
    After (@gameUseCase,   'tryToEnterGameArea',                  @showButtonInviteOrPostPicture)
    Around(@gameUseCase,   'tellPlayerHeIsPartOfTeam',            @showTeamPopup)
    Around(@gameUseCase,   'askPlayerToLikeFanpage',              @showLikePopup)
    Around(@gameUseCase,   'teachPlayerHowToPlay',                @showTutorialPopup)
    Around(@gameUseCase,   'playerWantsToKnowWinnersWithPrize',   @showWinnersPopup)
    Around(@gameUseCase,   'playerWantsToKnowPrizes',             @showPrizesPopup)
    Around(@gameUseCase,   'askPlayerToDeclareHisFavCountry',     @showDeclareCountryPopup)
    Around(@gameUseCase,   'iAcceptMyFriendInvitationToATeam',    @onIAcceptMyFriendInvitationToATeam)
Around(@gameUseCase, 'tellPlayerHeIsPartOfTeam', @showTeamPopup)
showTeamPopup: (proceed, friendsInviting) =>
  data = {inviting_friends: friendsInviting}
  popup = @popupsComponent.showPopup('team_popup', data)
  popup.bind('popup:closed', => proceed(friendsInviting))
Persistence
ServerSide
class engine.shared.server.ServerSide
  constructor: (@gameBasicDetails) ->
    @gameEngineUrl = "/engine/games/#{@gameBasicDetails.id}"
    @gameUrl = "/games/#{@gameBasicDetails.id}"
    @errors = []

  gameDetailsLoaded: (gameDetails, callback) =>
    callback(gameDetails)

  fetchGameDetails: (callback, errback) =>
    $.ajax(
      type: "GET"
      url: "#{@gameEngineUrl}.json"
      success: (gameDetails) =>
        @gameDetailsLoaded(gameDetails, callback)
      error: errback
    )
My ładujemy dane na
      starcie
Można ładować w
    trakcie
Testowanie
scenario "player enters and has no friends", ->
  @player.enterGame(@playerWithNoFriends)
  @player.shouldSeeMainAreaWithInviteButton()
  @player.shouldSeeRemainingFriendsToCompleteTeam(4)

scenario "player enters and has collected part team", ->
  @player.enterGame(@playerWith3AcceptedFriends)
  @player.shouldSeeMainAreaWithInviteButton()
  @player.shouldSeeRemainingFriendsToCompleteTeam(1)

scenario "player enters and has collected whole team", ->
  @player.enterGame(@playerWith4AcceptedFriends)
  @player.shouldSeeMainAreaWithPostToWallButton()
TDD
Acceptance tests

   with test.ServerSide
Reużycie?
Jak reużyć kod po obu
       stronach?
Nie wiem.
Czy Google
spozycjonuje SPA?
Tak.
Ale trzeba renderować
    html po stronie
       serwera
Frameworks
My nie potrzebujemy
Ty prawdopodobnie też
   nie potrzebujesz.
Krytyka Backbone.js
powiązanie danych z
    widokami
a gdzie logika
 biznesowa?
Backbone Models
Przydatne do API, ale
nie używajmy ich jako
      dziedziny
Relations/objects
    mismatch
Resources/objects
    mismatch
Libraries - yes
Frameworks - no
Bardzo ważne pytanie
A może Twój projekt
   powinien być
  SinglePageApp?
Co jest lepsze dla
 użytkowników?
tl;dr
• Frontend to osobna aplikacja
• Używaj CoffeeScript
• Nie używaj frameworków
• Pisz use case’y w kodzie
• Poczytaj o DCI
• Twórz fajne frontendy
Pytania?

  Dziękuję!
    @andrzejkrzywda
http://andrzejkrzywda.com
 (ostatnio sporo bloguję o frontendach)

More Related Content

Similar to Single Page Applications with CoffeeScript [Polish]

Tworzenie Chatbotów z wykorzystaniem BotMan'a
Tworzenie Chatbotów z wykorzystaniem BotMan'aTworzenie Chatbotów z wykorzystaniem BotMan'a
Tworzenie Chatbotów z wykorzystaniem BotMan'aLaravel Poland MeetUp
 
Laravel Poznań Meetup #2 - Tworzenie chatbotów z BotMan
Laravel Poznań Meetup #2 - Tworzenie chatbotów z BotManLaravel Poznań Meetup #2 - Tworzenie chatbotów z BotMan
Laravel Poznań Meetup #2 - Tworzenie chatbotów z BotManHighSolutions Sp. z o.o.
 
The starling framework
The starling frameworkThe starling framework
The starling frameworkukaszdev
 
Functional widgets in Rails
Functional widgets in RailsFunctional widgets in Rails
Functional widgets in RailsSebastian Sito
 
Konrad Kokosa - Pamięć w .NET - od ogólu do szczegółu- 4developers2016
Konrad Kokosa - Pamięć w .NET - od ogólu do szczegółu- 4developers2016Konrad Kokosa - Pamięć w .NET - od ogólu do szczegółu- 4developers2016
Konrad Kokosa - Pamięć w .NET - od ogólu do szczegółu- 4developers2016PROIDEA
 
Modularny JavaScript - meet.js
Modularny JavaScript - meet.jsModularny JavaScript - meet.js
Modularny JavaScript - meet.jsPatryk Jar
 
Metaprogramowanie w JS
Metaprogramowanie w JSMetaprogramowanie w JS
Metaprogramowanie w JSDawid Rusnak
 
AngularJS - podstawy
AngularJS - podstawyAngularJS - podstawy
AngularJS - podstawyApptension
 
Asynchroniczne testy JavaScript aplikacji webowych
Asynchroniczne testy JavaScript aplikacji webowychAsynchroniczne testy JavaScript aplikacji webowych
Asynchroniczne testy JavaScript aplikacji webowychFuture Processing
 
Angular restmod – wygodny sposób na komunikację z API
Angular restmod – wygodny sposób na komunikację z APIAngular restmod – wygodny sposób na komunikację z API
Angular restmod – wygodny sposób na komunikację z APIThe Software House
 
WebDeveloper - Yesterday, Today, Tomorrow
WebDeveloper - Yesterday, Today, TomorrowWebDeveloper - Yesterday, Today, Tomorrow
WebDeveloper - Yesterday, Today, TomorrowMarcin Dembowski
 
TGT#14 - @Before – Nie będę automatyzować @After – No dobra, to nie jest taki...
TGT#14 - @Before – Nie będę automatyzować @After – No dobra, to nie jest taki...TGT#14 - @Before – Nie będę automatyzować @After – No dobra, to nie jest taki...
TGT#14 - @Before – Nie będę automatyzować @After – No dobra, to nie jest taki...Trójmiejska Grupa Testerska
 
Programowanie aplikacji dla Windows 8 (WinRT)
Programowanie aplikacji dla Windows 8 (WinRT)Programowanie aplikacji dla Windows 8 (WinRT)
Programowanie aplikacji dla Windows 8 (WinRT)Bartlomiej Zass
 
AADays 2015 - Jak to zrobic w JavaScript
AADays 2015 - Jak to zrobic w JavaScriptAADays 2015 - Jak to zrobic w JavaScript
AADays 2015 - Jak to zrobic w JavaScriptJacek Okrojek
 
REST API - teoria i praktyka - WordUp Trójmiasto
REST API - teoria i praktyka - WordUp TrójmiastoREST API - teoria i praktyka - WordUp Trójmiasto
REST API - teoria i praktyka - WordUp TrójmiastoTomasz Dziuda
 
TWIG - niezłe widoki dla PHP
TWIG - niezłe widoki dla PHPTWIG - niezłe widoki dla PHP
TWIG - niezłe widoki dla PHPPiotr Gabryjeluk
 

Similar to Single Page Applications with CoffeeScript [Polish] (20)

Tworzenie Chatbotów z wykorzystaniem BotMan'a
Tworzenie Chatbotów z wykorzystaniem BotMan'aTworzenie Chatbotów z wykorzystaniem BotMan'a
Tworzenie Chatbotów z wykorzystaniem BotMan'a
 
Laravel Poznań Meetup #2 - Tworzenie chatbotów z BotMan
Laravel Poznań Meetup #2 - Tworzenie chatbotów z BotManLaravel Poznań Meetup #2 - Tworzenie chatbotów z BotMan
Laravel Poznań Meetup #2 - Tworzenie chatbotów z BotMan
 
The starling framework
The starling frameworkThe starling framework
The starling framework
 
Functional widgets in Rails
Functional widgets in RailsFunctional widgets in Rails
Functional widgets in Rails
 
Platforma Kontentowa
Platforma KontentowaPlatforma Kontentowa
Platforma Kontentowa
 
Konrad Kokosa - Pamięć w .NET - od ogólu do szczegółu- 4developers2016
Konrad Kokosa - Pamięć w .NET - od ogólu do szczegółu- 4developers2016Konrad Kokosa - Pamięć w .NET - od ogólu do szczegółu- 4developers2016
Konrad Kokosa - Pamięć w .NET - od ogólu do szczegółu- 4developers2016
 
Modularny JavaScript - meet.js
Modularny JavaScript - meet.jsModularny JavaScript - meet.js
Modularny JavaScript - meet.js
 
Metaprogramowanie w JS
Metaprogramowanie w JSMetaprogramowanie w JS
Metaprogramowanie w JS
 
AngularJS - podstawy
AngularJS - podstawyAngularJS - podstawy
AngularJS - podstawy
 
Asynchroniczne testy JavaScript aplikacji webowych
Asynchroniczne testy JavaScript aplikacji webowychAsynchroniczne testy JavaScript aplikacji webowych
Asynchroniczne testy JavaScript aplikacji webowych
 
Angular restmod – wygodny sposób na komunikację z API
Angular restmod – wygodny sposób na komunikację z APIAngular restmod – wygodny sposób na komunikację z API
Angular restmod – wygodny sposób na komunikację z API
 
Angular Restmod
Angular RestmodAngular Restmod
Angular Restmod
 
Podstawy php
Podstawy phpPodstawy php
Podstawy php
 
WebDeveloper - Yesterday, Today, Tomorrow
WebDeveloper - Yesterday, Today, TomorrowWebDeveloper - Yesterday, Today, Tomorrow
WebDeveloper - Yesterday, Today, Tomorrow
 
TGT#14 - @Before – Nie będę automatyzować @After – No dobra, to nie jest taki...
TGT#14 - @Before – Nie będę automatyzować @After – No dobra, to nie jest taki...TGT#14 - @Before – Nie będę automatyzować @After – No dobra, to nie jest taki...
TGT#14 - @Before – Nie będę automatyzować @After – No dobra, to nie jest taki...
 
Programowanie aplikacji dla Windows 8 (WinRT)
Programowanie aplikacji dla Windows 8 (WinRT)Programowanie aplikacji dla Windows 8 (WinRT)
Programowanie aplikacji dla Windows 8 (WinRT)
 
AADays 2015 - Jak to zrobic w JavaScript
AADays 2015 - Jak to zrobic w JavaScriptAADays 2015 - Jak to zrobic w JavaScript
AADays 2015 - Jak to zrobic w JavaScript
 
REST API - teoria i praktyka - WordUp Trójmiasto
REST API - teoria i praktyka - WordUp TrójmiastoREST API - teoria i praktyka - WordUp Trójmiasto
REST API - teoria i praktyka - WordUp Trójmiasto
 
Podstawy php
Podstawy phpPodstawy php
Podstawy php
 
TWIG - niezłe widoki dla PHP
TWIG - niezłe widoki dla PHPTWIG - niezłe widoki dla PHP
TWIG - niezłe widoki dla PHP
 

More from Andrzej Krzywda

[PL] PRUG Luty 2022 - Service objecty to za mało - jak żyć z Railsami?
[PL] PRUG Luty 2022 - Service objecty to za mało - jak żyć z Railsami?[PL] PRUG Luty 2022 - Service objecty to za mało - jak żyć z Railsami?
[PL] PRUG Luty 2022 - Service objecty to za mało - jak żyć z Railsami?Andrzej Krzywda
 
[PL] Service objecty to za mało - jak żyć z Railsami?
[PL] Service objecty to za mało - jak żyć z Railsami?[PL] Service objecty to za mało - jak żyć z Railsami?
[PL] Service objecty to za mało - jak żyć z Railsami?Andrzej Krzywda
 
Audit log with event sourcing
Audit log with event sourcingAudit log with event sourcing
Audit log with event sourcingAndrzej Krzywda
 
Event driven without microservices
Event driven without microservicesEvent driven without microservices
Event driven without microservicesAndrzej Krzywda
 
From legacy to DDD - 5 starting steps
From legacy to DDD - 5 starting stepsFrom legacy to DDD - 5 starting steps
From legacy to DDD - 5 starting stepsAndrzej Krzywda
 
Slack protips from Arkency
Slack protips from ArkencySlack protips from Arkency
Slack protips from ArkencyAndrzej Krzywda
 
From Rails legacy to DDD - Pivorak, Lviv
From Rails legacy to DDD - Pivorak, LvivFrom Rails legacy to DDD - Pivorak, Lviv
From Rails legacy to DDD - Pivorak, LvivAndrzej Krzywda
 
From legacy to DDD (slides for the screencast)
From legacy to DDD (slides for the screencast)From legacy to DDD (slides for the screencast)
From legacy to DDD (slides for the screencast)Andrzej Krzywda
 
DCI - the architecture from the future
DCI - the architecture from the futureDCI - the architecture from the future
DCI - the architecture from the futureAndrzej Krzywda
 
Refactoring Rails applications with RubyMine
Refactoring Rails applications with RubyMineRefactoring Rails applications with RubyMine
Refactoring Rails applications with RubyMineAndrzej Krzywda
 
Service objects in Rails tests - factory_girl replacement
Service objects in Rails tests - factory_girl replacementService objects in Rails tests - factory_girl replacement
Service objects in Rails tests - factory_girl replacementAndrzej Krzywda
 
A programmer or a business consultant?
A programmer or a business consultant?A programmer or a business consultant?
A programmer or a business consultant?Andrzej Krzywda
 
Rails refactoring call for help
Rails refactoring call for helpRails refactoring call for help
Rails refactoring call for helpAndrzej Krzywda
 
[Polish] Praca zdalna, praca asynchroniczna
[Polish] Praca zdalna, praca asynchroniczna[Polish] Praca zdalna, praca asynchroniczna
[Polish] Praca zdalna, praca asynchronicznaAndrzej Krzywda
 
Use cases in the code with AOP
Use cases in the code with AOPUse cases in the code with AOP
Use cases in the code with AOPAndrzej Krzywda
 

More from Andrzej Krzywda (20)

[PL] PRUG Luty 2022 - Service objecty to za mało - jak żyć z Railsami?
[PL] PRUG Luty 2022 - Service objecty to za mało - jak żyć z Railsami?[PL] PRUG Luty 2022 - Service objecty to za mało - jak żyć z Railsami?
[PL] PRUG Luty 2022 - Service objecty to za mało - jak żyć z Railsami?
 
[PL] Service objecty to za mało - jak żyć z Railsami?
[PL] Service objecty to za mało - jak żyć z Railsami?[PL] Service objecty to za mało - jak żyć z Railsami?
[PL] Service objecty to za mało - jak żyć z Railsami?
 
Audit log with event sourcing
Audit log with event sourcingAudit log with event sourcing
Audit log with event sourcing
 
Event driven without microservices
Event driven without microservicesEvent driven without microservices
Event driven without microservices
 
From legacy to DDD - 5 starting steps
From legacy to DDD - 5 starting stepsFrom legacy to DDD - 5 starting steps
From legacy to DDD - 5 starting steps
 
Slack protips from Arkency
Slack protips from ArkencySlack protips from Arkency
Slack protips from Arkency
 
From Rails legacy to DDD - Pivorak, Lviv
From Rails legacy to DDD - Pivorak, LvivFrom Rails legacy to DDD - Pivorak, Lviv
From Rails legacy to DDD - Pivorak, Lviv
 
From legacy to DDD (slides for the screencast)
From legacy to DDD (slides for the screencast)From legacy to DDD (slides for the screencast)
From legacy to DDD (slides for the screencast)
 
From legacy to DDD
From legacy to DDDFrom legacy to DDD
From legacy to DDD
 
DCI - the architecture from the future
DCI - the architecture from the futureDCI - the architecture from the future
DCI - the architecture from the future
 
Refactoring Rails applications with RubyMine
Refactoring Rails applications with RubyMineRefactoring Rails applications with RubyMine
Refactoring Rails applications with RubyMine
 
Beyond The Rails Way
Beyond The Rails WayBeyond The Rails Way
Beyond The Rails Way
 
Service objects in Rails tests - factory_girl replacement
Service objects in Rails tests - factory_girl replacementService objects in Rails tests - factory_girl replacement
Service objects in Rails tests - factory_girl replacement
 
Developer oriented
Developer orientedDeveloper oriented
Developer oriented
 
Can you TDD Rails?
Can you TDD Rails?Can you TDD Rails?
Can you TDD Rails?
 
A programmer or a business consultant?
A programmer or a business consultant?A programmer or a business consultant?
A programmer or a business consultant?
 
Rails refactoring call for help
Rails refactoring call for helpRails refactoring call for help
Rails refactoring call for help
 
[Polish] Praca zdalna, praca asynchroniczna
[Polish] Praca zdalna, praca asynchroniczna[Polish] Praca zdalna, praca asynchroniczna
[Polish] Praca zdalna, praca asynchroniczna
 
Use cases in the code with AOP
Use cases in the code with AOPUse cases in the code with AOP
Use cases in the code with AOP
 
Madeleine on Rails
Madeleine on RailsMadeleine on Rails
Madeleine on Rails
 

Single Page Applications with CoffeeScript [Polish]

Editor's Notes

  1. \n
  2. \n
  3. \n
  4. \n
  5. \n
  6. \n
  7. \n
  8. \n
  9. \n
  10. \n
  11. \n
  12. \n
  13. \n
  14. \n
  15. \n
  16. \n
  17. \n
  18. \n
  19. \n
  20. \n
  21. \n
  22. \n
  23. \n
  24. \n
  25. \n
  26. \n
  27. \n
  28. \n
  29. \n
  30. \n
  31. \n
  32. \n
  33. \n
  34. \n
  35. \n
  36. \n
  37. \n
  38. \n
  39. \n
  40. \n
  41. \n
  42. \n
  43. \n
  44. \n
  45. \n
  46. \n
  47. \n
  48. \n
  49. \n
  50. \n
  51. \n
  52. \n
  53. \n
  54. \n
  55. \n
  56. \n
  57. \n
  58. \n
  59. \n
  60. \n
  61. \n
  62. \n
  63. \n
  64. \n
  65. \n
  66. \n
  67. \n
  68. \n
  69. \n
  70. \n
  71. \n
  72. \n
  73. \n
  74. \n
  75. \n
  76. \n
  77. \n
  78. \n
  79. \n
  80. \n
  81. \n
  82. \n
  83. \n
  84. \n
  85. \n
  86. \n
  87. \n
  88. \n
  89. \n
  90. \n
  91. \n
  92. \n
  93. \n
  94. \n
  95. \n
  96. \n
  97. \n
  98. \n
  99. \n
  100. \n
  101. \n
  102. \n
  103. \n
  104. \n
  105. \n
  106. \n
  107. \n
  108. \n
  109. \n
  110. \n