"Here’s to the crazy ones, the misfits, the rebels, the troublemakers, the round pegs in the square holes… the ones who see things differently — they’re not fond of rules… You can quote them, disagree with them, glorify or vilify them, but the only thing you can’t do is ignore them because they change things… they push the human race forward, and while some may see them as the crazy ones, we see genius, because the ones who are crazy enough to think that they can change the world, are the ones who do."
— Apple Inc.
10:51 am • 6 October 2011 • view comments
Implementing SSL Tweet Button
According to Twitter doesn’t officially support Tweet Button over SSL.
The main issue is that assets are served from subdomains that has “untrusted” SSL certificates, for example: https://platform1.twitter.com/. This is a big problem when you want people to share a site that’s served under https.
To implement it we can do this:
1= link_to "Tweet", "https://twitter.com/share", class: "twitter-share-button"
And then include this javascript file widget.js that prevents Twitter from loading assets from untrusted subdomains and just load them from platform.twitter.com.
And… That’s it! You have now SSL Tweet Button (with “count” support) on your secure site.
4:21 pm • 27 July 2011 • 1 note • view comments
Identity Map and Active Record
As many of you may know Identity Map was merged recently into Active Record.
Identity Map is a design pattern that:
Ensures that each object gets loaded only once by keeping every loaded object in a map. Looks up objects using the map when referring to them.
ZOMG! What does this mean?
The following is an example of Active Record’s behaviour before Identity Map:
1 post = Post.find(1)
2 same_post = post.comments.first.post
3
4 puts post == same_post
Will return true as expected, since it’s the same object… wait… is it?
1 puts post.object_id == same_post.object_id
And we would get false. Why is this? Because equality method is redefined in Active Record to compare if both objects are instances of the same class and if they have the same id (not object_id). So they are 2 different objects, that looks the same.
Active Record with Identity Map
Identity Map was included in Active Record as a module: ActiveRecord::IdentityMap. This module keeps a map per thread to avoid concurrency issues, and handy method to add, remove and retrieve objects from the map (one map is used per Active Record class).
Then Active Record makes use of Identity Map when instantiating objects, before trying to instantiate it, it will look into the class map using the primary key, if it exists it will be retrieved from them map, otherwise it will be queried and then stored into the map. Same will happen when trying to load the object from finders or when loading them through an association.
So in the example above if we execute now:
1 puts post.object_id == same_post.object_id
We will get true as expected. In order to check more examples, take a look at Active Record’s IM tests.
Awesome! I want it!
In existing Rails apps it will be disabled by default. In order to use Identity Map in our Rails application we’ll have to enable it in application.rb file:
1 config.active_record.identity_map = true
As for new application, this line will be automatically added to application.rb file.
By setting this configuration a middleware will be added into the Rails middleware stack, this will wrap the transaction into an ActiveRecord::IdentityMap.use block:
1 def call(env)
2 ActiveRecord::IdentityMap.use do
3 @app.call(env)
4 end
5 end
This way a new map will be generated for each request. There isn’t a global map since it would introduce many concurrency issues and potential consistency problems.
We could also disable Identity Map and use manually the use block, just where we consider is needed:
1 ActiveRecord::IdentityMap.use do
2 user = User.find(id)
3 user.do_that_heavy_thing_you_do!
4 end
The other way around, we could enable it and disable it the same way use the ActiveRecord::IdentityMap.without block.
Benefits
- Consistency: an object is exactly the same object everywhere, not another object that just “looks” like it.
- Resources: as we avoid instantiating new objects, we also avoid allocating them thus saving memory. In some cases this can lead to huge improvements, for example when running heavy background jobs.
- Speed: in many cases queries will also won’t be triggered since the object will be in the map, saving processing time.
Closing
Thanks to everyone that made this possible. I hope we all enjoy having an identity map inside Active Record.
If you have any questions or thoughts, I would love to know them!
9:18 pm • 19 February 2011 • view comments