A View from the Street

Musings from the People of Eye Street

RSS

Archive

Jul
13th
Wed
permalink

Plain Language and Respectable Web Writing

The Plain Writing Act of 2010 requires federal agencies to write, “Clear government communication that the public can understand and use.” This aligns perfectly with good web writing. With the upcoming July 13, 2011 deadline for the first round of improvements, it’s a good time to address my favorite federal web writing, “Bad Habit.”

First, let’s go through the Act.

The July 13 deadline requires each federal agency:
• Designate a senior official for “plain writing”
• Explain the Act’s requirements to staff
• Establish a procedure to oversee the implementation of the Act within the agency
• Train agency staff in plain writing
• Designate staff as points of contact for the agency plain writing web page
• Post its compliance plan for meeting the requirements of the Act on its plain language web page

These requirements are setting the stage for the larger October 13, 2011 deadline, which requires each federal agency:
• Use plain language in any document that:
o Is necessary for obtaining any federal government benefit or service or filing taxes
o Provides information about an federal government benefit or service, or
o Explains to the public how to comply with a requirement that the federal government administers or enforces
• Write annual compliance reports and post these reports on its plain language web page

The requirements are clearly written in order to help with implementation. We should be seeing plenty of activity in the next three or so months on federal websites as the Act is implemented.

So my favorite “Bad Habit” is using the word “Pursuant.” Pursuant is defined as, “in accordance with the law.” It’s a horrible lead to a web page. The introduction paragraph of any web page should be a concise summary of the contents of the page with a focus to the end-user. It should identify the user’s top tasks and describe your agency’s key activities. That said, citing public law probably isn’t top of your list.

However, we aren’t tossing out the use public law references. Add a section or sub-page with your laws and regulations to allow the user to read or ignore them as they wish. Citation is important, but should not be the lead to your web page.

In fact, we could drop pursuant for “in reference to” and improve the readability of our web pages. Microsoft Word has a feature you can turn on to access readability statistics on your text. Shorter sentence structure, active voice and words with fewer syllables are easier to read than complicated, dense web copy. Test your document’s readability - Word - Office.com


There are also free online tools that you can use:
• Tests Document Readability
• Readability index calculator

How did this post score? Using Word, I get a grade level score of 7.9.

Learn More
www.plainlanguage.gov

Comments
Jul
6th
Wed
permalink

:accepts_nested_attributes_for with Polymorphic Associations and a Custom Autosave

Wheew… what a title… kinda dry, very geeky, but if you landed here, hopefully this will help. This blog documents some of the code wrangling that we did for a recent app, VRCompliance. I needed to have the ability to create multiple phone numbers when inputting either addresses or people in our system. It seemed like a great time to use models with with the :accepts_nested_attributes_for :nested_model declaration. When doing this I found out that the default creation of a nested object was not what I wanted. Essentially, I wanted a find_or_create for the nested object. After some searching I came across this StackOverflow article that describes a solution. This post adds to the discussed solution by going into additional detail and fleshing out the answer described in the previous link.

For this post I’ve simplified our objects so our sample application has people, addresses, and phone numbers. Both a person and an address can have many phone numbers. Additionally, with our application’s data it is possible to have a many-to-many relationship between the phone numbers, people and addresses. Instead of using two separate join tables to describe these relationships, I went with a polymorphic association, calling our resulting common join table, phonings, and the polymorphic relations a phonable.

Our models look similar to the snippets below:

And the initial phoning model was:

With the models and their relationships defined, I built the forms for creating an address, and wanted to nest the creation of the phone numbers within the forms for the creating of both a person and address. Initially, I think I had :accepts_nested_attributes_for :phone_numbers in the address object, but there were issues with that approach.

First, deletion of the phone number deleted the object, and second, if I added the phone number to two different objects then I would get validation errors due to uniqueness constraints that I have on our real phone number object. After digging around, I found some links that discussed making the nested attributes for the join table so that on deletion you are really deleting the join object and not the object it relates. This resulted in :accepts_nested_attributes_for :phonings in the address object (as seen above).

Deleting of an object no longer deleted my phone number object, just the phoning object. However, I still had the issue that if the same phone number was added to two addresses via nested attributes then two distinct phone number objects were created. The test below shows passing tests that document this issue. Two addresses are initialized and saved with the same nested phone number. After saving both, we find that we have two phone number objects with the same phone number.

