SlideShare una empresa de Scribd logo
1 de 23
Sinatra: a Micro-framework for Web Applicationshttp://www.sinatrarb.com/ Kevin Reiss Office of Library Services
What is Sinatra? A web application micro-framework Minimal stack framework A ruby Domain Specific Language (DSL) A ruby “rack” application A ruby “gem” Gems are the ruby equivalent of Perl modules PHP PEAR Managing gems is very easy - Gem install sinatra is all you need
Why Sinatra? It is lightweight Built on the rack “gem” Rack is a generic ruby library for building web applications It is nicely pluggable within other applications Rails3 has featured support for sinatra apps as middleware Good tool for creating REST-like interfaces  Supports many different template syntaxes It has it’s own web server: default thin Convention over Configuration: the Ruby Framework Way
Hello World? # hello_world.rb require 'sinatra'  # a single sinatra block with a return value get '/' do    'Hello world!'  # return the string “Hello World” end To run the app: > ruby hellow_world.rb
Second Hello World App Sinatra configuration Sinatra routes Sinatra helpers Watch your Request values
Sinatra: Helpers, Routes, and Blocks helpers do   def format_title(name) name.capitalize # your return value   end End get '/library/:department' do   @title = "#{format_title(params[:department])} Department".strip haml :department # invoke a template end
Views with Sinatra Standard convention Views always go in the “views” directory Templates marked “layout.ext” are automatically used as wrappers for “content-like templates” like “mycustomdisplay.ext” Static files (stylesheets, images, etc.) are served up out of the “public” directory Support a wide variety of template options to generate XHTML, HTML5, XML, etc.  Can easily define custom formats Integration with RACK makes it easy to deal with the parts of an HTTP Request
HAML Templates HAML – HTML Templates for the Lazy Also bundled with a CSS Template: SASS %html{:"xml:lang"=>"en"}   %head     %title My Library Web: #{@title}     %link{:type=>"text/css",:rel=>"stylesheet",:media=>"screen",:href=>"/stylesheet.css"}   %body     #pageContent       #header         %ul.nav           %li             %a{:href=>"/"} Home       #body         =yield       #footer         %p Office of Library Services
Where is the Registry? Set configuration options and constants easily Sinatra’s integration with rack makes it easy to access and manipulate the contents of the http.request associated
What about Testing? Unit tests are built into rack set :environment, :test class LibraryTest < Test::Unit::TestCase   def test_it_says_hello_world     browser = Rack::Test::Session.new(Rack::MockSession.new(Sinatra::Application)) browser.get '/'     assert browser.last_response.ok? assert_equal '<h1>Hello World!</h1>', browser.last_response.body   end   def test_it_says_hello_to_a_department     browser = Rack::Test::Session.new(Rack::MockSession.new(Sinatra::Application)) browser.get '/library/ill'     assert browser.last_response.body.include?('ill')   end end
Deployment Options Launch Locally with ruby thin web server This is built into the application Publish directly to heroku Launch via apache proxy_balancer module passenger module ngnix
Heroku Features Read-only filesystem Installed as a ruby gem Integrated with git and ssh Free for low-volume applications Add-ons to expand functionality Memcache Databases,DNS,  heroku logs Good documentation Not just sinatra, rails and any other rack-based application Similar to the “Google App Engine”
Heroku Deployment	 Ruby Platform as a Service – http://heroku.com/ Rails, Sinatra, generic Rack Applications Integrated directly with git version to control To Deploy: create “config.ru” file – defines your rack application create .gems file – defines libraries your app requires git init git add . git commit –m “Initial Commit” heroku create git push heroku master
Thin Server Configuration ---  chdir: /home/kreiss/ruby/lookup/ rackup: /home/kreiss/ruby/lookup/config.ru environment: production address: 127.0.0.1 port: 5000 timeout: 30 log: /home/kreiss/ruby/lookup/log/thin.log pid: /home/kreiss/ruby/lookup/tmp/pids/thin.pid max_conns: 1024 max_persistent_conns: 512 require: [] wait: 30 servers: 3 daemonize: true
An Actual Application Standard number checker Wrapper for our web services provided by our ILS Embed this as a web service in other application/scripts
REST-Like Interface Output multiple formats JSON Custom XML with builder gem XML parsing handled by the nokogiri ruby gem
More Complicated Sample Route get '/:campus/isbn/:isbn' do lookup_base = is_valid_sublibrary(params[:campus])   @number = is_valid_isbn(params[:isbn])   @type = "ISBN"   @title = “#{@type}: #{@number} for campus #{lookup_base}"   @items = standard_lookup(@number, "bath.isbn", lookup_base)   if params[:format] == "xml"     builder :bib elsifparams[:format] == "json"     @items.to_json   else haml :standard   end end
Heroku Deployment 486  curl http://cunylookup.heroku.com/laguardia/barcode/33324001754295 487  curl http://cunylookup.heroku.com/city/isbn/0800630807 488  curl http://cunylookup.heroku.com/city/isbn/0800630807?format=xml 489  curl http://cunylookup.heroku.com/city/isbn/0800630807?format=json 490  curl http://cunylookup.heroku.com/cun01/isbn/0800630807 491  curl http://cunylookup.heroku.com/cun01/isbn/0800630807?format=json 492  curl http://cunylookup.heroku.com/cun01/isbn/0800630807?format=xml 493  curl http://cunylookup.heroku.com/cun01/isbn/0800630807?format=xml 494  curl http://cunylookup.heroku.com/cun01/issn/1092-7735?format=xml 495  curl http://cunylookup.heroku.com/city/issn/1092-7735?format=xml 496  curl http://cunylookup.heroku.com/laguardia/issn/1092-7735?format=xml 497  curl http://cunylookup.heroku.com/laguardia/lccn/96042502?format=xml 498  curl http://cunylookup.heroku.com/cun01/lccn/96042502?format=xml
Gotchas Ruby 1.8 v. Ruby 1.9 Heroku supports both Gems need to be called differently in ruby 1.8 Name your gems sensibly – annoying rubyism Dalli: name for memcache gem Nokogiri: name for xml processing gem Sinatra vs. Sinatra Base If you plan to use as middleware in another ruby app you need to define your application with sinatra base
Other frameworks in Libraries Rails (Blacklight) PHP Zend (Omeka) Django (Solr front-end) Xerxes (Metasearch)
Drupal Platform	 Services Views datasource Drupal Workflow building capabilities Workflow module New workbench toolkit D7 Rest Server
Code4lib Report Looks of repository middleware
Code4libNYC	 Suggestion to host day long event

