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

Trailblazer: One Year After 1.0 Release

Trailblazer: One Year After 1.0 Release

Would like to be up to date what happened last year on Trailblazer ecosystem? This is your chance to get all the fresh news in 45 minutes!

After the v1.0 release on Sep 25th, 2015 a lot of things has changed, if you have evaluated the framework and aren't using on a daily basis, now is the time to reevaluate as the framework (and all the gems that support it) matured.

Still not sure about it? Don't worry, I'm gonna show some patterns we have been using in our +30.000 LOC and 2 yo rails app.

Celso Fernandes

September 23, 2016
Tweet

More Decks by Celso Fernandes

Other Decks in Technology

Transcript

  1. 2015 25th Sept -> Release v1.0 2016 5th Apr ->

    First API change (deprecation, not yet removed)
  2. Rails • Productivity! • Happiness! • Stability! • ActiveRecord •

    Migrations • Query Interface • ActiveSupport (Timezones)
  3. Rails • Productivity! • Happiness! • Stability! • ActiveRecord •

    Migrations • Query Interface • ActiveSupport (Timezones) • ActionCable
  4. Rails • Productivity! • Happiness! • Stability! • ActiveRecord •

    Migrations • Query Interface • ActiveSupport (Timezones) • ActionCable (!Scale)
  5. Rails • Productivity! • Happiness! • Stability! • ActiveRecord •

    Migrations • Query Interface • ActiveSupport (Timezones) • ActionCable • ActionView
  6. Rails • Productivity! • Happiness! • Stability! • ActiveRecord •

    Migrations • Query Interface • ActiveSupport (Timezones) • ActionCable • ActionView
  7. Controller class  SensorsController  <  ApplicationController      def  index  

           present  Sensors::Index          render  html:  concept('sensors/cell',  @model).(:index)      end   end # app/controllers/sensors_controller.rb
  8. Operation class  Sensors::Index  <  Trailblazer::Operation      def  model!(params)  

           Sensor.all.includes(:measurable)              .page(params[:page]).per(params[:per])      end   end # app/concepts/sensors/index.rb
  9. Cell class  Sensors::Cell  <  Cell::Concept      include  Kaminari::Cells  

       #  Property      property  :name      property  :kind      def  index          render      end      #  Colection      def  row          render      end      private          def  blank?              model.empty?          end   end # app/concepts/sensors/cell.rb
  10. View <div  class="row">      <table>        

     <thead>              <tr>                  <th><%=  t(".name")  %></th>                  <th><%=  t(".kind")  %></th>                  <th></th>              </tr>          </thead>          <tbody>              <%  unless  blank?  %>              <%=  concept("sensors/cell",  collection:  model).(:row)  %>              <%  else  %>              <tr  class="warning"><td  colspan="8"  class="text-­‐center"><%=   t(".no_sensors_yet")  %></td></tr>              <%=  model.count  %>              <%  end  %>          </tbody>      </table>   </div>   <%=  paginate  view.sensors  %> # app/concepts/sensors/views/index.erb
  11. View <div    <        <    

           <                <                <                <            </        </        <            <%              <%=  concept(            <%              < t(".no_sensors_yet"            <%=  model.count  %>              <%          </    </ </div <%= # app/concepts/sensors/views/index.erb            <%=  concept("sensors/cell",  collection:  model).(:row)  %>  
  12. View <tr>      <td><%=  name  %></td>      <td><%=

     kind  %></td>      <td>          <%=  link_to  "Edit",  edit_sensor_path(locale:   params[:locale],  id:  id)          <%=  link_to  "Destroy",  sensor_path(locale:   params[:locale],  id:  id),   data:  {  confirm:  'Are  you  sure?'  },   method:  :delete,   remote:  true      </td>   </tr> # app/concepts/sensors/views/row.erb
  13. Controller class  SensorsController  <  ApplicationController      def  new  

           form  Sensors::Create          render  html:  concept('sensors/cell',  @form).(:new)      end      def  create          run  Sensors::Create  do  |op|              return  respond_to  do  |format|                  format.js  {  redirect_to  sensors_url  }                  format.html  {  redirect_to  sensors_url  }              end          end          respond_to  do  |format|              format.js  {  render  html:  concept('sensors/cell',  @form).(:new),  status:  422  }              format.html  {  render  html:  concept('sensors/cell',  @form).(:new),  status:  422  }          end      end   end # app/controllers/sensors_controller.rb
  14. View <div  class="row">      <%=  trailblazer_form_for  model,  url:  @form_path

     do  |f|  %>          <%=  f.text_field  :name  %>          <%=  f.select  :kind,  model.kind_options  %>          <%=  f.submit  %>      <%  end  %>   </div> # app/concepts/sensors/form.erb
  15. Operation class  Sensors::Create  <  Trailblazer::Operation      class  Contract  <

     Reform::Form          property  :name          property  :kind          validates  :name,  presence:  true          def  kind_options              Sensor::KONSTANT.map  {  |value|  [value.humanize,   value]}          end      end   end # app/concepts/sensors/contract/create.erb
  16. Operation require_dependency  'sensors/contract/create'   class  Sensors::Create  <  Trailblazer::Operation    

     include  Model      model  Sensor      contract  Contract      def  process(params)          validate(params[:sensor])  do  |contract|              contract.save          end      end   end # app/concepts/sensors/operation/create.erb
  17. Formular =  form(model.contract,  url)  do  |f|      =  f.input

     :title,  placeholder:  "Title"      =  f.input  :url_slug,  placeholder:  "URL  slug" inputs
  18. Formular =  form(model.contract,  url)  do  |f|      .form-­‐group  

           =  f.checkbox  :is_public,  label:  “Public?”          =  f.checkbox  :roles,  collection:  [["Admin",   1],  ["Owner",  2],  ["Maintainer",  3]],  checked:   model.contract.roles,  label:  "Roles" checkbox
  19. Formular =  form(model.contract,  url)  do  |f|    .form-­‐group    

         =  f.radio  :owner,  label:  "Flori",  value:  1          =  f.radio  :owner,  label:  "Konsti",  value:  2      .row          .col-­‐md-­‐2              =  f.radio  :owner,  collection:  [["Flori",   1],  ["Konsti",  2]],  label:  "Owners"          .col-­‐md-­‐3              =  f.radio  :owner,  collection:  [["Flori",   1],  ["Konsti",  2]],  label:  "Owners,  inline",   inline:  true radio
  20. Formular =  form(model.contract,  url)  do  |f|      =  f.select

     :select_roles,            collection:  [["Admin",  1],  ["Owner",  2],   ["Maintainer",  3]],            selected:  model.contract.select_roles,            label:  "Selectable  Roles"   select
  21. Formular =  form(model.contract,  url)  do  |f|      .form-­‐group  

           =  f.textarea  :content,              placeholder:  "And  your  story...",  rows:  9   textarea
  22. Formular =  form(model.contract,  url)  do  |f|      .form-­‐group  

           =  f.button  type:  :submit,   value:  “Submit!”,   class:  [:btn,  :'btn-­‐lg',  :'btn-­‐default'] submit
  23. class  SessionController  <  AppController      def  sign_in    

         run  Tyrant::SignIn      end   end Tyrant
  24. Improvements • trailblazer-loader • Dry Validations on Reform • Dropped

    AV from Cells • Created http://trailblazer.to/ • Operation++
  25. Improvements • trailblazer-loader • Dry Validations on Reform • Dropped

    AV from Cells • Created http://trailblazer.to/ • Operation++
  26. trailblazer loader app   ├──  concepts   │    

     ├──  comment   │      │      ├──  callback.rb   │      │      ├──  cell.rb   │      │      ├──  contract.rb   │      │      ├──  operation.rb   │      │      ├──  policy.rb   │      │      └──  views   │      │              ├──  grid.haml   │      │              └──  show.haml Compound-Singular
  27. trailblazer loader app   ├──  concepts   │    

     ├──  comment   │      │      ├──  contract.rb   │      │      ├──  operation.rb   │      │      ├──  admin   │      │              ├──  contract.rb   │      │              └──  operation.rb Compound-Singular (Nested Concepts)
  28. trailblazer loader app   ├──  concepts   │    

     ├──  comment   │      │      ├──  contract   │      │      │      ├──  create.rb   │      │      │      └──  update.rb   │      │      ├──  cell   │      │      │      └──  form.rb   │      │      ├──  operation   │      │      │      ├──  create.rb   │      │      │      └──  update.rb   │      │      └──  views   │      │              ├──  grid.haml   │      │              └──  show.haml Explicit-Singular
  29. trailblazer loader app   ├──  concepts   │    

     ├──  comment   │      │      ├──  contract   │      │      │      ├──  create.rb   │      │      │      └──  update.rb   │      │      ├──  operation   │      │      │      ├──  create.rb   │      │      │      └──  update.rb   │      │      ├──  admin   │      │      │      └──  contract   │      │      │              ├──  create.rb   │      │      │              └──  update.rb Explicit-Singular (Nested)
  30. trailblazer loader app   ├──  concepts   │    

     ├──  comment   │      │      ├──  contracts   │      │      │      ├──  create.rb   │      │      │      └──  update.rb   │      │      ├──  cells   │      │      │      └──  form.rb   │      │      ├──  operations   │      │      │      ├──  create.rb   │      │      │      └──  update.rb   │      │      └──  views   │      │              ├──  grid.haml   │      │              └──  show.haml Explicit-Plural
  31. trailblazer loader app   ├──  concepts   │    

     ├──  comment   │      │      ├──  contracts   │      │      │      ├──  create.rb   │      │      │      └──  update.rb   │      │      ├──  operations   │      │      │      ├──  create.rb   │      │      │      └──  update.rb   │      │      ├──  admin   │      │      │      └──  contracts   │      │      │              ├──  create.rb   │      │      │              └──  update.rb Explicit-Plural (Nested)
  32. Improvements • trailblazer-loader • Dry Validations on Reform • Dropped

    AV from Cells • Created http://trailblazer.to/ • Operation++
  33. Improvements • trailblazer-loader • Dry Validations on Reform • Dropped

    AV from Cells • Created http://trailblazer.to/ • Operation++
  34. – Nick “We also got rid of ActionView. Replacing this

    jurassic gem with our own 30 lines rendering code has sped up rendering about 25%.”
  35. Improvements • trailblazer-loader • Dry Validations on Reform • Dropped

    AV from Cells • Created http://trailblazer.to/ • Operation++
  36. Operation++ class  Comment::Create  <  Trailblazer::Operation      callback  :after_save  do

             on_change  :notify!      end      callback  :after_save  do          on_change  :cleanup!      end   end  
  37. Operation++ class  Thing::Policy      def  initialize(user,  thing)    

         @user,  @thing  =  user,  thing      end      def  create?          admin?      end      def  admin?          @user.admin  ==  true      end      #  ..   end  
  38. Operation++ class  Thing::Create  <  Trailblazer::Operation      include  Resolver  

       policy  Thing::Policy,  :create?      model  Thing,  :create      builds  -­‐>  (model,  policy,  params)          return  Admin  if  policy.admin?          return  SignedIn  if  params[:current_user]      end   end  
  39. Operation++ class  Comment::Index  <  Trailblazer::Operation      include  Collection  

       def  model!(params)          Comment.all      end   end
  40. Frameworks Trailblazer with Rails Book | Repository Trailblazer with Sinatra

    Guide | Repository Trailblazer with Hanami - coming soon! Trailblazer with Roda - coming soon! Trailblazer with Grape - coming very soon!
  41. Frameworks Trailblazer with Rails Book | gemgem-trbrb Trailblazer with Sinatra

    Guide | gemgem-sinatra Trailblazer with Hanami - gemgem-hanami Trailblazer with Roda - coming soon! Trailblazer with Grape - coming very soon!
  42. Frameworks # Gems gem 'cells-erb', '~> 0.0' gem 'cells-rails', '~>

    0.0' gem 'kaminari-cells' gem 'reform', '~> 2.2' gem 'reform-rails', '~> 0.1' gem 'trailblazer', '~> 1.1' gem 'trailblazer-cells', '~> 0.0' gem 'trailblazer-rails', '~> 0.2'
  43. Frameworks All Rails-relevant files are now in the trailblazer-rails gem.

    You have to include it should you be in a Rails environment. roar-rails # Dec 29, 2011 reform-rails # Aug 15, 2015 trailblazer-rails # Sep 4, 2015 cells-rails # Feb 17, 2016
  44. ◦ be rake stats +----------------------+-------+-------+---------+---------+-----+-------+ | Name | Lines |

    LOC | Classes | Methods | M/C | LOC/M | +----------------------+-------+-------+---------+---------+-----+-------+ | Controllers | 1711 | 1439 | 102 | 148 | 1 | 7 | | Helpers | 248 | 216 | 1 | 31 | 31 | 4 | | Jobs | 31 | 28 | 1 | 2 | 2 | 12 | | Models | 7050 | 3560 | 125 | 461 | 3 | 5 | | Mailers | 0 | 0 | 0 | 0 | 0 | 0 | | Javascripts | 1232 | 968 | 0 | 157 | 0 | 4 | | Libraries | 2607 | 2600 | 3 | 8 | 2 | 323 | | Controller tests | 3313 | 2890 | 52 | 35 | 0 | 80 | | Helper tests | 267 | 219 | 7 | 13 | 1 | 14 | | Model tests | 7516 | 4294 | 83 | 60 | 0 | 69 | | Mailer tests | 0 | 0 | 0 | 0 | 0 | 0 | | Job tests | 47 | 41 | 1 | 1 | 1 | 39 | | Integration tests | 1143 | 950 | 8 | 4 | 0 | 235 | | Cucumber features | 338 | 248 | 0 | 2 | 0 | 122 | | Concepts | 4645 | 3866 | 245 | 608 | 2 | 4 | | Concepts Tests | 4136 | 3420 | 139 | 21 | 0 | 160 | +----------------------+-------+-------+---------+---------+-----+-------+ | Total | 34284 | 24739 | 767 | 1551 | 2 | 13 | +----------------------+-------+-------+---------+---------+-----+-------+ Code LOC: 12677 Test LOC: 12062 Code to Test Ratio: 1:1.0
  45. ◦ be rake stats +----------------------+-------+-------+---------+---------+-----+-------+ | Name | Lines |

    LOC | Classes | Methods | M/C | LOC/M | +----------------------+-------+-------+---------+---------+-----+-------+ | Controllers | 1711 | 1439 | 102 | 148 | 1 | 7 | | Helpers | 248 | 216 | 1 | 31 | 31 | 4 | | Jobs | 31 | 28 | 1 | 2 | 2 | 12 | | Models | 7050 | 3560 | 125 | 461 | 3 | 5 | | Mailers | 0 | 0 | 0 | 0 | 0 | 0 | | Javascripts | 1232 | 968 | 0 | 157 | 0 | 4 | | Libraries | 2607 | 2600 | 3 | 8 | 2 | 323 | | Controller tests | 3313 | 2890 | 52 | 35 | 0 | 80 | | Helper tests | 267 | 219 | 7 | 13 | 1 | 14 | | Model tests | 7516 | 4294 | 83 | 60 | 0 | 69 | | Mailer tests | 0 | 0 | 0 | 0 | 0 | 0 | | Job tests | 47 | 41 | 1 | 1 | 1 | 39 | | Integration tests | 1143 | 950 | 8 | 4 | 0 | 235 | | Cucumber features | 338 | 248 | 0 | 2 | 0 | 122 | | Concepts | 4645 | 3866 | 245 | 608 | 2 | 4 | | Concepts Tests | 4136 | 3420 | 139 | 21 | 0 | 160 | +----------------------+-------+-------+---------+---------+-----+-------+ | Total | 34284 | 24739 | 767 | 1551 | 2 | 13 | +----------------------+-------+-------+---------+---------+-----+-------+ Code LOC: 12677 Test LOC: 12062 Code to Test Ratio: 1:1.0
  46. ◦ be rake stats +----------------------+-------+-------+---------+---------+-----+-------+ | Name | Lines |

    LOC | Classes | Methods | M/C | LOC/M | +----------------------+-------+-------+---------+---------+-----+-------+ | Controllers | 1711 | 1439 | 102 | 148 | 1 | 7 | | Helpers | 248 | 216 | 1 | 31 | 31 | 4 | | Jobs | 31 | 28 | 1 | 2 | 2 | 12 | | Models | 7050 | 3560 | 125 | 461 | 3 | 5 | | Mailers | 0 | 0 | 0 | 0 | 0 | 0 | | Javascripts | 1232 | 968 | 0 | 157 | 0 | 4 | | Libraries | 2607 | 2600 | 3 | 8 | 2 | 323 | | Controller tests | 3313 | 2890 | 52 | 35 | 0 | 80 | | Helper tests | 267 | 219 | 7 | 13 | 1 | 14 | | Model tests | 7516 | 4294 | 83 | 60 | 0 | 69 | | Mailer tests | 0 | 0 | 0 | 0 | 0 | 0 | | Job tests | 47 | 41 | 1 | 1 | 1 | 39 | | Integration tests | 1143 | 950 | 8 | 4 | 0 | 235 | | Cucumber features | 338 | 248 | 0 | 2 | 0 | 122 | | Concepts | 4645 | 3866 | 245 | 608 | 2 | 4 | | Concepts Tests | 4136 | 3420 | 139 | 21 | 0 | 160 | +----------------------+-------+-------+---------+---------+-----+-------+ | Total | 34284 | 24739 | 767 | 1551 | 2 | 13 | +----------------------+-------+-------+---------+---------+-----+-------+ Code LOC: 12677 Test LOC: 12062 Code to Test Ratio: 1:1.0
  47. ◦ be rake stats +----------------------+-------+-------+---------+---------+-----+-------+ | Name | Lines |

    LOC | Classes | Methods | M/C | LOC/M | +----------------------+-------+-------+---------+---------+-----+-------+ | Controllers | 1711 | 1439 | 102 | 148 | 1 | 7 | | Helpers | 248 | 216 | 1 | 31 | 31 | 4 | | Jobs | 31 | 28 | 1 | 2 | 2 | 12 | | Models | 7050 | 3560 | 125 | 461 | 3 | 5 | | Mailers | 0 | 0 | 0 | 0 | 0 | 0 | | Javascripts | 1232 | 968 | 0 | 157 | 0 | 4 | | Libraries | 2607 | 2600 | 3 | 8 | 2 | 323 | | Controller tests | 3313 | 2890 | 52 | 35 | 0 | 80 | | Helper tests | 267 | 219 | 7 | 13 | 1 | 14 | | Model tests | 7516 | 4294 | 83 | 60 | 0 | 69 | | Mailer tests | 0 | 0 | 0 | 0 | 0 | 0 | | Job tests | 47 | 41 | 1 | 1 | 1 | 39 | | Integration tests | 1143 | 950 | 8 | 4 | 0 | 235 | | Cucumber features | 338 | 248 | 0 | 2 | 0 | 122 | | Concepts | 4645 | 3866 | 245 | 608 | 2 | 4 | | Concepts Tests | 4136 | 3420 | 139 | 21 | 0 | 160 | +----------------------+-------+-------+---------+---------+-----+-------+ | Total | 34284 | 24739 | 767 | 1551 | 2 | 13 | +----------------------+-------+-------+---------+---------+-----+-------+ Code LOC: 12677 Test LOC: 12062 Code to Test Ratio: 1:1.0
  48. ◦ be rake stats +----------------------+-------+-------+---------+---------+-----+-------+ | Name | Lines |

    LOC | Classes | Methods | M/C | LOC/M | +----------------------+-------+-------+---------+---------+-----+-------+ | Controllers | 1711 | 1439 | 102 | 148 | 1 | 7 | | Helpers | 248 | 216 | 1 | 31 | 31 | 4 | | Jobs | 31 | 28 | 1 | 2 | 2 | 12 | | Models | 7050 | 3560 | 125 | 461 | 3 | 5 | | Mailers | 0 | 0 | 0 | 0 | 0 | 0 | | Javascripts | 1232 | 968 | 0 | 157 | 0 | 4 | | Libraries | 2607 | 2600 | 3 | 8 | 2 | 323 | | Controller tests | 3313 | 2890 | 52 | 35 | 0 | 80 | | Helper tests | 267 | 219 | 7 | 13 | 1 | 14 | | Model tests | 7516 | 4294 | 83 | 60 | 0 | 69 | | Mailer tests | 0 | 0 | 0 | 0 | 0 | 0 | | Job tests | 47 | 41 | 1 | 1 | 1 | 39 | | Integration tests | 1143 | 950 | 8 | 4 | 0 | 235 | | Cucumber features | 338 | 248 | 0 | 2 | 0 | 122 | | Concepts | 4645 | 3866 | 245 | 608 | 2 | 4 | | Concepts Tests | 4136 | 3420 | 139 | 21 | 0 | 160 | +----------------------+-------+-------+---------+---------+-----+-------+ | Total | 34284 | 24739 | 767 | 1551 | 2 | 13 | +----------------------+-------+-------+---------+---------+-----+-------+ Code LOC: 12677 Test LOC: 12062 Code to Test Ratio: 1:1.0
  49. Gemfile # Gems gem 'cells-erb', '~> 0.0' gem 'cells-rails', '~>

    0.0' gem 'kaminari-cells' gem 'reform', '~> 2.2' gem 'reform-rails', '~> 0.1' gem 'trailblazer', '~> 1.1' gem 'trailblazer-cells', '~> 0.0' gem 'trailblazer-rails', '~> 0.2'
  50. File Structure app/concepts/home.rb (namespace) app/concepts/home/cell.rb app/concepts/home/views/show.erb app/concepts/home/views/locales/{en,pt-BR}.yml app/concepts/home/cell/new_tweets.rb app/concepts/home/cell/new_tweets/views/show.erb app/concepts/home/cell/profile.rb

    app/concepts/home/cell/profile/views/show.erb app/concepts/home/cell/trends.rb app/concepts/home/cell/trends/views/show.erb app/concepts/home/cell/tweets.rb app/concepts/home/cell/tweets/views/show.erb app/concepts/home/cell/who_follow.rb app/concepts/home/cell/who_follow/views/show.erb
  51. config/routes.rb post  "/tweet",  controller:  "home",  action:  "create"   get  "/refresh",

     controller:  "home",  action:  "refresh"   root  to:  "home#show"
  52. HomeController class  HomeController  <  ApplicationController      def  show  

           present  Home::Show          render_cell      end      def  create          run  Home::Create  do  |op|              return  respond_to  do  |format|                  format.js  {  redirect_to  root_path  }                  format.html  {  redirect_to  root_path  }              end          end          respond_to  do  |format|              format.js  {  render_cell("home/tweet/cell",  @form)  }              format.html  {  render_cell("home/tweet/cell",  @form)  }          end      end      def  refresh          present  Home::Refresh          respond_to  do  |format|              format.js  {  render_cell("home/cell",  @model,  action_name:  "show")  }              format.html  {  render_cell("home/cell",  @model,  action_name:  "show")  }          end      end   end
  53. HomeController class    def        present    

         render_cell      end    def        run                              format.js  {  redirect_to  root_path  }                  format.html  {  redirect_to  root_path  }                      end        respond_to              format.js  {  render_cell(            format.html  {  render_cell(        end    end    def        present          respond_to              format.js  {  render_cell(            format.html  {  render_cell(        end    end   end    def  show          present  Home::Show          render_cell      end  
  54. HomeController class    def        present    

         render_cell      end    def        run                              format.js  {  redirect_to  root_path  }                  format.html  {  redirect_to  root_path  }                      end        respond_to              format.js  {  render_cell(            format.html  {  render_cell(        end    end    def        present          respond_to              format.js  {  render_cell(            format.html  {  render_cell(        end    end   end        render_cell  
  55. HomeController class    def        present    

         render_cell      end    def        run                              format.js  {  redirect_to  root_path  }                  format.html  {  redirect_to  root_path  }                      end        respond_to              format.js  {  render_cell(            format.html  {  render_cell(        end    end    def        present          respond_to              format.js  {  render_cell(            format.html  {  render_cell(        end    end   end    def  create          run  Home::Create  do  |op|              return  respond_to  do  |format|                  format.js  {  redirect_to  root_path  }                  format.html  {  redirect_to  root_path  }              end          end          respond_to  do  |format|              format.js  {  render_cell("home/tweet/cell",  @form)  }              format.html  {  render_cell("home/tweet/cell",  @form)  }          end      end  
  56. HomeController class    def        present    

         render_cell      end    def        run                              format.js  {  redirect_to  root_path  }                  format.html  {  redirect_to  root_path  }                      end        respond_to              format.js  {  render_cell(            format.html  {  render_cell(        end    end    def        present          respond_to              format.js  {  render_cell(            format.html  {  render_cell(        end    end   end                format.js  {  redirect_to  root_path  }              format.js  {  render_cell("home/tweet/cell",  @form)  }  
  57. HomeController class    def        present    

         render_cell      end    def        run                              format.js  {  redirect_to  root_path  }                  format.html  {  redirect_to  root_path  }                      end        respond_to              format.js  {  render_cell(            format.html  {  render_cell(        end    end    def        present          respond_to              format.js  {  render_cell(            format.html  {  render_cell(        end    end   end    def  refresh          present  Home::Refresh          respond_to  do  |format|              format.js  {  render_cell("home/cell",  @model,  action_name:  "show")  }              format.html  {  render_cell("home/cell",  @model,  action_name:  "show")  }          end      end  
  58. HomeController class    def        present    

         render_cell      end    def        run                              format.js  {  redirect_to  root_path  }                  format.html  {  redirect_to  root_path  }                      end        respond_to              format.js  {  render_cell(            format.html  {  render_cell(        end    end    def        present          respond_to              format.js  {  render_cell(            format.html  {  render_cell(        end    end   end        present  Home::Refresh              format.js  {  render_cell("home/cell",  @model,  action_name:  "show")  }  
  59. ApplicationController class  ApplicationController  <  ActionController::Base      before_filter  :set_current_user  

       def  render_cell(name  =  nil,  model=nil,  options={},  &block)          name  =  cell_name(name)          model  =  cell_model(model)          action_name  =  cell_action(options)          render  html:  concept(name,  model,  options).(action_name),  layout:  options.fetch(:layout,  current_layout),  status:  options.fetch(:status,  200)      end      private          def  cell_name(name)              self.class.to_s.underscore.gsub(/_controller\z/,  '')  +  "/cell"  if  name.nil?          end          def  cell_model(model)              model  =  @model  if  model.nil?              model  =  @collection  if  model.nil?          end          def  cell_action(options)              action_name  =  options.delete(:action_name)  if  options.has_key?(:action_name)              action_name  =  @_action_name.to_sym  if  action_name.nil?          end          def  current_layout              current_layout_set  =  self.send(:_layout,  [:html])              return  current_layout_set  if  current_layout_set.is_a?(String)              return  current_layout_set.virtual_path  if  current_layout_set.is_a?(ActionView::Template)              (self.send(:_layout,  [:html])).identifier.split("/").last.gsub(/.html.erb/,"")          end          def  set_current_user              params[:current_user]  =  (current_user.nil?  ?  nil  :  current_user)          end   end
  60. class  ApplicationController  <  ActionController::Base    before_filter      def  render_cell

           name  =        model          action_name          render      end      private          def  cell_name            self        end          def  cell_model            model              model          end          def  cell_action            action_name              action_name          end          def  current_layout              current_layout_set              return            return            (self        end          def  set_current_user              params[        end   end    before_filter  :set_current_user          def  set_current_user              params[:current_user]  =  (current_user.nil?  ?  nil  :  current_user)          end   ApplicationController
  61. class  ApplicationController  <  ActionController::Base    before_filter      def  render_cell

           name  =        model          action_name          render      end      private          def  cell_name            self        end          def  cell_model            model              model          end          def  cell_action            action_name              action_name          end          def  current_layout              current_layout_set              return            return            (self        end          def  set_current_user              params[        end   end    def  render_cell(name  =  nil,  model=nil,  options={},  &block)          name  =  cell_name(name)          model  =  cell_model(model)          action_name  =  cell_action(options)          render  html:  concept(name,  model,  options).(action_name),  layout:  options.fetch(:layout,  current_layout),  status:  options.fetch(:status,  200)      end   ApplicationController
  62. class  ApplicationController  <  ActionController::Base    before_filter      def  render_cell

           name  =        model          action_name          render      end      private          def  cell_name            self        end          def  cell_model            model              model          end          def  cell_action            action_name              action_name          end          def  current_layout              current_layout_set              return            return            (self        end          def  set_current_user              params[        end   end        name  =  cell_name(name)          model  =  cell_model(model)          action_name  =  cell_action(options)                                                                                                                                                                                            current_layout                  cell_name(name)                  cell_model(model)                  cell_action(options)                  current_layout   ApplicationController
  63. class  ApplicationController  <  ActionController::Base    before_filter      def  render_cell

           name  =        model          action_name          render      end      private          def  cell_name            self        end          def  cell_model            model              model          end          def  cell_action            action_name              action_name          end          def  current_layout              current_layout_set              return            return            (self        end          def  set_current_user              params[        end   end        render  html:  concept(name,  model,  options).(action_name),  layout:  options.fetch(:layout,  current_layout),  status:  options.fetch(:status,  200)   ApplicationController
  64. Home::Show Operation class  Home::Show  <  Trailblazer::Operation      def  model!(params)

             view_store(:new_tweets,  new_tweets)          view_store(:profile,  profile)          view_store(:trends,  trends)          view_store(:tweets,  tweets)          view_store(:who_follow,  who_follow)      end      def  trends      end      ...   end  
  65. Operation Monkey Patch ( :P ) require  'trailblazer/operation'   class

     Trailblazer::Operation      attr_reader  :view      def  view_store(key,  object)          @view  =  OpenStruct.new  if  @view.nil?          @view.send("#{key}=",  object)      end   end
  66. Operation View class  Trailblazer::Operation::View      attr_reader  :view    

     def  view_store(key,  object)          @view  =  OpenStruct.new  if  @view.nil?          @view.send("#{key}=",  object)      end   end
  67. Inside Home::Show Cell concept("home/cell/new_tweets",  view.new_tweets)   concept("home/cell/profile",  view.profile)   concept("home/cell/trends",

     view.trends)   concept("home/cell/tweets",  view.tweets)   concept("home/cell/who_follow",  view.who_follow)
  68. Cell Monkey Patch! require  'cell/concept'   module  Cell    

     class  Concept  <  Cell::ViewModel          def  self.locale_file!              cell_name  =  self.to_s.underscore.gsub(/\/cell/,  '')              ::Rails.application.config.i18n.load_path  +=                  Dir[::Rails.root.join(                      'app',  'concepts',  cell_name,  'views',  'locales',   ‘*.{rb,yml}'                  )]          end      end   end
  69. Application Cell module  Cell::App      def  self.included(subclass)    

         subclass.include  ApplicationHelper          subclass.include  Cell::Translation          translation_path  =  define_translation_path          subclass.locale_file!      end      def  view          operation.try(:view)      end      private          def  operation              controller.instance_variable_get(:@operation)          end          def  contract              controller.instance_variable_get(:@operation).try(:contract)          end   end