Based on the StackOverflow thread from above, I realized that I needed to change the autosave creation of phone numbers. It should be noted that accepts_nested_attributes_for automatically sets :autosave for the model. Autosave means that associated records are automatically saved when the parent object is saved. In our examples this means that when an Address object is saved the Phoning object and the PhoneNumber object are saved. The default functionality is to create a new object. The gist below shows the necessary changes to our test to generate the desired functionality of the find or create for the nested phone numbers.

We can then move that functionality back in to our model:

In a future post, I will walk through the view and controllers used for these nested forms.

Comments
Jun
29th
Wed
permalink

Customer Service – the Art of Not Saying No

Eye Street Solutions has a strong commitment to customer service.   Some people may think about customer service in terms of retail returns or IT help desk support, but it’s a key factor in content management, especially if the clients you serve aren’t web content professionals. 

The team at Eye Street interacts with hundreds of different clients across a large federal agency.  All are subject matter experts in their field, but have varied levels of web experience.  Most of them publish as “other duties as assigned” or to meet a requirement.  They are task focused on getting their material posted with the least amount of hassle (to them!).

To manage expectations, we have published service level agreements. Each request is evaluated against the agency’s written policies and procedures as well as federal laws and guidelines (such as Section 508 / accessibility). If there are any issues with the content package, it is sent back to the client for further review.  Once the package is complete for processing, it’s assigned to a team member and an estimated publishing date is sent back to the client.

This process works well for routine updates as well as new information that follow established protocols, such as posting a publication.

What gets tricky is when the request comes in that isn’t routine.  Many times by the time it gets to the web team, there has been a lot of time and effort that has been put into the package without any recognition of federal requirements, the agency’s policies or procedures, or web writing best practices.  It’s easy to say “no” but that isn’t effective.  They need training or further education.

We know the training objective – training/refreshing the content provider on federal requirements, the agency’s policies or procedures, or web writing best practices while getting the content fit for publication.

For federal requirements, they will need to modify their package (say, provide a timed caption file for their online video).  We’ll send them a link to a training video to help them complete this step. Requirements are easy. They have to be completed before anything can be posted.  Through this process, they will be aware of federal requirements for future postings.

For policies and procedures, the discussion is more nuanced. For instance, their proposed information may be organized by how the office is structured, not by topic.  We see from research and our metrics that the American public doesn’t look for information by how the agency is organized but by the topics that interest them.   We’ll help them classify their information, while training them about how to classify new materials in the future.

Following web-writing standards is the most difficult as many times we are working with final cleared content.  Getting materials cleared is a herculean, time-consuming process that we can’t revisit.   What we can do is restructure, reorganize, as well as add sub-headers, bullets and images to help bring clarity to the information.  As well as giving them tools to write for the web in the future, we also offer to help out earlier in the clearance process before the information is final.

This training process is quick, customizable and meets the objectives.  We meet the client’s mission while producing materials that are friendly to the end-customer, the American public.  And it’s all done without having to say “no.”

Comments
May
16th
Mon
permalink

SpeedTouch v1.2

speedtouchapp:

A new release of SpeedTouch is now available in the App Store.

What’s New in Version 1.2

  • Added ability to create FaceTime shortcuts.
  • Fixed issue with international numbers.  Grazie Francesco!
  • Fixed issue with shortcut title.
  • Added high resolution shortcut icons.
Comments
Apr
11th
Mon
permalink

Polishing Objective-C: Pulling Up into Categories

Objective-C with Cocoa does a lot for you, but if you are used to other languages and frameworks, you’ll quickly pine for the convenience methods that are missing.  Lets say that you need to trim whitespace from strings.  In Java, you can trim the whitespace from a String object like this:

String trimmedString = myString.trim();

No simple trim method exists in the Objective-C NSString class, so I’ll use Google to find a code snippet to do the same thing.  Soon the snippet is sprinkled throughout my code:

NSString *trimmedString = [myString stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]

The result is very repetitive and verbose.  If I want use this snippet in multiple places, I should extract it into a method:

