SlideShare a Scribd company logo
@vanstee
operable.io
Ectoan ORM without objects
Ruby and ActiveRecord
Elixir and Ecto
=
ActiveRecord refresher
# Create an unpersisted record
user = User.new(name: "Caroline Holbrook")
# Modify the user
user.name = "Caroline Van Stee"
# Persist a record
user.save
# Retrieve a record
User.find(1)
# Run a complex query
User.where(admin: true).count
Calling methods on
objects, that have
methods which
return objects…
I love Ruby,
but what if we wanted
to build an ORM
without objects.
Data structures Functions
Models
Queries Attribute Mapping
Validations
Executing Queries
User.where(name: "Patrick")
query = { table: :users,
where: { name: "Patrick" } }
results = execute(connection, query)
users = results.map(&:to_model)
with objects
without objects
Wait, you just turned
1 line into 3.
How could that be
any better?
Queries are more flexible1
Connections can be
swapped out
2
Results are more flexible
and are just simple maps
3
Well, that's
how Ecto
works!
query = from u in User,
where: u.name == "Patrick"
results = Repo.all(query)
Integrated
Query
Language
Repo
Model
Changeset
Query
Repos are just
connections to
the database
user = %User{name: "Patrick"}
WriterRepo.insert!(user)
ReaderRepo.all(User)
Multiple Repos
Models
defmodule App.User do
use Ecto.Model
schema "users" do
field :name
end
end
Fields have types
defmodule JSON do
alias Postgres.TypeInfo
@behaviour Postgrex.Extension
def init(_parameters, opts),
do: Keyword.fetch!(opts, :library)
def matching(_library),
do: [type: "json"]
def format(_library),
do: :binary
def encode(%TypeInfo{type: "json"}, map, _state, library),
do: library.encode!(map)
def decode(%TypeInfo{type: "json"}, json, _state, library),
do: library.decode!(json)
end
Changesets
defmodule User do
use Ecto.Model
def changeset(user, params  :empty) do
user
|> cast(params, ~w(name email), ~w(age))
|> unique_constraint(:email)
end
end
Changesets
params = %{email: "patrick@vanstee.me"}
changeset = User.changeset(%User{}, params)
{:error, changeset} = Repo.insert(changeset)
changeset.errors
#=> [email: "has already been taken"]
Queries
from u in User,
join: p in Post, on: u.id == p.user_id,
where: u.name == "Patrick" or p.views > 500,
select: {u.name, p.title}
Everything else
• Migrations
• Mix tasks (like rake)
• Callbacks
• Validations
• PostgreSQL, MySQL, Mongo
⚡
elixir-lang.org
elixir-lang/ecto

More Related Content

Similar to Ecto Introduction by Patrick Vanstee

Concurrency and Thread-Safe Data Processing in Background Tasks
Concurrency and Thread-Safe Data Processing in Background TasksConcurrency and Thread-Safe Data Processing in Background Tasks
Concurrency and Thread-Safe Data Processing in Background Tasks
WO Community
 
Javascript Objects Deep Dive
Javascript Objects Deep DiveJavascript Objects Deep Dive
Javascript Objects Deep Dive
Manish Jangir
 
Ear
EarEar
Functional web with clojure
Functional web with clojureFunctional web with clojure
Functional web with clojure
John Stevenson
 
Cocoa Design Patterns in Swift
Cocoa Design Patterns in SwiftCocoa Design Patterns in Swift
Cocoa Design Patterns in Swift
Michele Titolo
 
Ruby on Rails Developer - Allerin
Ruby on Rails Developer - AllerinRuby on Rails Developer - Allerin
Ruby on Rails Developer - Allerin
Lauree R
 
Functional Programming in Go
Functional Programming in GoFunctional Programming in Go
Functional Programming in Go
Aaron Schlesinger
 
Basics of Functional Programming
Basics of Functional ProgrammingBasics of Functional Programming
Basics of Functional Programming
Sartaj Singh
 
11. session 11 functions and objects
11. session 11   functions and objects11. session 11   functions and objects
11. session 11 functions and objects
Phúc Đỗ
 
COScheduler
COSchedulerCOScheduler
COScheduler
WO Community
 
Elixir: the not-so-hidden path to Erlang
Elixir: the not-so-hidden path to ErlangElixir: the not-so-hidden path to Erlang
Elixir: the not-so-hidden path to Erlang
Laura M. Castro
 
