SlideShare a Scribd company logo
1 of 117
Building Web Service
     Clients with
    ActiveModel
          Paul Dix
      http://pauldix.net
          @pauldix
IM Paul Dix




  photo credit: Sebastian Delmont
I am a Ruby love
    machine!
Web Services, duh!
ActiveModel
Web Services Abstract
    Complexity
Scale
Scale with Complexity

PhOtOnQuAnTiQuE (http://www.flickr.com/photos/67968452@N00/1876685709/)
Scale with Team Size
alexkess (http://www.flickr.com/photos/34838158@N00/3370167184/)
Monolithic




  American Backroom (http://www.flickr.com/photos/41922098@N03/4247207167/)
Split into Logical Parts
How ActiveResource
killed my best friend
Brian Hathcock (http://www.flickr.com/photos/22961976@N00/3040920714/)
Understandable Code
Client libraries goal:
    readable and
 maintainable code
Parallel Connections
Make Stubbing Easy for
    Development
define:”Web Services”
External
Services
Internal
Services
ActiveModel is for use
with rails forms helpers
and other things. Things
that are only used inside
user requests.




                     Calls Inside User
                         Requests
focus(:internal_services)
Abstracting Complexity
Work with large code
       base
Scale
Not Traffic
NoSQL is getting there
Code Complexity
Team Size
Examples
Processor
Operating System
MapReduce
Web Services?
Email Service
User Service
Haystack
Indexing
How to separate
 functionality
Partition on Iteration
        Speed
Partition on Logical
      Fucntion
Partition on Read/Write
       Frequencies
Partition on Join
   Frequency
Goals
Denormalize and
   Replicate
Separation of Concerns
Abstraction
ActiveResource and
ActiveRecord killed
       these
Both make connections
   inside the model
class Collect < Base
end

class ShippingAddress < Base
end

class BillingAddress < Base
end

class LineItem < Base
end

class ShippingLine < Base
end

class NoteAttribute < Base
end
lloydi (http://www.flickr.com/photos/58944004@N00/2362260604/)
class Collect < Base
end

class ShippingAddress < Base
end

class BillingAddress < Base
end

class LineItem < Base
end

class ShippingLine < Base
end

class NoteAttribute < Base
end
Makes requests serially
Requests in Parallel
ActiveModel
helpers for adding
prefixes and suffixes to
methods.... boring




              AttributeMethods
Callbacks
class User
  include ActiveModel::Callbacks

 before_create :do_stuff

  def create
    # ...
  end

  def do_stuff
    # ...
  end
end
Dirty Tracking
class Person
  include ActiveModel::Dirty

 define_attribute_methods [:name]

  def name
    @name
  end

  def name=(val)
    name_will_change!
    @name = val
  end

  def save
    @previously_changed = changes
  end
end
# A newly instantiated object is unchanged:
person = Person.find_by_name('Uncle Bob')
person.changed?       # => false
# Change the name:
person.name = 'Bob'
person.changed?        #   =>   true
person.name_changed?   #   =>   true
person.name_was        #   =>   'Uncle Bob'
person.name_change     #   =>   ['Uncle Bob', 'Bob']
person.name = 'Bill'
person.name_change     # => ['Uncle Bob', 'Bill']
# Save the changes:
person.save
person.changed?        # => false
person.name_changed?   # => false
# Assigning the same value leaves the
# attribute unchanged:
person.name = 'Bill'
person.name_changed? # => false
person.name_change     # => nil
# Which attributes have changed?
person.name = 'Bob'
person.changed      # => ['name']
person.changes      # => {'name' => ['Bill', 'Bob']}
# Resetting an attribute returns it to
# its original state:
person.reset_name!    # => 'Bill'
person.changed?       # => false
person.name_changed? # => false
person.name           # => 'Bill'
Errors
class User
  def errors
    @errors ||= ActiveModel::Errors.new(self)
  end

  def validate!
    errors.add(:name, "can not be nil")
  end
end

user.errors[:name]   #=> ["can not be nil"]
Serialization
class User
  include ActiveModel::Serialization

  def attributes
    {
      :id => @id,
      :name => @name,
      :email => @email
    }
  end
end

user.to_json(:only => [:id, :name])
user.to_xml(:except => [:email])
Validations
class User
  include ActiveModel::Validations
  attr_reader :name, :email, :age,
              :terms_of_service, :password,
              :password_confirmation, :role

  validates_acceptance_of :terms_of_service
end

user = User.new
puts user.valid?
class User
  include ActiveModel::Validations
  attr_reader :name, :email, :age,
              :terms_of_service, :password,
              :password_confirmation, :role

  validates_confirmation_of :password
end

user = User.new
puts user.valid?
class User
  include ActiveModel::Validations
  attr_reader :name, :email, :age,
              :terms_of_service, :password,
              :password_confirmation, :role

  validates_presence_of :name
end

user = User.new
puts user.valid?
class User
  include ActiveModel::Validations
  attr_reader :name, :email, :age,
              :terms_of_service, :password,
              :password_confirmation, :role

  validates_exclusion_of :name,
    :in => ["admin"]
end

user = User.new
puts user.valid?
class User
  include ActiveModel::Validations
  attr_reader :name, :email, :age,
              :terms_of_service, :password,
              :password_confirmation, :role

  validates_inclusion_of :role,
    :in => ["user", "admin"]
end

user = User.new
puts user.valid?
class User
  include ActiveModel::Validations
  attr_reader :name, :email, :age,
              :terms_of_service, :password,
              :password_confirmation, :role

  validates_format_of :email,
:with => /A([^@s]+)@((?:[-a-z0-9]+.)+[a-z]{2,})Z/i
end

user = User.new
puts user.valid?
class User
  include ActiveModel::Validations
  attr_reader :name, :email, :age,
              :terms_of_service, :password,
              :password_confirmation, :role

  validates_length_of :password, :minimum => 6
end

user = User.new
puts user.valid?
class User
  include ActiveModel::Validations
  attr_reader :name, :email, :age,
              :terms_of_service, :password,
              :password_confirmation, :role

  validates_numericality_of :age
end

user = User.new
puts user.valid?
validates_uniqueness_of?
ehpien (http://www.flickr.com/photos/91499534@N00/343313257/)
Testing
require   'rubygems'
require   'active_model'
require   'test/unit'
require   'user'

class LintTest < ActiveModel::TestCase
  include ActiveModel::Lint::Tests

  def setup
    @model = User.new
  end
end
class User
  include ActiveModel::Conversion
  extend ActiveModel::Naming

  def valid?() true end

  def errors
    @errors ||= ActiveModel::Errors.new(self)
  end

  def persisted?
    true
  end
end
Parallel Connections
Asynchronous
EventMachine
Curb
Typhoeus




Mushkush (http://www.flickr.com/photos/43002463@N00/2877016310/)
Quick Example
PauldixReadingList::ReadingList.for_user(
  "paul",
  :include => [:entry, :rating_total]) do |list|

  reading_list = list
end

HYDRA.run

# now we can access the reading list
reading_list.entries.each do |entry|
  puts entry.id
  puts entry.title
  puts entry.body
  puts "up: #{entry.rating_total.up_count} |
down: #{entry.rating_total.down_count}nn"
end
def self.for_user(user_id, options = {}, &block)
  includes = options[:include] || []

 request =
   Typhoeus::Request.new(get_by_id_uri(user_id))
 request.on_complete do |response|
   list = new(response.body, options)

   list.request_entries if includes.include?(:entry)
   list.request_rating_totals if
     includes.include?(:rating_total)

    block.call(list)
  end

  PauldixReadingList::Config.hydra.queue(request)
end
def self.get_ids(ids, &block)
  request = Typhoeus::Request.new(get_ids_uri(ids))

 request.on_complete do |response|
   json = Yajl::Parser.parse(response.body)

   entries = ids.map do |id|
     new(json[id].merge("id" => id))
   end

    block.call(entries)
  end

  PauldixEntries::Config.hydra.queue(request)
end
def self.get_ids(ids, &block)
  request = Typhoeus::Request.new(get_ids_uri(ids))

 request.on_complete do |response|
   json = Yajl::Parser.parse(response.body)

   ratings = ids.map do |id|
     new(json[id])
   end

    block.call(ratings)
  end

  PauldixRatings::Config.hydra.queue(request)
end
Gunnsi (http://www.flickr.com/photos/38735097@N00/440198755/)
Threaded
require 'net/http'
include Java
import 'java.util.concurrent.Executors'

class Request
  include java.util.concurrent.Callable
  def initialize(url)
    @url = url
  end

  def call
    Net::HTTP.get(URI.parse(@url))
  end
end
thread_pool = Executors.new_fixed_thread_pool(50)

futures = []
100.times do |i|
  request =
Request.new("http://localhost:3000/entries/#{i}")
  futures << thread_pool.submit(request)
end

results = futures.map {|f| f.get}
# do something with results

thread_pool.shutdown
Keep Alive
Awesome art credit: Joe West
Stubbing
Review
Readable Client Code
lloydi (http://www.flickr.com/photos/58944004@N00/2362260604/)
Models Build Requests
Parallel Connections
Validate Early
Easy Stubs
Abstract Complexity
Scale
Scale with Complexity

PhOtOnQuAnTiQuE (http://www.flickr.com/photos/67968452@N00/1876685709/)
Scale with Team Size
alexkess (http://www.flickr.com/photos/34838158@N00/3370167184/)
Monolithic




  American Backroom (http://www.flickr.com/photos/41922098@N03/4247207167/)
Thanks!
Questions?

More Related Content

What's hot

Cis407 a ilab 6 web application development devry university
Cis407 a ilab 6 web application development devry universityCis407 a ilab 6 web application development devry university
Cis407 a ilab 6 web application development devry university
lhkslkdh89009
 
jQuery 1.7 Events
jQuery 1.7 EventsjQuery 1.7 Events
jQuery 1.7 Events
dmethvin
 
Filters in AngularJS
Filters in AngularJSFilters in AngularJS
Filters in AngularJS
Brajesh Yadav
 

What's hot (20)

Taming forms with React
Taming forms with ReactTaming forms with React
Taming forms with React
 
Active record(1)
Active record(1)Active record(1)
Active record(1)
 
Cis407 a ilab 6 web application development devry university
Cis407 a ilab 6 web application development devry universityCis407 a ilab 6 web application development devry university
Cis407 a ilab 6 web application development devry university
 
Get AngularJS Started!
Get AngularJS Started!Get AngularJS Started!
Get AngularJS Started!
 
jQuery Behaviours
jQuery BehavioursjQuery Behaviours
jQuery Behaviours
 
Medium TechTalk — iOS
Medium TechTalk — iOSMedium TechTalk — iOS
Medium TechTalk — iOS
 
jQuery 1.7 Events
jQuery 1.7 EventsjQuery 1.7 Events
jQuery 1.7 Events
 
jQuery -Chapter 2 - Selectors and Events
jQuery -Chapter 2 - Selectors and Events jQuery -Chapter 2 - Selectors and Events
jQuery -Chapter 2 - Selectors and Events
 
Android Testing
Android TestingAndroid Testing
Android Testing
 
Angular js form validation with ngmessages shashi-19-7-16
Angular js form validation with ngmessages shashi-19-7-16Angular js form validation with ngmessages shashi-19-7-16
Angular js form validation with ngmessages shashi-19-7-16
 
The Web Components interoperability challenge - Horacio Gonzalez - Codemotion...
The Web Components interoperability challenge - Horacio Gonzalez - Codemotion...The Web Components interoperability challenge - Horacio Gonzalez - Codemotion...
The Web Components interoperability challenge - Horacio Gonzalez - Codemotion...
 
Built in filters
Built in filtersBuilt in filters
Built in filters
 
Angular js form validation shashi-19-7-16
Angular js form validation shashi-19-7-16Angular js form validation shashi-19-7-16
Angular js form validation shashi-19-7-16
 
iOS Contact List Application Tutorial
iOS Contact List Application TutorialiOS Contact List Application Tutorial
iOS Contact List Application Tutorial
 
Acceptance Testing with Webrat
Acceptance Testing with WebratAcceptance Testing with Webrat
Acceptance Testing with Webrat
 
Shell
ShellShell
Shell
 
Filters in AngularJS
Filters in AngularJSFilters in AngularJS
Filters in AngularJS
 
AngularJS Basic Training
AngularJS Basic TrainingAngularJS Basic Training
AngularJS Basic Training
 
Symfony2. Form and Validation
Symfony2. Form and ValidationSymfony2. Form and Validation
Symfony2. Form and Validation
 
Documentation For Tab Setup
Documentation For Tab SetupDocumentation For Tab Setup
Documentation For Tab Setup
 

Similar to Building Web Service Clients with ActiveModel

Django Class-based views (Slovenian)
Django Class-based views (Slovenian)Django Class-based views (Slovenian)
Django Class-based views (Slovenian)
Luka Zakrajšek
 
Action View Form Helpers - 2, Season 2
Action View Form Helpers - 2, Season 2Action View Form Helpers - 2, Season 2
Action View Form Helpers - 2, Season 2
RORLAB
 
Rails 3 overview
Rails 3 overviewRails 3 overview
Rails 3 overview
Yehuda Katz
 
SummaryHW6 Account ManagementIn HW4, you kept track of multiple.pdf
SummaryHW6 Account ManagementIn HW4, you kept track of multiple.pdfSummaryHW6 Account ManagementIn HW4, you kept track of multiple.pdf
SummaryHW6 Account ManagementIn HW4, you kept track of multiple.pdf
ARORACOCKERY2111
 
Desenvolvimento web com Ruby on Rails (parte 3)
Desenvolvimento web com Ruby on Rails (parte 3)Desenvolvimento web com Ruby on Rails (parte 3)
Desenvolvimento web com Ruby on Rails (parte 3)
Joao Lucas Santana
 
How to disassemble one monster app into an ecosystem of 30
How to disassemble one monster app into an ecosystem of 30How to disassemble one monster app into an ecosystem of 30
How to disassemble one monster app into an ecosystem of 30
fiyuer
 
Rails 3: Dashing to the Finish
Rails 3: Dashing to the FinishRails 3: Dashing to the Finish
Rails 3: Dashing to the Finish
Yehuda Katz
 

Similar to Building Web Service Clients with ActiveModel (20)

More to RoC weibo
More to RoC weiboMore to RoC weibo
More to RoC weibo
 
Ruby on rails
Ruby on rails Ruby on rails
Ruby on rails
 
Django Class-based views (Slovenian)
Django Class-based views (Slovenian)Django Class-based views (Slovenian)
Django Class-based views (Slovenian)
 
Action View Form Helpers - 2, Season 2
Action View Form Helpers - 2, Season 2Action View Form Helpers - 2, Season 2
Action View Form Helpers - 2, Season 2
 
SOLID Ruby, SOLID Rails
SOLID Ruby, SOLID RailsSOLID Ruby, SOLID Rails
SOLID Ruby, SOLID Rails
 
Tame Accidental Complexity with Ruby and MongoMapper
Tame Accidental Complexity with Ruby and MongoMapperTame Accidental Complexity with Ruby and MongoMapper
Tame Accidental Complexity with Ruby and MongoMapper
 
Beyond MVC
Beyond MVCBeyond MVC
Beyond MVC
 
Django - sql alchemy - jquery
Django - sql alchemy - jqueryDjango - sql alchemy - jquery
Django - sql alchemy - jquery
 
Ruby/Rails
Ruby/RailsRuby/Rails
Ruby/Rails
 
Rails 3 overview
Rails 3 overviewRails 3 overview
Rails 3 overview
 
SummaryHW6 Account ManagementIn HW4, you kept track of multiple.pdf
SummaryHW6 Account ManagementIn HW4, you kept track of multiple.pdfSummaryHW6 Account ManagementIn HW4, you kept track of multiple.pdf
SummaryHW6 Account ManagementIn HW4, you kept track of multiple.pdf
 
Implementation of EAV pattern for ActiveRecord models
Implementation of EAV pattern for ActiveRecord modelsImplementation of EAV pattern for ActiveRecord models
Implementation of EAV pattern for ActiveRecord models
 
Dexterity in the Wild
Dexterity in the WildDexterity in the Wild
Dexterity in the Wild
 
RubyBarCamp “Полезные gems и plugins”
RubyBarCamp “Полезные gems и plugins”RubyBarCamp “Полезные gems и plugins”
RubyBarCamp “Полезные gems и plugins”
 
Boston Computing Review - Ruby on Rails
Boston Computing Review - Ruby on RailsBoston Computing Review - Ruby on Rails
Boston Computing Review - Ruby on Rails
 
Desenvolvimento web com Ruby on Rails (parte 3)
Desenvolvimento web com Ruby on Rails (parte 3)Desenvolvimento web com Ruby on Rails (parte 3)
Desenvolvimento web com Ruby on Rails (parte 3)
 
How to disassemble one monster app into an ecosystem of 30
How to disassemble one monster app into an ecosystem of 30How to disassemble one monster app into an ecosystem of 30
How to disassemble one monster app into an ecosystem of 30
 
Where's My SQL? Designing Databases with ActiveRecord Migrations
Where's My SQL? Designing Databases with ActiveRecord MigrationsWhere's My SQL? Designing Databases with ActiveRecord Migrations
Where's My SQL? Designing Databases with ActiveRecord Migrations
 
Rails 3: Dashing to the Finish
Rails 3: Dashing to the FinishRails 3: Dashing to the Finish
Rails 3: Dashing to the Finish
 
Python Code Camp for Professionals 4/4
Python Code Camp for Professionals 4/4Python Code Camp for Professionals 4/4
Python Code Camp for Professionals 4/4
 

More from pauldix (6)

An introduction to reinforcement learning (rl)
An introduction to reinforcement learning (rl)An introduction to reinforcement learning (rl)
An introduction to reinforcement learning (rl)
 
Terascale Learning
Terascale LearningTerascale Learning
Terascale Learning
 
Indexing thousands of writes per second with redis
Indexing thousands of writes per second with redisIndexing thousands of writes per second with redis
Indexing thousands of writes per second with redis
 
Building Event-Based Systems for the Real-Time Web
Building Event-Based Systems for the Real-Time WebBuilding Event-Based Systems for the Real-Time Web
Building Event-Based Systems for the Real-Time Web
 
Synchronous Reads Asynchronous Writes RubyConf 2009
Synchronous Reads Asynchronous Writes RubyConf 2009Synchronous Reads Asynchronous Writes RubyConf 2009
Synchronous Reads Asynchronous Writes RubyConf 2009
 
Machine Learning Techniques for the Semantic Web
Machine Learning Techniques for the Semantic WebMachine Learning Techniques for the Semantic Web
Machine Learning Techniques for the Semantic Web
 

Recently uploaded

Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
Joaquim Jorge
 

Recently uploaded (20)

Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdf
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUnderstanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 
Tech Trends Report 2024 Future Today Institute.pdf
Tech Trends Report 2024 Future Today Institute.pdfTech Trends Report 2024 Future Today Institute.pdf
Tech Trends Report 2024 Future Today Institute.pdf
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
 

Building Web Service Clients with ActiveModel

Editor's Notes