Más contenido relacionado

La actualidad más candente

The Evolution of Airbnb's Frontend
The Evolution of Airbnb's FrontendThe Evolution of Airbnb's Frontend
The Evolution of Airbnb's FrontendSpike Brehm
 
How to connect AngularJS to servers
How to connect AngularJS to serversHow to connect AngularJS to servers
How to connect AngularJS to serversCarlos Morales
 
[JCConf 2020] 用 Kotlin 跨入 Serverless 世代
[JCConf 2020] 用 Kotlin 跨入 Serverless 世代[JCConf 2020] 用 Kotlin 跨入 Serverless 世代
[JCConf 2020] 用 Kotlin 跨入 Serverless 世代Shengyou Fan
 
Deploy Rails Application by Capistrano
Deploy Rails Application by CapistranoDeploy Rails Application by Capistrano
Deploy Rails Application by CapistranoTasawr Interactive
 
Effective Web Application Development with Apache Sling
Effective Web Application Development with Apache SlingEffective Web Application Development with Apache Sling
Effective Web Application Development with Apache SlingRobert Munteanu
 
REST in AngularJS
REST in AngularJSREST in AngularJS
REST in AngularJSa_sharif
 
Ruby on Rails Security
Ruby on Rails SecurityRuby on Rails Security
Ruby on Rails Securityamiable_indian
 
RESTful web apps with Apache Sling - 2013 version
RESTful web apps with Apache Sling - 2013 versionRESTful web apps with Apache Sling - 2013 version
RESTful web apps with Apache Sling - 2013 versionBertrand Delacretaz
 
Real World Fun with ActiveResource
Real World Fun with ActiveResourceReal World Fun with ActiveResource
Real World Fun with ActiveResourceRob C
 
Apache Jackrabbit Oak - Scale your content repository to the cloud
Apache Jackrabbit Oak - Scale your content repository to the cloudApache Jackrabbit Oak - Scale your content repository to the cloud
Apache Jackrabbit Oak - Scale your content repository to the cloudRobert Munteanu
 