Awesomeness of JavaScript…almost
Awesomeness of JavaScript…almostAwesomeness of JavaScript…almost
Awesomeness of JavaScript…almost
Quinton Sheppard
 
JavsScript OOP
JavsScript OOPJavsScript OOP
JavsScript OOP
LearningTech
 
Phoenix demysitify, with fun
Phoenix demysitify, with funPhoenix demysitify, with fun
Phoenix demysitify, with fun
Tai An Su
 
Sequelize
SequelizeSequelize
Sequelize
Tarek Raihan
 
Javascript foundations: Introducing OO
Javascript foundations: Introducing OOJavascript foundations: Introducing OO
Javascript foundations: Introducing OO
John Hunter
 
Conf orm - explain
Conf orm - explainConf orm - explain
Conf orm - explain
Louise Grandjonc
 
Excel Scripting
Excel Scripting Excel Scripting
Excel Scripting
G C Reddy Technologies
 
Ajaxworld
AjaxworldAjaxworld
Ajaxworld
deannalagason
 
PofEAA and SQLAlchemy
PofEAA and SQLAlchemyPofEAA and SQLAlchemy
PofEAA and SQLAlchemy
Inada Naoki
 

Similar to Ecto Introduction by Patrick Vanstee (20)

Concurrency and Thread-Safe Data Processing in Background Tasks
Concurrency and Thread-Safe Data Processing in Background TasksConcurrency and Thread-Safe Data Processing in Background Tasks
Concurrency and Thread-Safe Data Processing in Background Tasks
 
Javascript Objects Deep Dive
Javascript Objects Deep DiveJavascript Objects Deep Dive
Javascript Objects Deep Dive
 
Ear
EarEar
Ear
 
Functional web with clojure
Functional web with clojureFunctional web with clojure
Functional web with clojure
 
Cocoa Design Patterns in Swift
Cocoa Design Patterns in SwiftCocoa Design Patterns in Swift
Cocoa Design Patterns in Swift
 
Ruby on Rails Developer - Allerin
Ruby on Rails Developer - AllerinRuby on Rails Developer - Allerin
Ruby on Rails Developer - Allerin
 
Functional Programming in Go
Functional Programming in GoFunctional Programming in Go
Functional Programming in Go
 
Basics of Functional Programming
Basics of Functional ProgrammingBasics of Functional Programming
Basics of Functional Programming
 
11. session 11 functions and objects
11. session 11   functions and objects11. session 11   functions and objects
11. session 11 functions and objects
 
COScheduler
COSchedulerCOScheduler
COScheduler
 
Elixir: the not-so-hidden path to Erlang
Elixir: the not-so-hidden path to ErlangElixir: the not-so-hidden path to Erlang
Elixir: the not-so-hidden path to Erlang
 
Awesomeness of JavaScript…almost
Awesomeness of JavaScript…almostAwesomeness of JavaScript…almost
Awesomeness of JavaScript…almost
 
JavsScript OOP
JavsScript OOPJavsScript OOP
JavsScript OOP
 
Phoenix demysitify, with fun
Phoenix demysitify, with funPhoenix demysitify, with fun
Phoenix demysitify, with fun
 
Sequelize
SequelizeSequelize
Sequelize
 
Javascript foundations: Introducing OO
Javascript foundations: Introducing OOJavascript foundations: Introducing OO
Javascript foundations: Introducing OO
 
Conf orm - explain
Conf orm - explainConf orm - explain
Conf orm - explain
 
Excel Scripting
Excel Scripting Excel Scripting
Excel Scripting
 
Ajaxworld
AjaxworldAjaxworld
Ajaxworld
 
PofEAA and SQLAlchemy
PofEAA and SQLAlchemyPofEAA and SQLAlchemy
PofEAA and SQLAlchemy
 

More from jasnow

app/assets/stylesheets - How to not make a mess
app/assets/stylesheets - How to not make a messapp/assets/stylesheets - How to not make a mess
app/assets/stylesheets - How to not make a mess
jasnow
 
ATLRUG Community Announcements for December 2016
ATLRUG Community Announcements for December 2016ATLRUG Community Announcements for December 2016
ATLRUG Community Announcements for December 2016
jasnow
 
Commitment
CommitmentCommitment
Commitment
jasnow
 