-(NSString*)trimString:(NSString*)string
{
    return [string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
}

This reduces each trim operation to:

NSString *trimmedString = [self trimString:myString];

If I want to use it in multiple classes I can go further by pulling it out and making it a class method inside of a Utility class so it is accessible to all of my classes:

+(NSString*)trimString:(NSString*)string
//...
NSString* trimmedString = [Utils trimString:myString];

Categories

The method is pretty clean, but wouldn’t you rather call a trim method directly on a string object?  Perhaps the most powerful refactoring tool in Objective-C is the category.  With categories, we can pull methods up into a class that is already defined by a framework.  In this case, we’ll also define trim as a read only property for conciseness.

Create a header file.

//NSString+Trim.h
@interface NSString(MyCategories)

@property(nonatomic, readonly) NSString *trim; // or stringByTrimming, if you want to name like Apple for derived objects.

@end

Create an implementation file.

//NSString+Trim.m
@implementation NSString(MyCategories)

(NSString*)trim
{
    return [self stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
}

@end

Include the category in your prefix headers file(myApp.pch).

//myApp.pch
#include "NSString+Trim.h"

Result

The result is far more concise and readable than the original code:

NSString *trimmedString = myString.trim;

To see many more examples of convenience methods pulled up into categories, see the es_ios_utils library.

Comments
Mar
25th
Fri
permalink

Veporter - Shoot. Splice. Style. Submit.

Introducing Veporter, an iPhone app that allows you to create a video to submit directly to your organization’s content management (ECM/WCM) system.  Turn your users or employees into reporters!  Users can import videos and photos from the iPhone’s cameras and albums, arrange them as desired with a simple crossfade, and upload the video to YouTube or a demonstration enterprise website.  The project is saved for future use and can be exported to your photo-roll.

Vist our website to download Veporter.

While Veporter makes it easy for anyone to compose video, the real purpose is for the app to be customized for your enterprise.  Collect videos for direct journalism, product reviews, inspection evidence, media libraries, online training, or public relations.  We can include a custom asset library with a logo title screen and any other standard items needed.  Even better, we can integrate it with your servers and processes.  Contact us for more information.

We are working to add a variety of features to Veporter such as titles, voice over, and support for tumblr.  Thousand of users have installed Veporter so far, and an April update will be released to respond to initial user feedback.

Comments
Nov
12th
Fri
permalink

Internet Explorer Cookies Bug

As a white labeling URL shortener, ShortSwitch.com needs to be able to support logins from not only our own domain but a user’s account domain as well.  One of our customers opened a ticket to inform us that some of his customers - namely those using Internet Explorer - were having problems logging in.

At the time we were setting the browser cookie to be .domain (e.g., .ab.cd, .abc.com) per a very nice write up on handling sessions in a multi-domain environment using Dynamic cookies and Rack.  After adding debugging lines all over the Ruby on Rails core code we found the problem - IE was not setting cookies for domains of less than five characters.

Internet research showed us Microsoft had fixed a bug where IE would not set a cookie for two letter domains.  Specifically they fixed it for root domains of two letters (e.g., ab.com).  But we had discovered that there’s still a bug in IE where cookies will not be set for domains that are less than five characters (e.g., ab.cd).  Our findings were confirmed on StackOverflow.

In Ruby on Rails not setting the cookie creates a problem - the server thinks each request is a new request causing it to regenerate a new auth token.  Any server request that checks the auth token will fail with the ever frustrating ActionController::InvalidAuthenticityToken error.

The solution we ended up using was to not set the domain as a value in the cookie for any domain other than ShortSwitch’s. Works just fine.

Thanks for keeping us on our toes, Microsoft.

Comments
Nov
10th
Wed
permalink
Comments
Sep
30th
Thu
permalink
Comments
Aug
9th
Mon
permalink

Additional Features To Maintain Your Brand

Here are some recent changes from our ShortSwitch product.

shortswitch:

Account Settings

We recently had a request to allow the root URL of your white-labeled domains to be redirected to another location, instead of the ShortSwitch homepage. Seemed like a great idea, so we added the feature. Now if someone sees your pithy short domain, and either strips the token or enters an invalid token, you can have them directed to a location on your web site. Both a custom invalid URL and a homepage redirect URL can be added in your account settings.

Comments