Rails 3.1 Awesomeness - what's new
Rails 3.1 Awesomeness - what's newRails 3.1 Awesomeness - what's new
Rails 3.1 Awesomeness - what's newDynamic Clarity
 
More to RoC weibo
More to RoC weiboMore to RoC weibo
More to RoC weiboshaokun
 
Ruby w/o Rails (Олександр Сімонов)
Ruby w/o Rails (Олександр Сімонов)Ruby w/o Rails (Олександр Сімонов)
Ruby w/o Rails (Олександр Сімонов)Fwdays
 
RoR 101: Session 3
RoR 101: Session 3RoR 101: Session 3
RoR 101: Session 3Rory Gianni
 
RoR 101: Session 2
RoR 101: Session 2RoR 101: Session 2
RoR 101: Session 2Rory Gianni
 

La actualidad más candente (20)

The Evolution of Airbnb's Frontend
The Evolution of Airbnb's FrontendThe Evolution of Airbnb's Frontend
The Evolution of Airbnb's Frontend
 
How to connect AngularJS to servers
How to connect AngularJS to serversHow to connect AngularJS to servers
How to connect AngularJS to servers
 
Rails cantrips
Rails cantripsRails cantrips
Rails cantrips
 
[JCConf 2020] 用 Kotlin 跨入 Serverless 世代
[JCConf 2020] 用 Kotlin 跨入 Serverless 世代[JCConf 2020] 用 Kotlin 跨入 Serverless 世代
[JCConf 2020] 用 Kotlin 跨入 Serverless 世代
 
Deploy Rails Application by Capistrano
Deploy Rails Application by CapistranoDeploy Rails Application by Capistrano
Deploy Rails Application by Capistrano
 
Effective Web Application Development with Apache Sling
Effective Web Application Development with Apache SlingEffective Web Application Development with Apache Sling
Effective Web Application Development with Apache Sling
 
REST in AngularJS
REST in AngularJSREST in AngularJS
REST in AngularJS
 
Sails.js Intro
Sails.js IntroSails.js Intro
Sails.js Intro
 
Ruby on Rails Security
Ruby on Rails SecurityRuby on Rails Security
Ruby on Rails Security
 
RESTful web apps with Apache Sling - 2013 version
RESTful web apps with Apache Sling - 2013 versionRESTful web apps with Apache Sling - 2013 version
RESTful web apps with Apache Sling - 2013 version
 
Real World Fun with ActiveResource
Real World Fun with ActiveResourceReal World Fun with ActiveResource
Real World Fun with ActiveResource
 
Apache Jackrabbit Oak - Scale your content repository to the cloud
Apache Jackrabbit Oak - Scale your content repository to the cloudApache Jackrabbit Oak - Scale your content repository to the cloud
Apache Jackrabbit Oak - Scale your content repository to the cloud
 
Rails 3.1 Awesomeness - what's new
Rails 3.1 Awesomeness - what's newRails 3.1 Awesomeness - what's new
Rails 3.1 Awesomeness - what's new
 
Red5 - PHUG Workshops
Red5 - PHUG WorkshopsRed5 - PHUG Workshops
Red5 - PHUG Workshops
 
Rails caching
Rails cachingRails caching
Rails caching
 
More to RoC weibo
More to RoC weiboMore to RoC weibo
More to RoC weibo
 
Ruby w/o Rails (Олександр Сімонов)
Ruby w/o Rails (Олександр Сімонов)Ruby w/o Rails (Олександр Сімонов)
Ruby w/o Rails (Олександр Сімонов)
 
Web sockets in Java
Web sockets in JavaWeb sockets in Java
Web sockets in Java
 
RoR 101: Session 3
RoR 101: Session 3RoR 101: Session 3
RoR 101: Session 3
 
RoR 101: Session 2
RoR 101: Session 2RoR 101: Session 2
RoR 101: Session 2
 

Destacado

Ids search presentation
Ids search presentationIds search presentation
Ids search presentationkevinreiss
 
Doing More with Less: Mash Your Way to Productivity
Doing More with Less: Mash Your Way to ProductivityDoing More with Less: Mash Your Way to Productivity
Doing More with Less: Mash Your Way to Productivitykevinreiss
 
Dspace at CUNY
Dspace at CUNYDspace at CUNY
Dspace at CUNYkevinreiss
 