ATLRUG Community/Giveback Announcments
ATLRUG Community/Giveback AnnouncmentsATLRUG Community/Giveback Announcments
ATLRUG Community/Giveback Announcments
jasnow
 
ATLRUG Announcements - October 2016
ATLRUG Announcements - October 2016ATLRUG Announcements - October 2016
ATLRUG Announcements - October 2016
jasnow
 
Seamless Migration
Seamless MigrationSeamless Migration
Seamless Migration
jasnow
 
ATLRUG Announcements - Septemer 2016
ATLRUG Announcements - Septemer 2016ATLRUG Announcements - Septemer 2016
ATLRUG Announcements - Septemer 2016
jasnow
 
Hacking Aaway with ionic
Hacking Aaway with ionicHacking Aaway with ionic
Hacking Aaway with ionic
jasnow
 
ATLRUG Announcements/Upgrade News - August 2016
ATLRUG Announcements/Upgrade News - August 2016ATLRUG Announcements/Upgrade News - August 2016
ATLRUG Announcements/Upgrade News - August 2016
jasnow
 
ATLRUG Announcements - July 2016
ATLRUG Announcements - July 2016ATLRUG Announcements - July 2016
ATLRUG Announcements - July 2016
jasnow
 
Ruby on Docker
Ruby on DockerRuby on Docker
Ruby on Docker
jasnow
 
Getting Answers to Your Testing Questions
Getting Answers to Your Testing QuestionsGetting Answers to Your Testing Questions
Getting Answers to Your Testing Questions
jasnow
 
ATLRUG Announcments - May 2016
ATLRUG Announcments - May 2016ATLRUG Announcments - May 2016
ATLRUG Announcments - May 2016
jasnow
 
ATLRUG Announcements and Fun Facts - April 2016
ATLRUG Announcements and Fun Facts - April 2016ATLRUG Announcements and Fun Facts - April 2016
ATLRUG Announcements and Fun Facts - April 2016
jasnow
 
ATLRUG Announcements - March 2016
ATLRUG Announcements - March 2016ATLRUG Announcements - March 2016
ATLRUG Announcements - March 2016
jasnow
 
Our ATLRUG.com Web Site
Our ATLRUG.com Web SiteOur ATLRUG.com Web Site
Our ATLRUG.com Web Site
jasnow
 
WebRTC: Real Time Video/Audio For Your App ...
WebRTC: Real Time Video/Audio For Your App ...WebRTC: Real Time Video/Audio For Your App ...
WebRTC: Real Time Video/Audio For Your App ...
jasnow
 
ATLRUG Announcements for Feb. 2016
ATLRUG Announcements for Feb. 2016ATLRUG Announcements for Feb. 2016
ATLRUG Announcements for Feb. 2016
jasnow
 
ATLRUG December 2015
ATLRUG December 2015ATLRUG December 2015
ATLRUG December 2015
jasnow
 
Convox introduction by Matt Manning
Convox introduction by Matt ManningConvox introduction by Matt Manning
Convox introduction by Matt Manning
jasnow
 

More from jasnow (20)

app/assets/stylesheets - How to not make a mess
app/assets/stylesheets - How to not make a messapp/assets/stylesheets - How to not make a mess
app/assets/stylesheets - How to not make a mess
 
ATLRUG Community Announcements for December 2016
ATLRUG Community Announcements for December 2016ATLRUG Community Announcements for December 2016
ATLRUG Community Announcements for December 2016
 
Commitment
CommitmentCommitment
Commitment
 
ATLRUG Community/Giveback Announcments
ATLRUG Community/Giveback AnnouncmentsATLRUG Community/Giveback Announcments
ATLRUG Community/Giveback Announcments
 
ATLRUG Announcements - October 2016
ATLRUG Announcements - October 2016ATLRUG Announcements - October 2016
ATLRUG Announcements - October 2016
 
Seamless Migration
Seamless MigrationSeamless Migration
Seamless Migration
 
ATLRUG Announcements - Septemer 2016
ATLRUG Announcements - Septemer 2016ATLRUG Announcements - Septemer 2016
ATLRUG Announcements - Septemer 2016
 
Hacking Aaway with ionic
Hacking Aaway with ionicHacking Aaway with ionic
Hacking Aaway with ionic
 
