Upgrade to Pro — share decks privately, control downloads, hide ads and more …

OpenBuildings Modules

Avatar for Ivan Kerin Ivan Kerin
November 01, 2012

OpenBuildings Modules

Avatar for Ivan Kerin

Ivan Kerin

November 01, 2012
Tweet

More Decks by Ivan Kerin

Other Decks in Technology

Transcript

  1. Asset Merger combine and minify css / javascript files for

    faster download use exotic languages ( LESS, SASS, CoffeeScript ) Handle IE Conditional comments, external libriaries Thursday, November 1, 12
  2. Asset Merger <?php echo Assets::factory('main') ->css('css/reset.css') ->css("css/elements.css") ->css("css/typography.css") ->css('http://fonts.googleapis.com/css?family=Economica:400,700|Schoolbell') ->css('css/ie.css',

    array('condition' => 'IE')) ->css('css/jquery.clippings.windows.css') ->js('http://use.typekit.net/jwk6rso.js') ->js_block('try{Typekit.load();}catch(e){}') ->js("http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js", array('fallback' => array('window.jQuery', '/js/plugins/jquery-1.7.2.min.js'))) ->js("plugins/jquery.clippings.tooltips.js") ->js("plugins/jquery.clippings.attachments.js") ->js("main/general.js", array('processor' => 'jsmin')) ->render(); ?> Thursday, November 1, 12
  3. <?php echo Assets::factory('main') ->css('css/reset.css') ->css("css/elements.css") ->css("css/typography.css") ->css('http://fonts.googleapis.com/css?family=Economica:400,700|Schoolbell') ->css('css/ie.css', array('condition' =>

    'IE')) ->css('css/jquery.clippings.windows.css') ->js('http://use.typekit.net/jwk6rso.js') ->js_block('try{Typekit.load();}catch(e){}') ->js("http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js", array('fallback' => array('window.jQuery', '/js/plugins/jquery-1.7.2.min.js'))) ->js("plugins/jquery.clippings.tooltips.js") ->js("plugins/jquery.clippings.attachments.js") ->js("main/general.js", array('processor' => 'jsmin')) ->render(); ?> Asset Merger Remote urls for both CSS and JS IE conditional comments JS Blocks Google CDN for JQuery + Fallback Processor Thursday, November 1, 12
  4. Asset Merger <link type="text/css" href="http://fonts.googleapis.com/css?family=Economica:400,700|Schoolbell" rel="stylesheet" /> <link type="text/css" href="/assets/css/main.css?1347884221"

    rel="stylesheet" /> <!--[if IE]> <link type="text/css" href="/assets/css/css/ie.css?1347636778" rel="stylesheet" /> <![endif]--> <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script> <script type="text/javascript" src="http://use.typekit.net/jwk6rso.js"></script> <script type="text/javascript"> (window.jQuery) || document.write('<script type="text/javascript" src="/js/plugins/jquery-1.7.2.min.js"><\/script>') </script> <script type="text/javascript" src="/assets/js/main.js"></script> Production <link type="text/css" href="http://fonts.googleapis.com/css?family=Economica:400,700|Schoolbell" rel="stylesheet" /> <link type="text/css" href="/assets/css/reset.css?1347884221" rel="stylesheet" /> <link type="text/css" href="/assets/css/elements.css?1347869098" rel="stylesheet" /> <link type="text/css" href="/assets/css/typography.css?1347869098" rel="stylesheet" /> <!--[if IE]> <link type="text/css" href="/assets/css/css/ie.css?1347636778" rel="stylesheet" /> <![endif]--> <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script> <script type="text/javascript" src="http://use.typekit.net/jwk6rso.js"></script> <script type="text/javascript"> (window.jQuery) || document.write('<script type="text/javascript" src="/js/plugins/jquery-1.7.2.min.js"><\/script>') </script> <script type="text/javascript" src="/assets/js/main/window-events.js?1347891915"></script> <script type="text/javascript" src="/assets/js/main/window-events.js?1347869098"></script> <script type="text/javascript" src="/assets/js/main.js?1347891915"></script> Development Thursday, November 1, 12
  5. Timestamped Migrations Development Bob David Joss CREATE TABLE ALTER TABLE

    ADD COLUMN UPDATE TABLE DELETE FROM TABLE ALTER TABLE REMOVE COLUMN ALTER TABLE ADD COLUMN Development Development Staging Production Thursday, November 1, 12
  6. Timestamped Migrations $> ./minion --help Minion is a cli tool

    for performing tasks Usage minion {task} Where {task} is one of the following: * db:generate * db:migrate:down * db:migrate:redo * db:migrate:up * db:migrate * db:recreate * db:structure:copy * db:structure:dump * db:structure:load * db:test:load * db:version Thursday, November 1, 12
  7. Timestamped Migrations $> ./minion db:generate --name=add_created_at_to_images 1347956310_add_created_at_to_images.php Migration File Generated

    <?php defined('SYSPATH') OR die('No direct script access.'); /** * create_table($table_name, $fields, array('id' => TRUE, 'options' => '')) * drop_table($table_name) * rename_table($old_name, $new_name) * add_column($table_name, $column_name, $params) * rename_column($table_name, $column_name, $new_column_name) * change_column($table_name, $column_name, $params) * remove_column($table_name, $column_name) * add_index($table_name, $index_name, $columns, $index_type = 'normal') * remove_index($table_name, $index_name) */ class Add_Created_At_To_Images extends Migration { public function up() { $this->add_column('images', 'created_at', 'datetime'); } public function down() { $this->remove_column('images', 'created_at'); } } Thursday, November 1, 12
  8. Timestamped Migrations $> ./minion db:generate --help Usage ======= minion db:generate

    --name=<string> Params ======= --name: string required paramter - the name of the migration Description =========== Generate a migration file Based on the name of the migration it will be populated with appropraite commands: - add_<column>_and_<column>_to_<table> - remove_<column>_and_<column>_from_<table> - drop_table_<table> - rename_table_<table>_to_<new table> - rename_<column>_to_<new column>_in_<table> - change_<column>_in_<table> You can also chain those together with also: add_<column>_to_<table>_also_drop_table_<table> Additionally based on column names it will try to guess the type, using 'string' by default: - ..._id, ...__count, id or position - integer - ..._at - datetime - ..._on - date - is_... - boolean - description or text - text Thursday, November 1, 12
  9. Timestamped Migrations $> ./minion db:generate --name=drop_table_actions 1347956417_drop_table_actions.php Migration File Generated

    <?php defined('SYSPATH') OR die('No direct script access.'); /** * create_table($table_name, $fields, array('id' => TRUE, 'options' => '')) * drop_table($table_name) * rename_table($old_name, $new_name) * add_column($table_name, $column_name, $params) * rename_column($table_name, $column_name, $new_column_name) * change_column($table_name, $column_name, $params) * remove_column($table_name, $column_name) * add_index($table_name, $index_name, $columns, $index_type = 'normal') * remove_index($table_name, $index_name) */ class Drop_Table_Actions extends Migration { public function up() { $this->drop_table('actions'); } public function down() { $this->create_table('actions', array( 'id' => array("type" => 'int', "limit" => '11', "auto" => TRUE, "primary" => TRUE, "null" => TRUE), 'user_id' => array("type" => 'int', "limit" => '11'), 'type' => array("type" => 'varchar', "limit" => '255'), 'object_model' => array("type" => 'varchar', "limit" => '255', "null" => TRUE), 'object_id' => array("type" => 'int', "limit" => '11'), 'creation_time' => array("type" => 'datetime') ), array()); } } Thursday, November 1, 12
  10. Timestamped Migrations Development Bob David Joss 1323080934_add_file_to_products.php 1323175460_add_slug_to_users.php 1323160933_add_country_id_to_projects.php 1323160932_add_copyright_to_images.p

    hp Development Development Staging Production 1322837510_create_table_briefs.php 1323082183_add_slug_to_spaces.php Thursday, November 1, 12
  11. Jam Form <?php defined('SYSPATH') OR die('No direct script access.'); class

    Controller_Authors extends Controller { public function action_edit() { $author = Jam::factory('author', $this->request->param('id')); if ($this->request->method() === Request::POST) { $data = $this->request->post(); if ($author->set($data)->check()) { $author->save(); $this->request->redirect('authors/show/'.$author->id()); } } $this->response->body(View::factory('authors/form', array('author' => $author))); } } Controller Code Thursday, November 1, 12
  12. Jam Form <?php $form = Jam::form($author) ?> <?php echo Form::open('author/edit/'.$author->id())

    ?> <?php echo $form->row('input', 'name') ?> <?php echo $form->row('input', 'email', array(), array('type' => 'email')) ?> <?php echo $form->row('textarea', 'biography', array(), array('rows' => 5, 'cols' => 40)) ?> <button type="submit"> Save Author </button> <?php echo Form::close(); ?> Normal Form Thursday, November 1, 12
  13. Jam Form <?php $form = Jam::form($author) ?> <?php echo Form::open('author/edit/'.$author->id())

    ?> <?php echo $form->row('input', 'name') ?> <?php echo $form->row('input', 'email', array(), array('type' => 'email')) ?> <?php echo $form->row('textarea', 'biography', array(), array('rows' => 5, 'cols' => 40)) ?> <fieldset> <legend>Account</legend> <?php echo $account_form = $form->fields_for('account') ?> <?php echo $account_form->row('input', 'balance') ?> <?php echo $account_form->row('text', 'comments') ?> </fieldset> <button type="submit"> Save Author </button> <?php echo Form::close(); ?> Nested Forms Thursday, November 1, 12
  14. Jam Associations Polymorphic • belongs to any model • has

    many any model Taxonomies • vocabularies of term trees • multiple terms for any model • represented as normal association Thursday, November 1, 12
  15. Jam Associations • Lazy loading - perform the query at

    the last possible moment • Add conditions to associations • Bi-directional associations • Different types of cascade deletions • Database Builders for each association + extensions • Mass Assignment • Permitted Attributes Thursday, November 1, 12
  16. Jam Goodies • File upload done right • multiple backends

    • image validation, transformations & thumbnails • multiple sources (url, ajax) • Built in Behaviors - Paranoid, Sluggable, Sortable, Nested • Builder knows about associations • Serialized fields (to JSON) Thursday, November 1, 12
  17. Jam Auth • Remember me auth tokens as in ORM-Auth

    • Create custom auth tokens (forgotten password) • Login with external services (facebook) Thursday, November 1, 12
  18. Jam Auth <?php defined('SYSPATH') OR die('No direct script access.'); class

    Controller_Session extends Controller { function action_send_forgotten() { $request = $this->request; $view = View::factory('session/form'); if ($request->method() === Request::POST) { $user = Jam::factory('user', $request->post('email')); if ($user->loaded()) { $token = $user->generate_login_token(); mail($user->email, 'Forgotten Password', 'Click this link to login: '.URL::site(TRUE).'/session/login_token/'.$token- >token); $view->set('message', 'An email with instructions has been sent to '.$user->email); } else { $view->set('message', 'A user with this email was not found'); } } $this->response->body($view); } function action_login_token() { if ($user = $this->auth->login_with_token($this->request->param('id'))) { $this->request->redirect(URL::site()); } } } Thursday, November 1, 12
  19. FuncTest • Test actual html pages easily (Integration/ Functional Testing)

    • Built on top of Kohana Unittest • Friendly DSL - ported from capybara • High Performance - only one instance of Kohana classes, shared among all requests • Snapshot of each failure / error • Selenium integration, browser session management Thursday, November 1, 12
  20. FuncTest <?php defined('SYSPATH') OR die('No direct script access.'); /** *

    @group func */ class myTest extends FuncTest_TestCase { public function test_user_create() { $this ->visit('/signup') ->assertHasCss('h1', array('text' => 'Signup to our great service')) ->find('form.my-form') ->fill_in('Name', 'John') ->fill_in('Username', 'john-user') ->select('Select Year', '2004') ->check('Recieve Newsletter') ->click_button('Create User'); $user = Jam::factory('user', 'john-user'); $this->assertTrue($user->loaded()); } } Native driver Thursday, November 1, 12
  21. FuncTest <?php class Story_ClipTest extends Unittest_Functest_Testcase { public $driver_name =

    'selenium'; public function test_clip_button() { $this ->visit('/shop'); $image = $this->find('.clippable', array('at' => 0)); $image ->hover() ->click_button('Clip') ->assertHasButton('Clipped'); $this->assertHasCss('h3', array('text' => 'Item was clipped successfully!')); } } Selenium driver Thursday, November 1, 12
  22. Jamaker • Inspired by Factory Girl • Works with any

    ORM (sets attributes of objects) • Very flexible template logic - traits, nested templates, sequences Thursday, November 1, 12
  23. Jamaker Jamaker::define('invite', array( 'email' => '[email protected]', Jamaker::trait('company', array( 'invited_to' =>

    'company' )), Jamaker::trait('folder', array( 'invited_to' => 'folder' )), )); $invite = Jamaker::create('invite'); $invite = Jamaker::create('invite', array('company')); $invite = Jamaker::create('invite', array('email' => '[email protected]')); $invite = Jamaker::create('invite', array('company', 'email' => '[email protected]')); $invites = Jamaker::create_list('invite', 10, array('folder')); Thursday, November 1, 12
  24. Jamaker Cleaner • Cleanup all the models that were created

    in the test • Different strategies • Truncate • Transaction Thursday, November 1, 12
  25. Services Manager • css files • javascript files • php

    libraries and SDKs • javascript code blocks Thursday, November 1, 12
  26. Services Manager • Manage multiple external services • Service manages

    its own assets • Fail silently if service is disabled • Configure each service, based on environment • Lazy loading Thursday, November 1, 12