Are Library Services Ready for the Mobile Web?
Are Library Services Ready for the Mobile Web?Are Library Services Ready for the Mobile Web?
Are Library Services Ready for the Mobile Web?kevinreiss
 
Launching metaware.buzz
Launching metaware.buzzLaunching metaware.buzz
Launching metaware.buzzJenn Riley
 
The future of cataloguing? Future cataloguers!
The future of cataloguing? Future cataloguers!The future of cataloguing? Future cataloguers!
The future of cataloguing? Future cataloguers!Jenn Riley
 

Destacado (7)

Xml Overview
Xml OverviewXml Overview
Xml Overview
 
Ids search presentation
Ids search presentationIds search presentation
Ids search presentation
 
Doing More with Less: Mash Your Way to Productivity
Doing More with Less: Mash Your Way to ProductivityDoing More with Less: Mash Your Way to Productivity
Doing More with Less: Mash Your Way to Productivity
 
Dspace at CUNY
Dspace at CUNYDspace at CUNY
Dspace at CUNY
 
Are Library Services Ready for the Mobile Web?
Are Library Services Ready for the Mobile Web?Are Library Services Ready for the Mobile Web?
Are Library Services Ready for the Mobile Web?
 
Launching metaware.buzz
Launching metaware.buzzLaunching metaware.buzz
Launching metaware.buzz
 
The future of cataloguing? Future cataloguers!
The future of cataloguing? Future cataloguers!The future of cataloguing? Future cataloguers!
The future of cataloguing? Future cataloguers!
 

Similar a Sinatra

Ruby On Rails Siddhesh
Ruby On Rails SiddheshRuby On Rails Siddhesh
Ruby On Rails SiddheshSiddhesh Bhobe
 
StackMate - CloudFormation for CloudStack
StackMate - CloudFormation for CloudStackStackMate - CloudFormation for CloudStack
StackMate - CloudFormation for CloudStackChiradeep Vittal
 
The Future is Now: Leveraging the Cloud with Ruby
The Future is Now: Leveraging the Cloud with RubyThe Future is Now: Leveraging the Cloud with Ruby
The Future is Now: Leveraging the Cloud with RubyRobert Dempsey
 
Building web framework with Rack
Building web framework with RackBuilding web framework with Rack
Building web framework with Racksickill
 
Introduction to Rails - presented by Arman Ortega
Introduction to Rails - presented by Arman OrtegaIntroduction to Rails - presented by Arman Ortega
Introduction to Rails - presented by Arman Ortegaarman o
 
Ruby On Rails Basics
Ruby On Rails BasicsRuby On Rails Basics
Ruby On Rails BasicsAmit Solanki
 
Construindo APIs Usando Rails
Construindo APIs Usando RailsConstruindo APIs Usando Rails
Construindo APIs Usando RailsFernando Kakimoto
 
Intro to node and mongodb 1
Intro to node and mongodb   1Intro to node and mongodb   1
Intro to node and mongodb 1Mohammad Qureshi
 
Using and scaling Rack and Rack-based middleware
Using and scaling Rack and Rack-based middlewareUsing and scaling Rack and Rack-based middleware
Using and scaling Rack and Rack-based middlewareAlona Mekhovova
 
Rails Request & Middlewares
Rails Request & MiddlewaresRails Request & Middlewares
Rails Request & MiddlewaresSantosh Wadghule
 
Introduction to Alfresco Surf Platform
Introduction to Alfresco Surf PlatformIntroduction to Alfresco Surf Platform
Introduction to Alfresco Surf PlatformAlfresco Software
 
Rails Engine | Modular application
Rails Engine | Modular applicationRails Engine | Modular application
Rails Engine | Modular applicationmirrec
 

Similar a Sinatra (20)

Wider than rails
Wider than railsWider than rails
Wider than rails
 
Rack
RackRack
Rack
 
Ruby On Rails Siddhesh
Ruby On Rails SiddheshRuby On Rails Siddhesh
Ruby On Rails Siddhesh
 
Sun Web Server Brief
Sun Web Server BriefSun Web Server Brief
Sun Web Server Brief
 
StackMate - CloudFormation for CloudStack
StackMate - CloudFormation for CloudStackStackMate - CloudFormation for CloudStack
StackMate - CloudFormation for CloudStack
 
Sun Web Server Brief
Sun Web Server BriefSun Web Server Brief
Sun Web Server Brief
 
