Developer's Corner

There's far more exciting work to do than our current Wagn team could possibly tackle -- we need your help! Whether you're into design, documentation, programming, testing, or coordination, the dev team is ready to welcome new members.

Yeah?  You want to help?  Rock on!

Lots to do around here!  Here are some ways you can help:


Wagn's no beauty queen, but she's getting better looking all the time.  There's still a long way to go though, and we'd love to have help designing skins for new Wagns, building logos, improving icons, touching up layouts, etc.

Or, if you're more of an interface design person than a graphic design person, we could definitely use your help, too.  We're trying to make a lot of tough concepts simple and accessible, and that's a design problem if I ever heard one.


As you can see from this site's Documentation page, we're still lagging behind quite a bit in this arena.  You don't have to be a Wagn pro to help with documentation, you just need some initiative.  It's about asking questions and organizing.  What a great way to contribute to this open source community project!


We're extremely grateful for the software patches various folks have sent us already, and we're hoping to make Wagn a more and more welcoming project to contribute to.  Feel free to contact us!  Or you can just get started by installing Wagn and developing. When you come up with something you'd like us to see, send us a patch 

Dig In

Oh, and then there's the whole piece that makes community software - digging in and figuring out what could be done to make the site and software better.  Refine content, add suggestions, contribute to discussions, play with the features.  It's all a huge help!


It can be daunting to jump in and start developing code for a big project like Wagn, so we're keeping a running list of good ways to get your feet wet.


We've divided them into two groups -- (1) ways you can jump in and write a good chunk of helpful code without having to learn much about Wagn's innards, and (2) smaller issues involving minor code fixes that will pull you deeper in.


Of course, if you're looking for more of a challenge, we can provide!



More Code / Less Deep

  1. √- Installation Scripts — Getting Wagn working is still a bit of a hassle. Many of the gem installations could be scripted, and core configuration options could be prompted.
  2. Quick Install -- We'd love to offer a simple installation with SQLite that users can get going in just a few clicks.
  3. Integration -- There are lots of opportunities to start building things that use Wagn's api. A Facebook app, a Ubiquity script, etc. We'd love to see what you can come up with.


Deeper In / Less Code

  1. Image Edit Mode — We want to be able to see current images while we edit them. This is an easy one — amounts to adding an image tag — but offers a chance to dig into our cardtype structure.
  2. No links in table of contents — A shallow bug that will be fun for folks who like playing with regular expressions.
  3. Handle Name Collisions Better — Right now if you try to card with an existing name, it fails and gives you an error that says that card already exists. But there's no way to see the card.
  4. Escaping Syntax — We want to be able to use backslashes () to escape square ([) and curly (}) brackets, used in link and inclusion syntax respectively. The links should be fairly straightforward; the inclusions will be a bit trickier.
  5. Database Compatibility -- We think things are going pretty smoothly in MySql and Postgres, but we haven't tested SQLite enough for confidence, and we'd love help testing in all of them
  6. Firefox spell-check — Frankly, I don't know what turns this off. Maybe this isn't really "deeper in"??



Caching Cards

Current caching strategy uses "cached cards".  CachedCard.get() may return a cached card.  a cached card is a proxy which handles some method calls-- if they are stored in the cache it retrieves them.

the granular cache strategy makes sense for some kinds of rendering--
"give me line view for card X"..  why load all the rest of the stuff?

in some ways, it would be nice to have the caching more integrated with the core api-- so that whenever you're requesting a card, it can come from the cache if it's available there.  the trouble with this is that the API for the CachedCard is different from a "real" card.   this is for two reasons:

1) a cached card can't do all the stuff a real card can.  You can make it so that the cached card will retrieve the real card if you call a method it can't handle, but in that case you're likely defeating the point of going to the cache in the first place.

2) cached cards can respond to some methods that real cards can't-- line_content() for example-- some parts of the cached card are assigned by the rendering layer, and don't really belong in the lower level model.

If the APIs of the objects in fact need to be different, then it makes sense for the caller to have different points of entry so they're choosing on purpose which thing they want. 

For now the cached card strategy is working,  and there is at least some sense to the reasoning that leads us to this "model" that is nestled in between a real DB model and and the rendering layers.  In MVC, Cached Cards are sortof a wrapper around M for special purpose use by V. 

Update:  some of the need for API integration, for example use in caching templates accessed deep in the system, have turned out to be fairly shallow problems and have been addressed.  others still need work; see below

Caching Auto and Search Cards

Caching Auto cards is not hard, providing we know when they expire, except that they are usually search cards, and search cards are "uncacheable".   We flag cards as "uncacheable" but what we really want most of the time is "post-cache-processing".  Here we run into the problem of API mentioned above-- post-cache we have only cached cards, which in the case of search won't have the methods necessary to run the search, and it's not clear how to best differentiate between the different types of cards.

I think we need two things to make this all work. 

1) We need to be able to specify some methods that apply to both the card and to cached cards of that type.  One solution is to designate a special module name for these method,  say "PostCache".  Then Card::Foo  mixes in Card::Foo::PostCache, and when we create a CachedCard of type="Foo" we also mix in Card::Foo::PostCache. 

2) We need to modify the rendering in slot.render to somehow allow cards to interject custom post-cache rendering.

Recent Changes

Recent Changes is a special case that needs its own mechanism.  One possibility is grouping into a series of changesets.  When a card is edited, we check how many changes in the current changeset-- if its over N then we increment $current_changeset_id.  in either case, we set card.changeset_id = current_changeset_id.
Then when we go to recent changes we add a condition of most changeset_id=$current_changeset_id (which can be indexed) and boom we've narrowed to the last N revised cards without having to order the whole table by update.  the only problem is paging.  If  N (changeset size) happens to be == page_size, then there may be opportunity for a mapping there.  otherwise we have to do funky math to figure out which changesets we need for which page.

Serials in the sky for caching

In a hash, in the sky, we have a set  of serial_key=>serial_value pairs.  serial keys can be associated with cards, types, searches, anything.  then, there are two questions to ask.

reading:  what serials does my object depend on?
writing:  what serials does my object affect?

for example, say you have a search:  {"type":"User"}.     depends on serial_key: "type_User"
any card of type User affects key:  "type_User"

one key concept here is when you go to grab the results of the search, you DON'T HAVE TO KNOW what the "type_User" serial_key was last time you saved to the cache.  you just ask for the current one. 

all that remains is to layout the serial_key dependences and affectations.  oh and implementation :-)





just a note:

sql queries on save:
  5 - validation
    9 - expire_cache ( hard_templatees, dependents, referencers, name_references )
    12 - update_references_on_update

for now, in order for the test database setup to work, you need your current development environment connected to a database WITHOUT fulltext enabled-- the fulltext fields break the schema transfer. one workaround is just to switch to a new wagn database temporarily to run the tests.


Building a healthy online community takes more than just choosing the right tool; you have to adapt that tool to make it fit your community's needs.



Community design isn't primarily a feature-driven activity, but the following should be considered:

  • accounts - what is the process for entering the community?
  • Role - what levels / arenas of engagement are codified?
  • permissions - who can create, read, update, and delete what?  It's also worth considering that not all permission rules need to be technically enforced; in some cases it's smoother to have social agreements (eg, you can fix typos, but please send comments rather than make major edits)
  • history / recent changes - who will review edits?
  • comments - how should you frame online discussions?



Tickets relevant to community