MoneyBird - The Rails Side

1,391 views

Published on

Short presentation of the Rails side of MoneyBird, given at the Twente.rb meeting on 26 november 2008.

Published in: Technology, Economy & Finance
0 Comments
2 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
1,391
On SlideShare
0
From Embeds
0
Number of Embeds
396
Actions
Shares
0
Downloads
11
Comments
0
Likes
2
Embeds 0
No embeds

No notes for slide

MoneyBird - The Rails Side

  1. 1. The Rails side! Edwin Vlieg - BlueTools Twente.rb - november 2008
  2. 2. MoneyBird • Simpele facturatie voor kleine bedrijven • Facturen aanmaken, versturen en beheren • Simpel contactbeheer • Binnenkort periodieke facturen • Innovatieve Ajax interface voor factuur bewerken Edwin Vlieg — MoneyBird 2008 2
  3. 3. MoneyBird • April 2008: eerste idee • Juni 2008: prototypes van applicatie gereed (HTML mockups met JavaScript functionaliteit) • September 2008: test versie gereed • Oktober 2008: live! Edwin Vlieg — MoneyBird 2008 3
  4. 4. The Rails side! +‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐+‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐+‐‐‐‐‐+‐‐‐‐‐‐‐+ | Name                 | Lines |   LOC | Classes | Methods | M/C | LOC/M | +‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐+‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐+‐‐‐‐‐+‐‐‐‐‐‐‐+ | Controllers          |   977 |   779 |      10 |      89 |   8 |     6 | | Helpers              |   300 |   194 |       0 |      30 |   0 |     4 | | Models               |  1340 |   983 |      22 |     127 |   5 |     5 | | Libraries            |   830 |   575 |       4 |      61 |  15 |     7 | | Model specs          |  1045 |   826 |       0 |       3 |   0 |   273 | | View specs           |   252 |   189 |       0 |       0 |   0 |     0 | | Controller specs     |   678 |   560 |       1 |       6 |   6 |    91 | | Helper specs         |   185 |   162 |       0 |       0 |   0 |     0 | | Library specs        |    68 |    57 |       1 |       0 |   0 |     0 | +‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐+‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐+‐‐‐‐‐+‐‐‐‐‐‐‐+ | Total                |  5675 |  4325 |      38 |     316 |   8 |    11 | +‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐+‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐+‐‐‐‐‐+‐‐‐‐‐‐‐+   Code LOC: 2531     Test LOC: 1794     Code to Test Ratio: 1:0.7 Edwin Vlieg — MoneyBird 2008 4
  5. 5. The Rails side! • Rails 2.2 (since this week!) • PostgreSQL • Capistrano • Developed in TextMate Edwin Vlieg — MoneyBird 2008 5
  6. 6. Plugins • acts_as_state_machine • attachment_fu • i18n_labels • localized_dates • subdomain_fu • restful-authentication Edwin Vlieg — MoneyBird 2008 6
  7. 7. Rails 2.2: I18n • Scoping # Override translate method to consider translate_scope. def t(text, options = {}) scope = (translate_scope.dup << options.delete(:subscope)).compact super(text, {:scope => scope}.merge(options)) end # The current translation scope, default to current controller name. def translate_scope @translate_scope || [template.base_path] end Edwin Vlieg — MoneyBird 2008 7
  8. 8. Rails 2.2: I18n • Localized labels, based on ActiveRecord::human_attribute_name <tr> <th><%= f.label :name %></label></th> <td> <%= f.text_field :name %> <%= error_message_on :contact, :name %> </td> </tr> <tr> <th><%= f.label :contact_name %></th> <td><%= f.text_field :contact_name %></td> </tr> Edwin Vlieg — MoneyBird 2008 8
  9. 9. Rails 2.2: I18n • In locales definition: nl: activerecord: attributes: contact: contact_name: Contactpersoon name: Naam of Bedrijfsnaam Edwin Vlieg — MoneyBird 2008 9
  10. 10. Testing • RSpec • For testing models (business logic) • Covers 141 examples • Cucumber • Plain text stories for integration testing • Covers 535 steps • Factory girl • Webrat Edwin Vlieg — MoneyBird 2008 10
  11. 11. Testing: Cucumber Feature: invoice An user should be able to manage his invoices Scenario: Create a new invoice Given I'm logged in as edwin at bluetools When I follow quot;New invoicequot; And I fill in quot;Name or Companynamequot; with quot;Test companyquot; And I fill in quot;Addressquot; with quot;Hengelosestraat 534quot; And I fill in quot;invoice_zipcodequot; with quot;7500AGquot; And I fill in quot;invoice_cityquot; with quot;Enschedequot; And I fill in quot;invoice_new_detail_attributes__descriptionquot; with quot;Test descriptionquot; And I fill in quot;invoice_new_detail_attributes__pricequot; with quot;123quot; And I press quot;Savequot; Then an invoice with invoice id quot;2008-0001quot; should exist And I should see quot;2008-0001quot; And I should see quot;Test companyquot; And I should see quot;Test descriptionquot; Scenario: Create a new invoice with no invoice details Given I'm logged in as edwin at bluetools When I follow quot;New invoicequot; And I fill in quot;Name or Companynamequot; with quot;Test companyquot; And I fill in quot;Addressquot; with quot;Hengelosestraat 534quot; And I fill in quot;invoice_zipcodequot; with quot;7500AGquot; And I fill in quot;invoice_cityquot; with quot;Enschedequot; And I press quot;Savequot; Then no invoice with name quot;Test companyquot; should exist And I should see quot;Details should contain at least one rowquot; Edwin Vlieg — MoneyBird 2008 11
  12. 12. Testing: Cucumber • Only ~30 steps defined! • Example resource definition and assertion: Given /^I've created (a|an) ([A-z].*) with ([A-z ].* quot;.*quot;( and )?)+$/ do |_, resource, fields, _| #' fields = fields.split(quot; and quot;).collect { |f| r = f.strip.match(/^([A-z ].*) quot;(.*)quot;$/); [r[1].tr(quot; quot;, quot;_quot;).underscore, r[2]] }.flatten Factory(resource.tr(quot; quot;, quot;_quot;).to_sym, Hash[*fields]) end # Then a company with name quot;foobarquot; should exist Then /^(a|an|no) ([A-z].*) with ([A-z ].*) quot;(.*)quot; should exist$/ do |condition, resource, field, value| if resource.to_class.respond_to?(:exists?) condition = condition == 'no' ? false : true resource.to_class.exists?({ field.tr(quot; quot;, quot;_quot;).underscore => value }).should == condition else raise quot;Resource #{resource.classify} isn't a modelquot; end end Edwin Vlieg — MoneyBird 2008 12
  13. 13. PDF generation • PDF writer: • API.... :-( • PNG file errors (‘PNG uses more than 8 bits’, ‘Invalid filter algorithm 61’) Edwin Vlieg — MoneyBird 2008 13
  14. 14. PDF generation • Prawn • API... :-) • Better PNG support • Only the Euro sign doesn’t show up Edwin Vlieg — MoneyBird 2008 14
  15. 15. PDF generation Prawn::Document.generate(quot;fancy_table.pdfquot;) do data = [[quot;Gregory Brownquot;, quot;gregory.t.brown@fakemail.testquot; ], [quot;James Healyquot; , quot;jimmy@fakemail.testquot; ], [quot;Ross Perotquot; , quot;ross@fakemail.testquot; ], [quot;Al Gorequot; , quot;al@fakemail.testquot; ], [quot;Ralph Naderquot; , quot;ralph@fakemail.testquot; ]] table data, :position => :center, :headers => [quot;Namequot;, quot;Emailquot;], :row_colors => [quot;ffffffquot;,quot;ffff00quot;], :vertical_padding => 5, :horizontal_padding => 3 end Edwin Vlieg — MoneyBird 2008 15
  16. 16. Concerned_with • Problem: Invoice model has 450 LOC • Other models have on average 200 LOC • Make the model less fat with concerned_with Edwin Vlieg — MoneyBird 2008 16
  17. 17. Concerned_with # In config/initializers class << ActiveRecord::Base def concerned_with(*concerns) concerns.each do |concern| require_dependency quot;#{name.underscore}/#{concern}quot; end end end # In models/invoice.rb class Invoice < ActiveRecord::Base concerned_with :validations, :states, :policies, :scopes ... end # In models/invoice/validations.rb class Invoice validates_presence_of ... end Edwin Vlieg — MoneyBird 2008 17
  18. 18. Invoice edit interface • Difference between new and edit action: • ‘edit’ is performed on an persistant instance • ‘new’ does not exist after the request has finished Edwin Vlieg — MoneyBird 2008 18
  19. 19. Invoice edit interface • Solution: always load the complete form on the background • Switch between display and form with JS • Just plain old submitting the complete form for creating a new record Edwin Vlieg — MoneyBird 2008 19
  20. 20. Invoice edit interface • Input is validated and rendered via an Ajax call. <div id=quot;invoice_descriptionquot;> <div class=quot;showquot;> <%= render :partial => quot;invoice_descriptionquot; %> </div> <div class=quot;formquot;> <%= render :partial => quot;invoice_description_formquot; %> </div> </div> Edwin Vlieg — MoneyBird 2008 20
  21. 21. The End! Try MoneyBird for free at www.moneybird.nl info@moneybird.nl blog.bluetools.nl

×