The Future is Now: Leveraging the Cloud with Ruby
The Future is Now: Leveraging the Cloud with RubyThe Future is Now: Leveraging the Cloud with Ruby
The Future is Now: Leveraging the Cloud with Ruby
 
Supa fast Ruby + Rails
Supa fast Ruby + RailsSupa fast Ruby + Rails
Supa fast Ruby + Rails
 
Building web framework with Rack
Building web framework with RackBuilding web framework with Rack
Building web framework with Rack
 
Introduction to Rails - presented by Arman Ortega
Introduction to Rails - presented by Arman OrtegaIntroduction to Rails - presented by Arman Ortega
Introduction to Rails - presented by Arman Ortega
 
Ruby On Rails Basics
Ruby On Rails BasicsRuby On Rails Basics
Ruby On Rails Basics
 
Construindo APIs Usando Rails
Construindo APIs Usando RailsConstruindo APIs Usando Rails
Construindo APIs Usando Rails
 
App fabric introduction
App fabric introductionApp fabric introduction
App fabric introduction
 
Intro to node and mongodb 1
Intro to node and mongodb   1Intro to node and mongodb   1
Intro to node and mongodb 1
 
Using and scaling Rack and Rack-based middleware
Using and scaling Rack and Rack-based middlewareUsing and scaling Rack and Rack-based middleware
Using and scaling Rack and Rack-based middleware
 
Rack
RackRack
Rack
 
Rails Request & Middlewares
Rails Request & MiddlewaresRails Request & Middlewares
Rails Request & Middlewares
 
Introduction to Alfresco Surf Platform
Introduction to Alfresco Surf PlatformIntroduction to Alfresco Surf Platform
Introduction to Alfresco Surf Platform
 
Rails Engine | Modular application
Rails Engine | Modular applicationRails Engine | Modular application
Rails Engine | Modular application
 
Knolx session
Knolx sessionKnolx session
Knolx session
 

