Upgrade to PRO for Only $50/Year—Limited-Time Offer! 🔥
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Virtus
Search
Florian Gilcher
October 10, 2013
Programming
0
140
Virtus
Florian Gilcher
October 10, 2013
Tweet
Share
More Decks by Florian Gilcher
See All by Florian Gilcher
A new contract with users
skade
1
500
Using Rust to interface with my dive computer
skade
0
270
async/.await with async-std
skade
1
790
Training Rust
skade
1
120
Internet of Streams - IoT in Rust
skade
0
100
How DevRel is failing communities
skade
0
93
The power of the where clause
skade
0
650
Three Years of Rust
skade
1
200
Rust as a CLI language
skade
1
220
Other Decks in Programming
See All in Programming
AIエージェントを活かすPM術 AI駆動開発の現場から
gyuta
0
400
Microservices rules: What good looks like
cer
PRO
0
1.3k
30分でDoctrineの仕組みと使い方を完全にマスターする / phpconkagawa 2025 Doctrine
ttskch
3
830
MAP, Jigsaw, Code Golf 振り返り会 by 関東Kaggler会|Jigsaw 15th Solution
hasibirok0
0
230
まだ間に合う!Claude Code元年をふりかえる
nogu66
5
800
リリース時」テストから「デイリー実行」へ!開発マネージャが取り組んだ、レガシー自動テストのモダン化戦略
goataka
0
130
안드로이드 9년차 개발자, 프론트엔드 주니어로 커리어 리셋하기
maryang
1
110
大体よく分かるscala.collection.immutable.HashMap ~ Compressed Hash-Array Mapped Prefix-tree (CHAMP) ~
matsu_chara
2
220
バックエンドエンジニアによる Amebaブログ K8s 基盤への CronJobの導入・運用経験
sunabig
0
150
AIコーディングエージェント(Gemini)
kondai24
0
210
Developing static sites with Ruby
okuramasafumi
0
270
251126 TestState APIってなんだっけ?Step Functionsテストどう変わる?
east_takumi
0
310
Featured
See All Featured
How to Ace a Technical Interview
jacobian
280
24k
jQuery: Nuts, Bolts and Bling
dougneiner
65
8.2k
Become a Pro
speakerdeck
PRO
31
5.7k
Scaling GitHub
holman
464
140k
Optimising Largest Contentful Paint
csswizardry
37
3.5k
Done Done
chrislema
186
16k
I Don’t Have Time: Getting Over the Fear to Launch Your Podcast
jcasabona
34
2.5k
Save Time (by Creating Custom Rails Generators)
garrettdimon
PRO
32
1.8k
Easily Structure & Communicate Ideas using Wireframe
afnizarnur
194
17k
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
31
2.6k
StorybookのUI Testing Handbookを読んだ
zakiyama
31
6.4k
What's in a price? How to price your products and services
michaelherold
246
13k
Transcript
News!!!
Rails Rumble 2013 http://railsrumble.com/ Signup ends Oct. 13th
http://gotocon.com/berlin-2013/
URM
Unsung Rubyist of the Month
http://www.ruby-mine.de/wonado http://www.ruby-mine.de/regexp
Virtus
DataMapper: The Awesome Parts
This is a partial extraction of the DataMapper Property API
with various modifications and im- provements. The goal is to provide a common API for defining attributes on a model...
The README covers (almost) all, so I am not iterating
through the examples.
class User include Virtus.model attribute :name, String attribute :age, Integer
attribute :birthday, Date attribute :registered, Time, :default =>->() { Time.now } end
json = '{"name": "Florian Gilcher", "age": 30, "birthday": "October 4th,
1983"}' parsed = JSON.parse(json) user = User.new(parsed) #=> #<User:0x000001008d8b68 @age=30, @birthday= #<DateTime: 1983-10-04T...>, @name="Florian Gilcher", @registered="....">
module Named include Virtus.module attribute :name, String end class User
include Named end u = User.new u.attributes = {:name => "Florian Gilcher"}
class Location include Virtus.value_object values do attribute :lat, BigDecimal attribute
:lon, BigDecimal end end Location.new(:lat => 1, :lon => 1) == Location.new(:lat => 1, :lon => 1)
All this actually consisted of 3 parts: • coercion •
constructor • mass assignment
class User include Virtus.model( :constructor => false, :mass_assignment => false
) attribute :name, String attribute :age, Integer attribute :birthday, DateTime end
class User include Virtus.model(:coerce => false) attribute :name, String attribute
:age, Integer attribute :birthday, DateTime end u = User.new u.age = "123" u.age #=> "123"
class Named include Virtus.module(:coerce => false) attribute :name, String end
class ShowOff attribute :users, Set[User] attribute :tags, Array[String] attribute :meta,
Hash[Symbol => String], :coerce => false attribute :i_dont_know_what_this_is_good_for, Hash[String => Hash[String => User]] end
What is this good for?
Object graph prototyping
ActiveRecord::serialize
class User < ActiveRecord::Base serialize :preferences end User.new(:name => "fgilcher",
:preferences => { :columns => 3, :scheme => "dark"} })
class User < ActiveRecord::Base serialize :preferences end User.new(:name => "fgilcher",
:preferences => { :columns => 3, :scheme => "dark"} })
class Preferences include Virtus.model attribute :columns, Fixnum, :default => 2
attribute :scheme, String end class User < ActiveRecord::Base serialize :preferences, Preferences end
pref = Preferences.new(:columns => 2, :scheme => "dark") User.create(:name =>
"fgilcher", :preferences => pref) User.first #=> #<User id: 1, name: "fgilcher", preferences: #<Preferences...>>
Or any other store storing complex values (NoSQL)
Form objects
require 'active_model' class Preferences include ActiveModel::Validations validates_presence_of :columns, :scheme end
Consider using Virtus every time you would use OpenStruct or
Hash in anger!
Handling attributes
att = Preferences.attribute_set[:columns] att.name #=> :columns att.coerce("2") #=> 2 att.default_value.value
#=> 2
hash.each do |k,v| setter_name = "#{k}=" object.send(setter_name, v) end
att.get(pref) #=> 2 att.set(pref, 3) #=> 3
Finally, a proper attribute setting API on all objects!
Final words
Virtus comes at a small cost, so it should be
used for domain models only.
This cost does JIT away very well in most cases.
Virtus shines through what it doesn’t do, not through what
it does.