ATLRUG Announcements/Upgrade News - August 2016
ATLRUG Announcements/Upgrade News - August 2016ATLRUG Announcements/Upgrade News - August 2016
ATLRUG Announcements/Upgrade News - August 2016
 
ATLRUG Announcements - July 2016
ATLRUG Announcements - July 2016ATLRUG Announcements - July 2016
ATLRUG Announcements - July 2016
 
Ruby on Docker
Ruby on DockerRuby on Docker
Ruby on Docker
 
Getting Answers to Your Testing Questions
Getting Answers to Your Testing QuestionsGetting Answers to Your Testing Questions
Getting Answers to Your Testing Questions
 
ATLRUG Announcments - May 2016
ATLRUG Announcments - May 2016ATLRUG Announcments - May 2016
ATLRUG Announcments - May 2016
 
ATLRUG Announcements and Fun Facts - April 2016
ATLRUG Announcements and Fun Facts - April 2016ATLRUG Announcements and Fun Facts - April 2016
ATLRUG Announcements and Fun Facts - April 2016
 
ATLRUG Announcements - March 2016
ATLRUG Announcements - March 2016ATLRUG Announcements - March 2016
ATLRUG Announcements - March 2016
 
Our ATLRUG.com Web Site
Our ATLRUG.com Web SiteOur ATLRUG.com Web Site
Our ATLRUG.com Web Site
 
WebRTC: Real Time Video/Audio For Your App ...
WebRTC: Real Time Video/Audio For Your App ...WebRTC: Real Time Video/Audio For Your App ...
WebRTC: Real Time Video/Audio For Your App ...
 
ATLRUG Announcements for Feb. 2016
ATLRUG Announcements for Feb. 2016ATLRUG Announcements for Feb. 2016
ATLRUG Announcements for Feb. 2016
 
ATLRUG December 2015
ATLRUG December 2015ATLRUG December 2015
ATLRUG December 2015
 
Convox introduction by Matt Manning
Convox introduction by Matt ManningConvox introduction by Matt Manning
Convox introduction by Matt Manning
 

Recently uploaded

WWDC 2024 Keynote Review: For CocoaCoders Austin
WWDC 2024 Keynote Review: For CocoaCoders AustinWWDC 2024 Keynote Review: For CocoaCoders Austin
WWDC 2024 Keynote Review: For CocoaCoders Austin
Patrick Weigel
 
Oracle 23c New Features For DBAs and Developers.pptx
Oracle 23c New Features For DBAs and Developers.pptxOracle 23c New Features For DBAs and Developers.pptx
Oracle 23c New Features For DBAs and Developers.pptx
Remote DBA Services
 
Preparing Non - Technical Founders for Engaging a Tech Agency
Preparing Non - Technical Founders for Engaging  a  Tech AgencyPreparing Non - Technical Founders for Engaging  a  Tech Agency
Preparing Non - Technical Founders for Engaging a Tech Agency
ISH Technologies
 
ALGIT - Assembly Line for Green IT - Numbers, Data, Facts
ALGIT - Assembly Line for Green IT - Numbers, Data, FactsALGIT - Assembly Line for Green IT - Numbers, Data, Facts
ALGIT - Assembly Line for Green IT - Numbers, Data, Facts
Green Software Development
 
Lecture 2 - software testing SE 412.pptx
Lecture 2 - software testing SE 412.pptxLecture 2 - software testing SE 412.pptx
Lecture 2 - software testing SE 412.pptx
TaghreedAltamimi
 
Fundamentals of Programming and Language Processors
Fundamentals of Programming and Language ProcessorsFundamentals of Programming and Language Processors
Fundamentals of Programming and Language Processors
Rakesh Kumar R
 
SQL Accounting Software Brochure Malaysia
SQL Accounting Software Brochure MalaysiaSQL Accounting Software Brochure Malaysia
SQL Accounting Software Brochure Malaysia
GohKiangHock
 
UI5con 2024 - Bring Your Own Design System
UI5con 2024 - Bring Your Own Design SystemUI5con 2024 - Bring Your Own Design System
UI5con 2024 - Bring Your Own Design System
Peter Muessig
 
一比一原版(USF毕业证)旧金山大学毕业证如何办理
一比一原版(USF毕业证)旧金山大学毕业证如何办理一比一原版(USF毕业证)旧金山大学毕业证如何办理
一比一原版(USF毕业证)旧金山大学毕业证如何办理
dakas1
 