Sinatra

  • 1. Sinatra: a Micro-framework for Web Applicationshttp://www.sinatrarb.com/ Kevin Reiss Office of Library Services
  • 2. What is Sinatra? A web application micro-framework Minimal stack framework A ruby Domain Specific Language (DSL) A ruby “rack” application A ruby “gem” Gems are the ruby equivalent of Perl modules PHP PEAR Managing gems is very easy - Gem install sinatra is all you need
  • 3. Why Sinatra? It is lightweight Built on the rack “gem” Rack is a generic ruby library for building web applications It is nicely pluggable within other applications Rails3 has featured support for sinatra apps as middleware Good tool for creating REST-like interfaces Supports many different template syntaxes It has it’s own web server: default thin Convention over Configuration: the Ruby Framework Way
  • 4. Hello World? # hello_world.rb require 'sinatra' # a single sinatra block with a return value get '/' do 'Hello world!' # return the string “Hello World” end To run the app: > ruby hellow_world.rb
  • 5. Second Hello World App Sinatra configuration Sinatra routes Sinatra helpers Watch your Request values
  • 6. Sinatra: Helpers, Routes, and Blocks helpers do def format_title(name) name.capitalize # your return value end End get '/library/:department' do @title = "#{format_title(params[:department])} Department".strip haml :department # invoke a template end
  • 7. Views with Sinatra Standard convention Views always go in the “views” directory Templates marked “layout.ext” are automatically used as wrappers for “content-like templates” like “mycustomdisplay.ext” Static files (stylesheets, images, etc.) are served up out of the “public” directory Support a wide variety of template options to generate XHTML, HTML5, XML, etc. Can easily define custom formats Integration with RACK makes it easy to deal with the parts of an HTTP Request
  • 8. HAML Templates HAML – HTML Templates for the Lazy Also bundled with a CSS Template: SASS %html{:"xml:lang"=>"en"} %head %title My Library Web: #{@title} %link{:type=>"text/css",:rel=>"stylesheet",:media=>"screen",:href=>"/stylesheet.css"} %body #pageContent #header %ul.nav %li %a{:href=>"/"} Home #body =yield #footer %p Office of Library Services
  • 9. Where is the Registry? Set configuration options and constants easily Sinatra’s integration with rack makes it easy to access and manipulate the contents of the http.request associated
  • 10. What about Testing? Unit tests are built into rack set :environment, :test class LibraryTest < Test::Unit::TestCase def test_it_says_hello_world browser = Rack::Test::Session.new(Rack::MockSession.new(Sinatra::Application)) browser.get '/' assert browser.last_response.ok? assert_equal '<h1>Hello World!</h1>', browser.last_response.body end def test_it_says_hello_to_a_department browser = Rack::Test::Session.new(Rack::MockSession.new(Sinatra::Application)) browser.get '/library/ill' assert browser.last_response.body.include?('ill') end end
  • 11. Deployment Options Launch Locally with ruby thin web server This is built into the application Publish directly to heroku Launch via apache proxy_balancer module passenger module ngnix
  • 12. Heroku Features Read-only filesystem Installed as a ruby gem Integrated with git and ssh Free for low-volume applications Add-ons to expand functionality Memcache Databases,DNS, heroku logs Good documentation Not just sinatra, rails and any other rack-based application Similar to the “Google App Engine”
  • 13. Heroku Deployment Ruby Platform as a Service – http://heroku.com/ Rails, Sinatra, generic Rack Applications Integrated directly with git version to control To Deploy: create “config.ru” file – defines your rack application create .gems file – defines libraries your app requires git init git add . git commit –m “Initial Commit” heroku create git push heroku master
  • 14. Thin Server Configuration --- chdir: /home/kreiss/ruby/lookup/ rackup: /home/kreiss/ruby/lookup/config.ru environment: production address: 127.0.0.1 port: 5000 timeout: 30 log: /home/kreiss/ruby/lookup/log/thin.log pid: /home/kreiss/ruby/lookup/tmp/pids/thin.pid max_conns: 1024 max_persistent_conns: 512 require: [] wait: 30 servers: 3 daemonize: true
  • 15. An Actual Application Standard number checker Wrapper for our web services provided by our ILS Embed this as a web service in other application/scripts
  • 16. REST-Like Interface Output multiple formats JSON Custom XML with builder gem XML parsing handled by the nokogiri ruby gem
  • 17. More Complicated Sample Route get '/:campus/isbn/:isbn' do lookup_base = is_valid_sublibrary(params[:campus]) @number = is_valid_isbn(params[:isbn]) @type = "ISBN" @title = “#{@type}: #{@number} for campus #{lookup_base}" @items = standard_lookup(@number, "bath.isbn", lookup_base) if params[:format] == "xml" builder :bib elsifparams[:format] == "json" @items.to_json else haml :standard end end
  • 18. Heroku Deployment 486 curl http://cunylookup.heroku.com/laguardia/barcode/33324001754295 487 curl http://cunylookup.heroku.com/city/isbn/0800630807 488 curl http://cunylookup.heroku.com/city/isbn/0800630807?format=xml 489 curl http://cunylookup.heroku.com/city/isbn/0800630807?format=json 490 curl http://cunylookup.heroku.com/cun01/isbn/0800630807 491 curl http://cunylookup.heroku.com/cun01/isbn/0800630807?format=json 492 curl http://cunylookup.heroku.com/cun01/isbn/0800630807?format=xml 493 curl http://cunylookup.heroku.com/cun01/isbn/0800630807?format=xml 494 curl http://cunylookup.heroku.com/cun01/issn/1092-7735?format=xml 495 curl http://cunylookup.heroku.com/city/issn/1092-7735?format=xml 496 curl http://cunylookup.heroku.com/laguardia/issn/1092-7735?format=xml 497 curl http://cunylookup.heroku.com/laguardia/lccn/96042502?format=xml 498 curl http://cunylookup.heroku.com/cun01/lccn/96042502?format=xml
  • 19. Gotchas Ruby 1.8 v. Ruby 1.9 Heroku supports both Gems need to be called differently in ruby 1.8 Name your gems sensibly – annoying rubyism Dalli: name for memcache gem Nokogiri: name for xml processing gem Sinatra vs. Sinatra Base If you plan to use as middleware in another ruby app you need to define your application with sinatra base
  • 20. Other frameworks in Libraries Rails (Blacklight) PHP Zend (Omeka) Django (Solr front-end) Xerxes (Metasearch)
  • 21. Drupal Platform Services Views datasource Drupal Workflow building capabilities Workflow module New workbench toolkit D7 Rest Server
  • 22. Code4lib Report Looks of repository middleware
  • 23. Code4libNYC Suggestion to host day long event