An introduction to the Diaspora source
Framework and Tools
Diaspora is written in Ruby on Rails, a web framework for the Ruby programming language.
If you’ve never looked at a Rails project, you may want to check out a Rails guide like this one.
There are a few tools we’re using that aren’t in every rails project:
- Haml
Our view templates are written in HAML (a templating language) instead of the default ERB (HTML with inline Ruby code).
The HAML docs can be found here. The corresponding files under app/views.
- Sass
Our CSS is written in SASS (specifically, the ‘scss’ dialect), which generates the actual CSS via the Rails asset pipeline. The syntax is inspired by CSS, and quite similar, but it offers some additional features like nesting and variables. If you want to edit the stylesheets, have a look in app/assets/stylesheets/.
Note: Both HAML and SASS are whitespace sensitive.
- Backbone.js & Handlebars.js
The client-side functionality and rendering is mostly coordinated with Backbone.js, which communicates REST-fully with the server with JSON and triggers the rendering of the Handlebars.js templates. The logic is found in app/assets/javascripts/app and the Handlebars templates are located in app/assets/templates
Testing
Our goal is to test everything. If you find a bug, you first expose it by writing a tests that fails because of the bug. Only then you start fixing the actual code. This is called Test Driven Delopment (TDD).
We write our unit tests for ruby code in Rspec, the JavaScript test are in Jasmine and integration tests in Cucumber. Specs are in spec, and Cucumber features are in features. For more details see our page on Testing Workflow.
The Models
Our Models can be found in the app/models folder:
User – Users, of course, come first. A User object represents the private information and capabilities of a user on that server. The user object is able to friend people, post updates, and update his profile. A User has a Person.
Person – A Person is a User viewed from the outside. When a user friends another user, they friend that user’s Person object. Person objects are replicated across servers, and they are where a User’s public key lives. A Person has many Posts. A Person has a Profile.
Profile – This contains information about the person. Currently, a profile looks the same to anyone looking at it.
Contact – Defines the relationship between a User and another user's Person.
Request – This is a friend request object that gets sent to another person.
Aspect – This contains a list of people, and posts which are for that aspect. Aspects are private to Users, and we might embed the Aspect documents in the User document.
Post – A Post belongs to a Person. This is a parent class for different types of posts, it contains comment ids and a few other attributes common to all Posts.
- Status Message inherits from Post
- Album inherits from Post
- Photo inherits from Post
Comment – a comment belongs to a Post
Retraction – this is an object that gets sent out when a post creator deletes a post. It is not a model, but it serializes for dispatch to other Diaspora servers the same way our models do.
Posting something (app/models/user)
- When a user posts anything, they posts it to an aspect or all aspects.
- Assuming the post is valid, the post is created and its id is stored in raw_visible_posts for that user
- The html for that post is rendered on the server and is pushed to the user through the websocket
- The post is then serialized to xml, wrapped in an encrypted and signed Salmon envelope and POSTed to the receive urls (http://pod.location/receive/users/:id[person_id]) for the recipients' Person objects.
Receiving a post (app/controllers/publics_controller.rb & lib/diaspora/user/receiving.rb)
- The user receives the salmon, decrypts the headers.
- If the signature on the salmon data is from the person who claims to have sent the post is marshaled into an object and saved into the database.
- That post id is stored in the visible posts for the receiving user as well as posts for the aspect the sender is in.
Here’s the autogenerated documentation http://rubydoc.info/github/diaspora/diaspora/master