How Can Hiring A Mobile App Development Company Help Your Business Grow?
How Can Hiring A Mobile App Development Company Help Your Business Grow?How Can Hiring A Mobile App Development Company Help Your Business Grow?
How Can Hiring A Mobile App Development Company Help Your Business Grow?
ToXSL Technologies
 
Mobile App Development Company In Noida | Drona Infotech
Mobile App Development Company In Noida | Drona InfotechMobile App Development Company In Noida | Drona Infotech
Mobile App Development Company In Noida | Drona Infotech
Drona Infotech
 
原版定制美国纽约州立大学奥尔巴尼分校毕业证学位证书原版一模一样
原版定制美国纽约州立大学奥尔巴尼分校毕业证学位证书原版一模一样原版定制美国纽约州立大学奥尔巴尼分校毕业证学位证书原版一模一样
原版定制美国纽约州立大学奥尔巴尼分校毕业证学位证书原版一模一样
mz5nrf0n
 
Measures in SQL (SIGMOD 2024, Santiago, Chile)
Measures in SQL (SIGMOD 2024, Santiago, Chile)Measures in SQL (SIGMOD 2024, Santiago, Chile)
Measures in SQL (SIGMOD 2024, Santiago, Chile)
Julian Hyde
 
Project Management: The Role of Project Dashboards.pdf
Project Management: The Role of Project Dashboards.pdfProject Management: The Role of Project Dashboards.pdf
Project Management: The Role of Project Dashboards.pdf
Karya Keeper
 
YAML crash COURSE how to write yaml file for adding configuring details
YAML crash COURSE how to write yaml file for adding configuring detailsYAML crash COURSE how to write yaml file for adding configuring details
YAML crash COURSE how to write yaml file for adding configuring details
NishanthaBulumulla1
 
Oracle Database 19c New Features for DBAs and Developers.pptx
Oracle Database 19c New Features for DBAs and Developers.pptxOracle Database 19c New Features for DBAs and Developers.pptx
Oracle Database 19c New Features for DBAs and Developers.pptx
Remote DBA Services
 
What next after learning python programming basics
What next after learning python programming basicsWhat next after learning python programming basics
What next after learning python programming basics
Rakesh Kumar R
 
E-Invoicing Implementation: A Step-by-Step Guide for Saudi Arabian Companies
E-Invoicing Implementation: A Step-by-Step Guide for Saudi Arabian CompaniesE-Invoicing Implementation: A Step-by-Step Guide for Saudi Arabian Companies
E-Invoicing Implementation: A Step-by-Step Guide for Saudi Arabian Companies
Quickdice ERP
 
UI5con 2024 - Keynote: Latest News about UI5 and it’s Ecosystem
UI5con 2024 - Keynote: Latest News about UI5 and it’s EcosystemUI5con 2024 - Keynote: Latest News about UI5 and it’s Ecosystem
UI5con 2024 - Keynote: Latest News about UI5 and it’s Ecosystem
Peter Muessig
 
Safelyio Toolbox Talk Softwate & App (How To Digitize Safety Meetings)
Safelyio Toolbox Talk Softwate & App (How To Digitize Safety Meetings)Safelyio Toolbox Talk Softwate & App (How To Digitize Safety Meetings)
Safelyio Toolbox Talk Softwate & App (How To Digitize Safety Meetings)
safelyiotech
 

Recently uploaded (20)

WWDC 2024 Keynote Review: For CocoaCoders Austin
WWDC 2024 Keynote Review: For CocoaCoders AustinWWDC 2024 Keynote Review: For CocoaCoders Austin
WWDC 2024 Keynote Review: For CocoaCoders Austin
 
Oracle 23c New Features For DBAs and Developers.pptx
Oracle 23c New Features For DBAs and Developers.pptxOracle 23c New Features For DBAs and Developers.pptx
Oracle 23c New Features For DBAs and Developers.pptx
 
Preparing Non - Technical Founders for Engaging a Tech Agency
Preparing Non - Technical Founders for Engaging  a  Tech AgencyPreparing Non - Technical Founders for Engaging  a  Tech Agency
Preparing Non - Technical Founders for Engaging a Tech Agency
 
ALGIT - Assembly Line for Green IT - Numbers, Data, Facts
ALGIT - Assembly Line for Green IT - Numbers, Data, FactsALGIT - Assembly Line for Green IT - Numbers, Data, Facts
ALGIT - Assembly Line for Green IT - Numbers, Data, Facts
 
