Just a quick announcement that I just pushed a new version of Virtus with support for long awaited features: EmbeddedValue, member type coercions for array/set attributes and ValueObject. Current version is 0.2.0, please give it a try and tell me what you think.
Here’s a quick sneak-preview of what you can do with Virtus:
It really surprises me that there are people arguing that writing controller tests doesn’t make sense. Probably the most common argument is that actions are covered in acceptence tests along with checking if views are properly rendered. Right? Right…well that’s just wrong! Are you trying to say that your slow acceptance tests are covering every possible controller action scenario? Are you trying to say that, for instance, every redirect that should take place is tested within an acceptance test? Are you also checking every invalid request in acceptance tests? Are you telling me that your acceptance test suite takes 27 hours and 13 minutes to finish because you fully test your controllers there?! Oh I’m sure that your acceptance test suite runs faster and you probably cover only ‘the happy scenarios’ there…which basically means you miss A LOT of test coverage.
A Simple Fact About a Controller
Here’s a simple fact about a controller - it’s a class with methods! Yes, it’s a class with methods I repeat. It should have tests. Every method (action) should be covered by a test.
Why? Well, for the same reason that you write tests for any other class in your application. We want to make sure that our code behaves like expected. It’s also much easier to keep your controllers thin when you have tests. If it’s trivial to write a test for a controller then it’s probably a well implemented controller. If you’re drowning in mocks then you probably want to refactor your controller.
Here’s an example of a users controller with a sample create action:
As you can see we load a group object in the before filter and then we use that object to create a new user. Pretty dead-simple. If you just write an acceptance spec for this controller I bet you will not cover the case when the group cannot be found. After all people usually write acceptance tests for optimistic scenarios. If they want to cover every case then I’m sure they will miss the deadline ;)
But it’s not just about covering every path! It’s also about the quality of the code. When you look at the example above you probably won’t see any code smells, right? OK so let me write a spec for the create action:
describeUsersControllerdodescribe"#create"dosubject{post:create,:group_id=>group_id,:user=>attributes}let(:group_id){mock('group_id')}let(:group){mock('group')}let(:user){mock('user')}let(:users){mock('users')}beforedoGroup.should_receive(:find).with(group_id).and_return(group)group.should_receive(:users).and_return(users)users.should_receive(:create).with(attributes).and_return(user)endcontext'when attributes are valid'doit'saves the user and redirects to the index page'douser.should_receive(:persisted?).and_return(true)subject.shouldredirect_to(:users)endendcontext'when attributes are not valid'doit'saves the user and redirects to the index page'douser.should_receive(:persisted?).and_return(false)subject.shouldrender_template(:new)endendendend
What happens there? Because we reach deeper into group object, get its users and then use it to build a new user the spec requires more mocks then it should. This is a trivial example but you can probably imagine how a spec would look like if the action was more complicated, had more branching logic and even more structural coupling.
Let’s quickly make a small refactor of the action:
users_controller.rb
123456789101112131415
classUsersController<ApplicationController# stuffdefcreate@user=@group.create_user(params[:user])if@user.persisted?redirectusers_path,:notice=>'User created!'elserender:newendend# more stuffend
Now the spec will be a bit simpler:
users_controller_spec.rb
12345678910111213141516171819202122232425262728
describeUsersControllerdodescribe"#create"dosubject{post:create,:group_id=>group_id,:user=>attributes}let(:group_id){mock('group_id')}let(:group){mock('group')}let(:user){mock('user')}beforedoGroup.should_receive(:find).with(group_id).and_return(group)group.should_receive(:create_user).with(attributes).and_return(users)endcontext'when attributes are valid'doit'saves the user and redirects to the index page'douser.should_receive(:persisted?).and_return(true)subject.shouldredirect_to(:users)endendcontext'when attributes are not valid'doit'saves the user and redirects to the index page'douser.should_receive(:persisted?).and_return(false)subject.shouldrender_template(:new)endendendend
We should also add an example checking the case where a group is not found. This is going to be a rather rare case but this doesn’t change the fact that we should have a test for it:
users_controller_spec.rb
1234567891011121314151617
describeUsersControllerdosubject{post:create,:group_id=>group_id,:user=>attributes}let(:group_id){mock('group_id')}let(:group){mock('group')}describe'#create'docontext'when group is not found'dobeforedoGroup.should_receive(:find).with(group_id).and_raise(ActiveRecord::RecordNotFound)endit{shouldrender_template(:not_found)}endendend
That’s it! Small test, fast test. Code is covered. Controller is thin. Now it’s probably a good idea to write some views specs for users controller too but I’m not going to write about it here, that’s boring ;)
Summing up
Yes, you should write tests for controllers. Whenever somebody asks you if he/she should write them, your answer should be ‘yes!’. There are no good arguments against writing controller tests. It’s code after all, it should be covered by tests. Let the tests drive your design and you will be happy with your controllers, otherwise you might end up with a mess. Without proper tests you won’t be able to truly verify if your controllers are thin and well designed. So please go and write controller tests!
In case you missed it you might want to read Avdi’s great post about “Law of Demeter” where he writes about structural coupling which is mentioned in this post too.
In my recent post I gave you a brief
overview of what I think about the state of Ruby ORMs.
Since I’m involved in the development of DataMapper
project I want to write a little more lines of text to give you a good overview
of the current state of DataMapper project and how the future version 2.0 is
going to look like.
DataMapper 1.x
Let’s get this straight once and for all: DataMapper was never a pure
implementation of the Data Mapper pattern. It has elements of both Data Mapper
and Active Record patterns. It has a mapping layer where you can configure
mappings between model properties and database columns but this doesn’t change
the fact that your models have direct access to the persistence layer and a lot
of persistence-related functionality is mixed into them. This is what makes
DataMapper an ‘ActiveRecord-ish’ library. After a few years of development it’s
become clear that this approach, despite its advantages over ActiveRecord, is
still not good enough.
Probably one of the biggest wins of DataMapper is support for many different
kinds of data stores. Apart from supporting most common RDBMS databases there are
adapters for various key-value stores, NoSQL databases and more. The flip side
is that working with multiple data stores at once is not very stable at the
moment and that you can’t easily use the full power of various databases, like
MongoDB, due to limitations in DataMapper’s API.
The good news is that while working on DataMapper and many of its adapters we’ve
learned our lessons. With all that knowledge and experience the work on
DataMapper 2.0 has been started.
DataMapper 2.0
First of all the next major version of DataMapper will implement the Data Mapper
pattern as described in the PoEAA:
A layer of Mappers that moves data between objects and a database while keeping them independent of each other and the mapper itself.
DataMapper 2 won’t be a big monolithic library, it will consist of multiple
independent pieces that are glued together. Each piece of DM2 is a standalone
library so that you could use it separately from the DM itself.
Let me describe all the related projects.
Veritas - the new relational algebra engine
The core of DM2 is Veritas - the new
relational algebra engine developed by Dan Kubb. Why not ARel? The answer is
simple - ARel is designed to generate SQL whereas DataMapper needs something more
abstract with adapters that can handle different kinds of query dialects. With
that premise Veritas is a full-featured relational algebra implementation and
there’s already an SQL generator
which can build pretty complex queries. More generators will be written soon.
Here’s a quick sneak-preview of how you can build relations with Veritas:
header_one=[[:id,Integer],[:name,String]]header_two=[[:id,Integer],[:user_id,Integer],[:name,String]]tuples_one=[[1,"john"],[2,"jane"]]tuples_two=[[1,1,"john's project"],[2,2,"jane's project"]]# build base relationsrelation_one=Veritas::Relation::Base.new('one',header_one,tuples_two)relation_two=Veritas::Relation::Base.new('two',header_two,tuples_two)# rename conflicting attributesrelation_two=relation_two.rename(:id=>:project_id,:name=>:project_name)# join the two relations on id == user_idnew_relation=relation_one.join(relation_two){|r|r.id.eq(r.user_id)}
What’s great about Veritas is that with its level of abstraction you can use
it for various things - not just to generate queries. For example there’s an
idea of using Veritas to build a new “migrations” library for DM2 that will
easily handle even very complex scenarios.
Virtus - the new model definition and introspection layer
I’ve already introduced Virtus
- it’s an extraction of DataMapper’s Property API. During the last few months we’ve made many
significant improvements and more features will be added soon too. Virtus
already supports defining attributes on your models and can handle many kinds
of coercions. You can also implement your own coersion methods if you need them.
In the near future Virtus will be supporting more complex functionality like
EmbeddedValue and
ValueObject. It’s also
possible that with Virtus you will be able to define relationships between POROs.
The important thing about Virtus is that it’s designed to work with PORO and
it has nothing to do with any persistence concerns. For example there were
people asking me about things like support for dirty attributes tracking - it’s
not going to be included in Virtus.
I should mention that DataMapper 2.0 will be designed to work with POROs that are
not extended by Virtus. Virtus will be optional but since it provides a very
common functionality I suspect most people will want to use it.
Aequitas - the new validation library
Developed by Emmanuel Gomez, Aequitas is
designed to work with any Ruby object and it also has support for Virtus. The
idea is similar to what we have in DataMapper 1.x where validations can be
derived from property declarations. Aquitas is based on the current
dm-validations and the API is
very similar, if not identical. Aequitas has support for custom error messages,
I18n, validation contexts and built-in data types which come with their own set
of validation rules.
aequitas_example.rb
12345678910111213141516
require'virtus'require'aequitas/virtus_integration'classBookincludeVirtusincludeAequitasattribute:title,String,:required=>trueattribute:published_at,Dateendbook=Book.new(:published_at=>'')book.valid?# => falsebook.errors[:title]# => [ "can't be blank" ]"book.errors[:published_at]# => [ "must be a date" ]
Session, Dirty Tracking and Unit of Work
In the Data Mapper world every change made to the models loaded into memory is
tracked by a specialized object which works like a session. When you’re done
with making changes you can either commit them or rollback. The important thing
is that all the complex logic behind tracking what was changed, what was deleted
and what was added is handled by the session object. Your models are dumb in
this regard, they don’t care about dirty tracking, it’s not their responsibility.
It’s one of the major differences between AR and DM.
The session object will be an implementation of the Unit of Work pattern described in PoEAA as:
Maintains a list of objects affected by a business transaction and coordinates the writing out of changes and the resolution of concurrency problems.
More technically speaking a session will hold a DAG
of commands sorted by their dependencies so that when you commit the
session it will know in what order those commands should be executed.
When you think about it you will realize that this pattern is quite common.
That’s why it would probably make sense to come up with a general UoW library
and then create an extended version for DataMapper needs.
Here’s an example of how such a session may look like:
Probably dm-core, the current core
DataMapper library, will be completely rewritten and become the mapper layer
with a thin query API that delegates most of the heavy work down to a veritas
adapter. For your convenience there will be a veritas mapper class that you
can inherit from but this doesn’t mean that you won’t be able to write
custom mapper classes. The idea is really simple here, a mapper class defines
mappings between PORO and the database schema. In most of the cases this means
a direct 1:1 mapping but the huge advantage is that once you need something
custom - you will be able to define it.
This is really the key aspect of using a data mapper library - you define your
domain objects so that they correspond to your real world domain as close as
possible. It makes applying practices like “Fast Rails Tests”
suggested by Corey Haines come in a natural way because you’ll be implementing
the business logic in POROs and have them unit tested in an isolation without
the database access.
You will be able to define a mapper class more or less like this:
example_mapper.rb
123456789101112131415161718192021222324
classUserincludeVirtusattribute:id,IdentityFieldattribute:email,Stringattribute:name,Stringattribute:birthday_year,IntegerendclassUser::Mapper<VeritasMapper# default 1:1 mappingmap:id# custom field namemap:email=>:email_address# map to 2 fieldsmap:name=>[:first_name,:last_name]# map to a result of a function callmap:birthday_year=>:birthday_date,:function=>:dateend
Roadmap? ETA?
There’s a work-in-progress roadmap for DM2 available here.
Regarding ETA it’s really hard to say. We’re taking our time to build all these
libraries, there’s a big focus on code quality and proper test and docs coverage.
Once the roadmap is finalized we will be able to come up with some ETA.
Here’s the full list of related projects on Github:
If you’re eager to learn more you can always join #datamapper IRC channel. I
also understand that this post doesn’t answer many possible questions - feel
free to ask them in the comments.
We have a lot of different Object-Relational Mapper implementations in Ruby (and a ton and a half of Mongo mappers ;)) and it’s probably a good thing. It seems like the only ORM that really matters right now is ActiveRecord although in “the background” we still have DataMapper and Sequel with growing communities. So I’m wondering…what’s the state of these ORMs? This post is my brain-dump on the subject with a potential to start a disccusion about the future of Ruby ORMs. This is a huge subject but I’ll keep it short.
(beloved) ActiveRecord
I’ve been a rails developer for almost 5 years now and I remember my initial excitement about ActiveRecord just like if it happened yesterday. I remember how blown away I was when I saw ‘an empty’ class in app/models with a ton of functionality added dynamically. I remember how happy I was when I started setting up associations for the first time and seeing that I can easily use them and everything just works OOTB. I remember how awesome it was to use built-in validations - a few lines of simple ruby code and my model is “secured” and invalid data won’t be persisted. Just like that! I also remember what a great feeling it was to use migrations for the first time, oh man there was even a generator which creates files for me, wonderful! Yeah, that was really great and I loved it.
Years were passing and my excitement was slowly disappearing and now it’s almost completely gone. Why? What happened? First of all I’m disappointed with AR3. I thought transition to ARel and the general Rail3 refactor will lead to a better codebase and nicer API. What we have now is like a hybrid of AR2 and something that was promised as AR3 which was not finished in 100%. The general lack of consistency in the API worries me. Too bad because making a major bump in the version number was a great opportunity to clean things up for good. Now we have to wait for 4.0. I’m also still facing various “WTF moments” when I see things like that:
Yeah I know that’s just rude to point things like that, right? On the other hand is this what you would expect from a library which has a version number > 3.0? I’d expect some level of maturity but what I see now is still a bit of a mess. It’s definitely getting better so probably, with this level of support that AR has now, version ~5.0 will be truly great and mature. I’m really looking forward to that.
Through all those years ActiveRecord got a lot of great features though. Lazy
queries, attribute serializers, prepared statements just to name a few.
Extracting ActiveModel was also a huge step into the right direction and I’m
very happy with it. It’s all great and the improvement is clearly visible.
On the other hand there are still cases where ActiveRecord fails. For instance it still has
problems with proper handling of object graph. Which isn’t a great surprise
because it’s a tough problem to solve and none of the 3 ORMs has solved it
yet.
With ActiveRecord you get things done, that’s true. Just read the recent post from Xavier Shay “DataMapper Retrospective” where he writes why he likes DataMapper and despite that why he chooses ActiveRecord. He writes “This is my responsible choice at the moment” - I would expect that in many, many cases people pragmaticaly and wisely choose ActiveRecord because the support from community is important and ActiveRecord does have the best support at the moment. When you get yourself into trouble with AR you will likely find help relatively quickly.
After reading Xavier’s post I feel obliged to comment on it. First of all I agree with him and his decisions. DataMapper is trying to solve bigger problems than AR and Sequel. It’s obviously much harder to support any kind of a storage system and it requires a lot of work. It definitely requires more than a couple of years of development and one stable version. DataMapper 1.x series was a great milestone as the API became stable and it’s truly great, just look at this:
DataMapper introduced a lot of fantastic solutions and just recently ActiveRecord started catching up. It doesn’t change the fact that DataMapper 1.x is much harder to use when you have to resort to raw SQL. That’s why I perfectly understand why Xavier prefers AR and Sequel - both ORMs are built specifically to handle RDBMS and they do it in a decent way.
This post would get too big if I started to write more about DataMapper that’s why I’m stopping now. I will write about what’s happening in the DataMapper camp in a separate post where I will give you an overview of our plans for the near future - expect a lot of goodness to say the least.
To quickly sum up - DataMapper is not there either but getting to the point
where we are now was a great experience that’s given us knowledge about how certain problems should
be solved. More about this in a separate post…
I’ve never been a sequel user. I only tried it out a couple of times in the past and it was really nice. The codebase looks much cleaner than in case of ActiveRecord and the feature set is truly impressive. I’m also absolutely amazed that this project has 0 issues on github - HUGE congratulations to Jeremy Evans. He’s doing a fantastic work and I’m really impressed so you should be.
I remember that Sequel introduced various advanced features before AR did - like lazy data sets (aka lazy execution of queries). You probably quickly forgot or you aren’t aware of the fact that AR was the last Ruby ORM that introduced this feature.
I’ve heard from many people that are familiar with Sequel that it’s simply better than ActiveRecord in every aspect. I would not be surprised if this turns out to be true.
I would love to hear more about your experiences with Sequel so please feel free to leave comments!
The State of ORMs?
Right. So where are we now with our favorite ORMs? In my opinion whether it’s ActiveRecord, DataMapper or Sequel - we’re still “not there yet”. I’ve been looking at other languages lately and it’s pretty clear that in Java, Python and PHP most popular ORMs implement the Data Mapper pattern. I’m not saying that this pattern is better. There’s been an open debate about AR vs DM patterns since for ever and there’s no ultimate answer. The fact is, though, that in most of the cases DM is the preffered one. And ORMs in other languages reflect that. Java with its powerful Hibernate, Python with its SQLAlchemy and PHP with its Doctrine. All those projects are mature, have solid codebases and solve hard problems using well known design patterns.
I really like what I see in those ORMs. They all implement Unit Of Work, Identity Map and a lot of other patterns that I didn’t have time to identify. It’s all there. Damn hard problems solved in a clean way with OOP approach and design patterns that were known for many years. When you open up sources of SQLAlchemy or Doctrine you are able to quickly navigate through those projects - classes are well organized and it’s easy to figure things out.
I understand why people like “the less is more” and “convention over configuration” but personally I would love to see more explicitness in Ruby ORMs. Metaprogramming is a dangerous weapon and we shouldn’t forget about this. You probably think “STFU and switch to Java” now. Well, that’s not gonna happen :)
All of this doesn’t change the fact that I believe we can still do better. By looking at other languages we can find a lot of inspirations but many things can be done in a much better way in Ruby.
I would love to get some feedback from you. Are you happy with your ORM of
choice?
“Skinny Controller, Fat Model” is a well known best practice in Ruby
community. Everybody seems to agree with it and follows it. It’s pretty clear
what a skinny controller means. The question is what is a fat model and what
should we do if it gets too fat? Even better, what should we do to avoid too fat
model? I think many people still confuse Domain Model with ActiveRecord. It’s
something more and in this post I will try to explain my new approach to writing
Ruby on Rails applications.
Also, I would like to thank Steve Klabnik who triggered the process of writing
this post by tweeting this:
We need something better. Persistance and logic are two separate responsibilities that every rails app combines.
I’m really glad more and more people are starting to realize this.
Behavior vs Data
When we say “model” we usually think about ActiveRecord. In Ruby on Rails world
this is how we established things. “M” in the MVC means app/models with a bunch
of ActiveRecord model files. This is where the domain logic of our applications
lives. I think we should stop thinking like that.
Martin Fowler defines Domain Model as:
An object model of the domain that incorporates both behavior and data.
We should remember though that the way your Domain Model behaves and the way
your data are persisted are two separate concerns. ActiveRecord objects
represent your data. They give you a low level interface to access your data.
Yes, low level. If you mix domain specific behavior into ActiveRecord models you
will create classes with too many responsibilities. By violating Single
Responsibility Principle
model code becomes difficult to extend, maintain and test. I have seen it many
times, I’m pretty sure you have too.
A few months ago I stumbled upon this quote:
I pull the behavior out of my models into other objects that wrap the models. I prefer to make the AR objects simple wrappers around the db-access stuff in AR.
I have a fairly strict rule that controller actions cannot use AR finders or, in fact, interact with AR at all. AR should be accessed within api methods inside your model, not from the outside.
This describes exactly what I’ve started doing in my recent Rails
projects. The outcome of this approach is more than great. I literally left
ActiveRecord models with only validation rules, scopes and before/after hooks.
The rest is handled by a separate class hierarchy with domain-specific
functionality. Those clases use ActiveRecord models only for the persistence.
Well Defined API
Something that always bothers me in a typical Rails application is the lack of
a well defined model API. Your Domain Model should have an interface to every
action your application should be able to perform. If you have an online shop
where a user can buy a product then with a well-written Rails application you
should be able to fire up the console and be able to easily perform this
operation. If it’s not so simple then you probably want to think about your
model implementation again.
What makes it so hard for us to design and implement a good API for our model?
In my opinion it happens because we start with the data instead of behavior. For
example if you’re building an online shop, how do you start the design and
implementation process? In Rails you probably create migration files to create a
db schema. Right? You initially think about the database columns you need to
create and validation rules you need to define in the models. After you have all
this done you start thinking about the behavior. You add various methods to your
ActiveRecord models so they can create new objects, validate and persist them.
In the end both data and behavior of your system is mixed together in
ActiveRecord models. If you change a column in some table, your system stops
working and it’s relatively difficult to fix. Why? Because the domain behavior
is tightly coupled with the database schema. Because you started with the db
schema and added behavior later.
How about reversing that process and starting with the behavior implemented in
separate classes that are not coupled with the database schema? This way you
will define your API at a higher level. What’s more important you will start
with an API and you will add the persistence logic later.
Behavior & API
The key difference between using ActiveRecord models and domain model classes is
that in case of the latter you clearly specify the behavior. For instance if I
want to find a product in my online shop, how do I do that? Well, with
ActiveRecord Product model I have plenty of choices. I can #find or #find_by_id
or #where(:id => id).first etc. This is problematic because the same operation can
be done in many different ways. Our goal is to create a consistent behavior
that is the same in every place of our application.
Let’s use a simplified example of an online shop and focus on one core behavior -
selling a product. Here’s a code spike how it could be modelled:
classShopclassWarehousedefself.find(id)# returns a productendendclassCustomerattr_reader:userdefself.find(id)# returns a userenddefinitialize(user)@user=userenddefpay(product)# perform the paymentendendclassTransactionattr_reader:customer,:product,:statusdefinitialize(customer,product)@customer=customer@product=productenddefcommit@status=customer.pay(product)ifsuccess?commit!endenddefcommit!# do some stuff to persist data about a successful transactionenddefsuccess?status===trueendendend
So, Warehouse can find a product, Customer can find a user, a customer instance can pay for a
product and Transaction handles selling a product to a customer. With this ridiculously
basic example let’s see how we can write a spec for Transaction:
shop_transaction_spec.rb
1234567891011121314151617181920212223
describeShop::Transaction,'#commit'dosubject{transaction.commit}let(:user){mock('customer')}let(:product){mock('product')}let(:transaction){described_class.new(customer,product)}beforedocustomer.should_receive(:pay).with(product).and_return(payment_status)endcontext'when payment is successful'dolet(:payment_status){true}its(:success){shouldbe(true)}endcontext'when payment is not successful'dolet(:payment_status){false}its(:success){shouldbe(false)}endend
Running the spec gives you this output:
12345678910
Shop::Transaction#commit
when payment is successful
success
should equal true
when payment is not successful
success
should equal false
Finished in 0.00182 seconds
2 examples, 0 failures
This way we started off by defining our API, it’s pretty simple to use:
Note that we designed and implemented the behavior and we could easily write a
spec that checks if that behavior is correct. What about real data and
persistence?
Behavior + Persistence
To continue with the shop example let’s add ActiveRecord models:
classShopclassWarehousedefself.find(id)Product.find_by_id(id)endendclassCustomerattr_reader:userdefself.find(id)User.find_by_id(id)enddefinitialize(user)@user=userenddefpay(product)# perform the paymentendendclassTransactionattr_reader:customer,:product,:order,:statusdefinitialize(customer,product)@customer=customer@product=productenddefcommit@status=customer.pay(product)ifsuccess?commit!endenddefcommit!create_orderiforder.persisted?mark_product_as_soldendenddefsuccess?status===trueendprivatedefcreate_order@order=Order.create(:user=>customer,:product=>product)enddefmark_product_as_sold@product.update_attribute(:sold,true)endendend
This way we hide all the details about our db schema behind objects holding the
domain logic behavior of our shop application. If something changes with the
ActiveRecord models you will only need to change the implementation in one
place because there’s one way of finding a user and a product and placing an
order.
Testing Benefits
With the approach I described it’s really easy to write solid tests. You can
test the behavior in a complete isolation from the db models which results in
fast execution of those tests. Most of the logic of your system can be
unit-tested without touching the database, this means thousands of test examples
running in less than a second. On the other hand when testing ActiveRecord models
you are only concerned about validation rules, hooks and finder methods cause
there’s no more logic there. It makes the AR tests really clean and easy to maintain.
Feedback?
I understand that it may seem like a heavy approach and Ruby on Rails is all
about rapid development and writing less code. However, every project I’ve seen
that evolved in something more than a blog written in 15 minutes, sooner or
later become a huge mess. I don’t think programmers are guilty here. We’ve been
taught to use certain tools and practices and now it’s time to move on, take a
step forward.
Still here? Awesome! I would love to get feedback about how you’re dealing with
complex logic in your Rails applications - so feel free to comment and let’s
start an interesting discussion.
I’m happy to announce the first release of Virtus gem. It is an extraction of
DataMapper Property API
with various tweaks and improvements. If you like how properties work in
DataMapper and would like to use such functionality in your plain ruby objects
then you should give Virtus a try.
It is an early release but I would not expect many API changes before 1.0.0
since the code is based on the stable DataMapper API and I’m quite happy with it.
How to install?
Virtus is just a gem and comes with no dependencies. To install just run this
in your shell:
sample.sh
1
gem install virtus
Why?
As some of you know we’re starting to work on DataMapper 2.0. It will be a true
implementation of the Data Mapper pattern and will use a certain set of
libraries under the hood. Dan Kubb has already
finished his absolutely fantastic relational algebra engine called
Veritas along with
Veritas SQL Generator - these
gems will be the core part of DataMapper 2.0 Query System.
When we were talking with Dan about the future of Property API in DataMapper we
both agreed we need an abstraction for defining your classes that would be
decoupled from any persistence logic. We also agreed that we actually don’t like
“property” word in that context and would prefer “attribute”. There you go -
Virtus was borned :)
How does it work?
Virtus works in an almost identical way as Property in DataMapper. You can
define attributes in your classes and it will create accessors to these attributes
along with typecasting abilities. It comes with a set of builtin attribute types
but you are free to add your own types too.
This creates 4 attribute objects that are associated with your class. Each of
these attributes is responsible for reading and writing values. Values are stored
as standard instance variables.
You can easily inspect what attributes a class has:
Every attribute type has the primitive option set. When you are setting a value
of an attribute, the corresponding attribute object will check if the value has
the correct type. If the type doesn’t match the primitive, then the attribute
will typecast the value.
Available Attribute Types
As I mentioned Virtus comes with various attribute types built-in:
Array
Boolean
Date
DateTime
Decimal
Float
Hash
Integer
Object
String
Time
These classes are organized in a hierarchy where Object inherits from an
abstract Attribute class and all other types inherit from Object.
Options For Defining Attributes
When defining an attribute you can provide additional options. Every attribute
class has a list of options that it accepts.
At the moment you can only use options for access control:
It is possible to set a default value of an option directly on an attribute class:
sample.rb
12345678910
Virtus::Attributes::String.reader(:protected)classUserincludeVirtus# :reader option will be set to :protectedattributes:name,String# you can override the default if you wantattributes:email,String,:reader=>:publicend
Custom Attribute Types and Options
Just like in DataMapper you can implement your own attribute types. Whenever you
need some twisted typecasting logic or you need to use extra options you can
create a custom attribute class.
Here’s an example use-case - let’s say you want a hash and you need to stringify or
symbolize the keys.
sample.rb
12345678910111213141516171819202122232425262728
require'active_support/core_ext/hash/keys'require'virtus'moduleMyAppmoduleAttributesclassHash<Virtus::Attributes::Objectprimitive::Hash# Define extra options that this attribute class acceptsaccept_options:stringify_keys,:symbolize_keys# Set up default values for our extra optionsstringify_keysfalsesymbolize_keystrue# Typecast logic is depends on the optionsdeftypecast(value,object)ifoptions[:stringify_keys]returnvalue.stringify_keysendifoptions[:symbolize_keys]returnvalue.symbolize_keysendendendendend
It’s a bit early to talk about that but I would love to see other Ruby ORM
libraries using a common gem for model attributes. After we integrate DataMapper
with Virtus it should be feasible for others like Mongoid, MongoMapper or even
ActiveRecord (sic!) to use Virtus too. Well, at least that’s my ultimate goal.
RSpec is one of my favorite tools. I have literally fallen in love with this
fantastic BDD library, especially with its second version. While using RSpec I
realized it teaches me how to write tests. Yes, exactly - learning RSpec DSL,
its syntax and structure of spec examples you actually learn the best practices
in writing tests. RSpec, despite many built-in matchers, comes with a DSL for
defining your own, custom matchers. It’s so easy that you’re not gonna believe
this.
Basics
In RSpec matchers are nothing but methods available in the context of an
example. You use them to make sure that a given expectation is met. There are
many matchers that come with RSpec for instance here is how you can use the
respond_to matcher:
sample.rb
123
describeStringdoit{shouldrespond_to(:gsub)}end
It’s so clean and beautiful that I probably don’t have to explain what this
piece of code does, right?
Tip: When you call describe with a class as an argument, RSpec will
automatically create an instance of that class and make it available via subject
method. Subject is also the default context of an example block. That’s why we
don’t have to write “subject.should respond_to(:gsub)”, because by default
“should” or “should_not” is called on the subject.
Alright, for a list of available matchers check out
the official docs. Let’s
focus on writing our own matchers. If you’re wondering why you would need to
do that, let me show a simple example of a User model spec:
sample.rb
1234567891011
describeUserdobefore{subject.email="foobar"}it"should have errors on email"dosubject.errors.shouldhave_key(:email)endit"should have correct error message"dosubject.errors[:email].shouldinclude("Email is invalid")endend
Now, you probably can imagine that almost identical code could be used in many
other cases for many other model classes. Those 6 lines of code can be written
as 1. You just need a custom matcher.
Defining a custom matcher is simple. Let’s start with a basic one that
checks if a given model instance has validation errors:
sample.rb
123456
RSpec::Matchers.define:have_errors_ondo|attribute|matchdo|model|model.valid?# call it here so we don't have to write it in before blocksmodel.errors.key?(attribute)endend
It covers only the first expectation, but it’s a good starting point.
Chaining
The second expectation in the example is to see if the correct validation
error message is set. It’s possible to run matchers in a chain so let’s see
how we can implement chaining in our custom matcher:
It’s really that simple. Now the matcher checks two things and returns true
only if the message exists and if it matches the expected one.
Let’s use it:
sample.rb
12345
describeUserdobefore{subject.email="foobar"}it{shouldhave_errors_on(:email).with_message("Email has an invalid format")}end
Nice! One line instead of six. But that’s not everything, with a failing spec
failure messages might look like that:
sample.sh
12345678910
F
Failures:
1) User when email is not valid
Failure/Error: it { should have_errors_on(:email).with_message("Email has an invali format")} expected #<User @id=nil @email="foobar"> to have errors on :emailFinished in 0.00047 seconds
1 examples, 1 failure
It’s automatically generated by RSpec based on the matcher name. It’s ok, but
notice that it won’t tell us if the error message was incorrect. That’s why we
need to set custom failure messages.
Custom failure messages and it’s done!
It is really recommended to use meaningful failure messages. We need to set 2 types of
them, first one for “should” and second one for “should_not” expectations. The
idea is that if there is an error and the message is not correct, we need to
show that information in the failure output.
So, our complete matcher looks like that:
sample.rb
1234567891011121314151617181920212223242526272829
RSpec::Matchers.define:have_errors_ondo|attribute|chain:with_messagedo|message|@message=messageendmatchdo|model|model.valid?@has_errors=model.errors.key?(attribute)if@message@has_errors&&model.errors[attribute].include?(@message)else@has_errorsendendfailure_message_for_shoulddo|model|if@message"Validation errors #{model.errors[attribute].inspect} should include #{@message.inspect}"else"#{model.class} should have errors on attribute #{attribute.inspect}"endendfailure_message_for_should_notdo|model|"#{model.class} should not have an error on attribute #{attribute.inspect}"endend
Now if we run our example and it fails because an error message doesn’t match
the expectation, we will get following failure message in the output:
sample.sh
1234567891011
F
Failures:
1) User
Failure/Error: it { should have_errors_on(:email).with_message("Email has an invalid format")} Validation errors ["Email is blah"] should include "Email has an invalid format"# ./_examples/rspec2_matchers.rb:55:in `block (2 levels) in <top (required)>'Finished in 0.00053 seconds
1 example, 1 failure
Summing up
As you can see implementing custom RSpec matchers is
easy
trivial and it’s a highly recommended practice. There are plenty of use cases
where you want to write custom matchers. It makes your specs clean and even
more readable and what’s most important it keeps your spec’s code DRY and
extendable.
Here are some resources if you want to learn more:
Hello World! As usual it’s been a while since I wrote anything here. Just wanted to say
that I’m moving the site from WordPress to Jekyll and I like to share what I have
learned so far. If you are considering a migration too here are the steps I have
taken in order to port most of the tiny content of my blog. Read on and let me
know if something can be done in a better (or even completely different) way.
Posts migration
I followed the instruction
on the official Jekyll wiki. It worked without any troubles. I only had to
manually change file extensions from “html” to “textile”, since that’s what
I was using with WordPress to format my posts. Generated post files have
YAML fronts with
additional information taken from WordPress, specifically post ids and
permalinks.
Nginx setup
I had to make sure that old urls from WordPress will redirect correctly to the
new ones. Fortunatelly it’s easy to do that with Nginx, here’s my config:
Liquid error: ClassNotFound: no lexer for alias ‘conf’ found
This makes sure that urls with format “/year/month/day/post-title” will be
redirected to “/year/month/day/post-title.html”. I didn’t take care of
categories and tags urls, but it would be as easy to handle as in case of post
permalinks.
Setting up Jekyll
This was (actually still is as I haven’t finished) also a straightfoward task.
There is a nice overview on the
wiki that describes the basics you need to know about Jekyll.
Configuration has
defaults that work for me except pygments that I use for code highlighting which
is turned off by default. Every additional setting that you add to _config.yml
will be available via “site” object in your templates, so it’s handy
to configure at least your site’s url.
Layouts
In Jekyll you can easily nest layouts. I use 4 layouts, where “default” is
the base one:
tag -
used by “tag” pages which show all posts tagged with a given tag
Posts
Index page displays a list of post excerpts. With Jekyll you can include
“partial” templates by adding them to _includes folder. Here’s how you can use
it, given you have “_includes/excerpt.html” in your project:
123456789101112
---
layout: default
title: Home
---
<ul class="posts">
\{\% for post in site.posts limit: 15 \%\}
<li>
\{\% include excerpt.html \%\}
</li>
\{\% endfor \%\}
</ul>
I had troubles using categories with Jekyll so after all I decided to just use
tags. You can tag a post with YAML front:
template.erb
12345678
---title: My Posttags: - foo - bar---post content
Then all the tags will be accessible via site object in your templates. For
example you can list your tags along with post counts like that:
sample.html
1234567
<ul> \{\% for tag_data in site.tags \%\}
<li> \{\{ tag_data[0] }} (\{\{ tag_data[1].size \}\})
</li> \{\% endfor \%\}
</ul>
I put pages that list tagged posts in “tags” folder which makes them accessible
via “/tags/some-tag.html” urls.
I still need to write a rake task which dynamically generates these templates.
Rake task is done and it looks like that:
I use Pygments to highlight code snippets. Installation
instruction for various platforms is also on the wiki.
Once you got it installed you will need to generate CSS:
sample.sh
1
pygmentize -f html -S default > pygments.css
Where “default” is the name of a pygment theme. Here are available built-in pygments
themes:
autumn
borland
bw
colorful
default
emacs
friendly
fruity
manni
monokai
murphy
native
pastie
perldoc
tango
trac
vs
To learn more about Pygments you can check out the docs.
In order to highlight a code sample in your post you just wrap everything in a
liquid “highlight” block providing language name as an argument. Check out the
list of all languages supported by
Pygments, pretty impressive, BrainFuck included :). For instance if you want to
highlight a ruby snippet you do this:
This is still a work in progress. You can export entire content of your
WordPress blog to a special XML feed called “WordPress eXtended RSS”. Then you
upload this file via Disqus’ import tool. There is also another way, you can
use Disqus WordPress plugin to do the import automatically. Unfortunately neither
of these methods worked for me. It seems like the generated file is corrupted,
but the data are there so I will have to manually parse it and generate a new
import XML file. YAY…!
Resources
Here are some related links that you may find useful:
CodeRack is a coding contest dreamed up by a group of the Ruby programmers at Lunar Logic Polska who were excited about the possibilities of Rack middleware. The team wants to encourage Ruby developers to explore the possibilities and what better way than to hold a contest? The secondary goal of the contest is to generate a set of open source solutions that will solve real problems and inspire others. Every entry will be released under the MIT open source license.
Programmers are encouraged to submit contest entries that will be judged based on the cleverness of the application and the elegance of the code. Entries can be submitted at coderack.org until midnight EST November 15th. Finalists are scheduled to be announced on the 1st of December and public voting will run for one month. The final winners will be announced on the 5th of January.
The first round of the contest will be judged by an elite panel of judges including Ben Bangert of O’Reilly Media, Chris Wanstrath and PJ Hyett of GitHub, Joshua Peek of 37Signals, Yehuda Katz of Engine Yard and Rails core team member, Ryan Tomayko of Heroku, Core Rails team member Matt Aimonetti, and the Rails Envy team of Gregg Pollack and Jason Seifer.
Once the finalists have been selected by the panel, the public will vote for the top prize winners.
Prizes have been donated by Bytemark Hosting, GitHub, Jetbrains, Mindmeister, Freelance Total, Heroku, Rackspace Hosting, Peepcode, BDDCasts, and Zenbe Shareflow. The top prize includes a dedicated quad core server package and is valued at over $3000. Every entrant will receive a credit from bddcasts.com and $30 credit from Heroku. All finalists will receive a package including Zenbe Shareflow subscriptions, a RubyMine license from JetBrains, and five credits from bddcasts.com. Details of all of the prize packages will soon be available on the coderack.org website.
More information about the contest, including the contest rules, can be found at coderack.org.
A while ago I have written a post about JavaScript helpers in Ruby on Rails and tried to explain why they are a bad idea. It’s hard to believe for me that it was almost 2 years ago! Since then so many things have happened in the Ruby world…Now Rails 3 is on its way and we already know what significant improvements and changes it will include. One of them is related to JavaScript helpers and the way how remote links and forms will be handled and I must admit that the new idea is absolutely great.
The new way is based on unobtrusive approach to JavaScript. This means that HTML code will be separated from JavaScript. I have checked out the latest sources of Ruby on Rails and found out that some of the work is already done. There is a new helper called AjaxHelper, it implements link_to_remote method which in the moment of writing this post looks like this:
What you see here will generate a clean markup with HTML5-compliant attributes prefixed with a word “data-”. If you are not familiar with them you can checkout a nice article by John Resig HTML 5 data- Attributes. Those attributes will instruct the additional JavaScript code how it should handle the behavior. Basically all links, buttons and forms that have the special attribute “data-remote” set to “true” will issue an AJAX request. There has been a discussion on the Rails on Rails Core group about how to implement corresponding JavaScript code. People are worried about its performance since finding all elements with data-remote=true appears to be slow in case of Prototype and jQuery. Moreover there is a problem of new elements that may be dynamically inserted after the page was loaded and all the event listeners were attached. Fortunately there is no need to be worried as our situation is a perfect example where we should use Event Delegation. DHH has already showed in his Rails 3 and the Real Secret to High Productivity presentation how links and buttons can be handled by Prototype library and it looks absolutely reasonable to me.
I would like to focus on jQuery though as it’s getting more popular even in the Rails community. Great example is my job where we use jQuery in every of our new projects. So how can we handle new remote links and forms using this popular library? Actually it’s ridiculously easy. Thanks to jQuery.live function we can easily use Event Delegation to handle AJAX calls. Just take a look at this sample of a markup that new helpers in Rails 3 will generate:
sample.html
12345678
<!-- the new link to remote --><ahref="/users"data-remote="true">Users</a><!-- the new remote form --><formaction="/users"method="post"data-remote="true"><inputtype="text"name="login"/><inputtype="submit"/></form>
Pretty clean, I really like it! Now let’s see how we can implement jQuery handler that will send AJAX requests:
sample.js
1234567891011121314
varrequest=function(options){$.ajax($.extend({url:options.url,type:'get'},options));returnfalse;};// remote links handler$('a[data-remote=true]').live('click',function(){returnrequest({url:this.href});});// remote forms handler$('form[data-remote=true]').live('submit',function(){returnrequest({url:this.action,type:this.method,data:$(this).serialize()});});
The above code will send an AJAX request when you click on a remote link or submit a remote form. Note that it will work also with new elements dynamically inserted to the DOM. The example JavaScript code is the bare minimum of course, we could have something much more sophisticated. We will be able to specify success and failure handlers and also elements that should be updated with an AJAX response text (and probably much more!), hence the JavaScript is going to be more complicated.
This is definitely a step into the right direction. I’m looking forward to Rails 3!