Lecture 2 - software testing SE 412.pptx
Lecture 2 - software testing SE 412.pptxLecture 2 - software testing SE 412.pptx
Lecture 2 - software testing SE 412.pptx
 
Fundamentals of Programming and Language Processors
Fundamentals of Programming and Language ProcessorsFundamentals of Programming and Language Processors
Fundamentals of Programming and Language Processors
 
SQL Accounting Software Brochure Malaysia
SQL Accounting Software Brochure MalaysiaSQL Accounting Software Brochure Malaysia
SQL Accounting Software Brochure Malaysia
 
UI5con 2024 - Bring Your Own Design System
UI5con 2024 - Bring Your Own Design SystemUI5con 2024 - Bring Your Own Design System
UI5con 2024 - Bring Your Own Design System
 
一比一原版(USF毕业证)旧金山大学毕业证如何办理
一比一原版(USF毕业证)旧金山大学毕业证如何办理一比一原版(USF毕业证)旧金山大学毕业证如何办理
一比一原版(USF毕业证)旧金山大学毕业证如何办理
 
How Can Hiring A Mobile App Development Company Help Your Business Grow?
How Can Hiring A Mobile App Development Company Help Your Business Grow?How Can Hiring A Mobile App Development Company Help Your Business Grow?
How Can Hiring A Mobile App Development Company Help Your Business Grow?
 
Mobile App Development Company In Noida | Drona Infotech
Mobile App Development Company In Noida | Drona InfotechMobile App Development Company In Noida | Drona Infotech
Mobile App Development Company In Noida | Drona Infotech
 
原版定制美国纽约州立大学奥尔巴尼分校毕业证学位证书原版一模一样
原版定制美国纽约州立大学奥尔巴尼分校毕业证学位证书原版一模一样原版定制美国纽约州立大学奥尔巴尼分校毕业证学位证书原版一模一样
原版定制美国纽约州立大学奥尔巴尼分校毕业证学位证书原版一模一样
 
Measures in SQL (SIGMOD 2024, Santiago, Chile)
Measures in SQL (SIGMOD 2024, Santiago, Chile)Measures in SQL (SIGMOD 2024, Santiago, Chile)
Measures in SQL (SIGMOD 2024, Santiago, Chile)
 
Project Management: The Role of Project Dashboards.pdf
Project Management: The Role of Project Dashboards.pdfProject Management: The Role of Project Dashboards.pdf
Project Management: The Role of Project Dashboards.pdf
 
YAML crash COURSE how to write yaml file for adding configuring details
YAML crash COURSE how to write yaml file for adding configuring detailsYAML crash COURSE how to write yaml file for adding configuring details
YAML crash COURSE how to write yaml file for adding configuring details
 
Oracle Database 19c New Features for DBAs and Developers.pptx
Oracle Database 19c New Features for DBAs and Developers.pptxOracle Database 19c New Features for DBAs and Developers.pptx
Oracle Database 19c New Features for DBAs and Developers.pptx
 
What next after learning python programming basics
What next after learning python programming basicsWhat next after learning python programming basics
What next after learning python programming basics
 
E-Invoicing Implementation: A Step-by-Step Guide for Saudi Arabian Companies
E-Invoicing Implementation: A Step-by-Step Guide for Saudi Arabian CompaniesE-Invoicing Implementation: A Step-by-Step Guide for Saudi Arabian Companies
E-Invoicing Implementation: A Step-by-Step Guide for Saudi Arabian Companies
 
UI5con 2024 - Keynote: Latest News about UI5 and it’s Ecosystem
UI5con 2024 - Keynote: Latest News about UI5 and it’s EcosystemUI5con 2024 - Keynote: Latest News about UI5 and it’s Ecosystem
UI5con 2024 - Keynote: Latest News about UI5 and it’s Ecosystem
 
Safelyio Toolbox Talk Softwate & App (How To Digitize Safety Meetings)
Safelyio Toolbox Talk Softwate & App (How To Digitize Safety Meetings)Safelyio Toolbox Talk Softwate & App (How To Digitize Safety Meetings)
Safelyio Toolbox Talk Softwate & App (How To Digitize Safety Meetings)
 

Ecto Introduction by Patrick Vanstee