tag:blogger.com,1999:blog-11761372534566086472024-03-13T08:03:20.042-07:00Short PathAttention Driven DevelopmentDavehttp://www.blogger.com/profile/16335253725087209777noreply@blogger.comBlogger20125tag:blogger.com,1999:blog-1176137253456608647.post-73531543231431051372009-11-15T20:25:00.001-08:002009-11-15T20:25:48.433-08:00Caught in App Store LimboA few weeks back I <a href="http://twitter.com/digidigo/status/5046894539">tweeted</a> about a problem I was having in the app store with one of my client's apps. The problem was that our application , <a href="http://itunes.apple.com/us/app/bed-bug-identifier/id334697423?mt=8">BedBug Identifier</a>, was not showing up in the app store , although it had been approved. I checked the normal things, typos, categories, release date and everything was in order. We waited days.<br /><br />Finally the client got through to someone in developer relations (note: they do not actually have anything to do with the store itself). They gave us a glimmer of hope, indicating that we did not have a developer certificate in place, or a developer provisioning profile. This was simply because I use my own to develop for clients and don't see the need. This wasn't the first client that I did this for but it was worth a try. I casted the magic developer portal incantation and 'presto chango' ... nothing. I called develper relations myself, and basically got a slap on the wrist for not following official protocol. But still no luck, and the client was in a panic since they were at their yearly trade show and really wanted to get the app out the door.<br /><br />Finally a true hero emerged, the fine folks at<a href="http://www.x-cr.com/"> Xcellent Creations</a> had done all the design work on the app and had some contacts at apple that were actually helpful. It turns out that the large icon for the app had a compression format that the app store didn't support. Everything in iTunes Connect showed green - go indicators, but still the icon was not valid. So 30 seconds later, I converted the tiff file to jpg , uploaded it to the store and 'presto chango' the app appeared in the store 2 hours later.<br /><br />Now you would hope that someone at apple would realize that a 15 second <span style="font-style: italic;">convert</span> scrpit could save them and developers all this headache. Or at the very least detect that the file is not supported and kick it back out ~ <span style="font-style: italic;">that is probaly only 10 seconds to write.</span><br /><br />So if you app is approved but doesn't show up in the app store. Make sure your TIFF files don't have some compression turned on. Or even better, just make them jpegs to be sure.Davehttp://www.blogger.com/profile/16335253725087209777noreply@blogger.com0tag:blogger.com,1999:blog-1176137253456608647.post-68043542417854988062009-07-02T13:17:00.000-07:002009-07-02T13:24:22.600-07:00Codesign Error and FBConnect Library for IphoneJust spent the morning tracking down an issue where I couldn't submit an application to the app store. Hopefully good will pick this up and save you some trouble<br /><br />This is the key issue:<br /><pre style="font-weight: bold;"><span style="font-size:130%;">a sealed resource is missing or invalid</span></pre>You will see that error when using <span style="font-weight: bold;">ApplicationLoader</span> while looking at Console.app.<br /><pre>Here is the full message:<br /><br />7/2/09 1:26:31 PM ApplicationLoader[1037] *** Codesign error (please ignore invalid option comments): got requirements(0x805a00, 556)<br />Executable=/var/folders/fC/fCYkmIs5EtextlqOt9Oo9E+++TQ/-Tmp-/YourApp.app.zip/YourApp.app/YourApp<br />Identifier=com.yourcompany.app<br />Format=bundle with Mach-O thin (armv6)<br />CodeDirectory v=20001 size=10131 flags=0x0(none) hashes=498+5 location=embedded<br />Signature size=4331<br />Authority=iPhone Distribution: Your Company Inc.<br />Authority=Apple Worldwide Developer Relations Certification Authority<br />Authority=Apple Root CA<br />Signed Time=Jul 2, 2009 1:25:44 PM<br />Info.plist entries=20<br />Sealed Resources rules=3 files=86<br />Internal requirements count=0 size=12<br /><br />Executable=/var/folders/fC/fCYkmIs5EtextlqOt9Oo9E+++TQ/-Tmp-/iGotchaLite.app.zip/iGotchaLite.app/iGotchaLite<br />got entitlements(0x805e00, 323)<br />codesign_wrapper-0.7.3: using Apple CA for profile evaluation<br />codesign_wrapper-0.7.3: Caling codesign with the following args:<br />codesign_wrapper-0.7.3: /usr/bin/codesign<br />codesign_wrapper-0.7.3: --verify<br />codesign_wrapper-0.7.3: -vvvv<br />codesign_wrapper-0.7.3: -R=anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.1] exists and certificate leaf[field.1.2.840.113635.100.6.1.4] exists<br />codesign_wrapper-0.7.3: --entitlements<br />codesign_wrapper-0.7.3: /var/tmp/signingbox/codesign_wrapper_entitlements.plist<br />codesign_wrapper-0.7.3: /var/folders/fC/fCYkmIs5EtextlqOt9Oo9E+++TQ/-Tmp-/YourApp.app.zip/YourApp.app<br />/var/folders/fC/fCYkmIs5EtextlqOt9Oo9E+++TQ/-Tmp-/YourApp.app.zip/YourApp.app: a sealed resource is missing or invalid<br />codesign_wrapper-0.7.3: failed to execute codesign(1)<br /><br /></pre>I finally found out that the issue was some strangely named files in the FBConnect.bundle .<br /><br />The solution is to remove files that start with "._".<br /><br />Here is the blog post that finally saved me from my mental breakdown.<br /><br /><a href="http://blog.evandavey.com/2009/04/a-solution-to-application-failed-codesign-verification.html">A solution to: Application failed codesign verification</a><br /><br />Thanks Ev.Davehttp://www.blogger.com/profile/16335253725087209777noreply@blogger.com3tag:blogger.com,1999:blog-1176137253456608647.post-68798158892873502692009-02-26T15:13:00.000-08:002009-04-02T09:53:42.840-07:00Apple is Removing Apps from the Store --- Again!Some of you might remember Sound Grenade. A total app store success story. Guy build an app in 20 minutes. You press a button and it makes a very annoying sound. Sound Grenade quickly became the #1 Free app in the App Store. And is sibling Sound Grenade Pro also did very well.<br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhHkcEpPceoMU-2lSNxauxuK7z00Uocm0f8FJRqVJGsBmcib5NU0ZisEQoZaWH35dnlkRa6vugjE-9V6ta2oUO2PLesGGCCM9PNbAFa-wbCEBhveUnZriGPAk6GVF787c6wpEHLOKIWnGs/s1600-h/Picture+94.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 231px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhHkcEpPceoMU-2lSNxauxuK7z00Uocm0f8FJRqVJGsBmcib5NU0ZisEQoZaWH35dnlkRa6vugjE-9V6ta2oUO2PLesGGCCM9PNbAFa-wbCEBhveUnZriGPAk6GVF787c6wpEHLOKIWnGs/s320/Picture+94.png" alt="" id="BLOGGER_PHOTO_ID_5307249893151246882" border="0" /></a><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiX_xnnn9HvSKypmeoWRDumn5ZVL0v-SstUVEU0wOQwaKlzO7kutCE5g1WsnuTKLocrWsLBI3xSyvohhcGVfMDAW1xateHoDn8uzC-DHN5xVGSiLTpsqP84LlXWQ2XvlqjM10vZnhm68tc/s1600-h/Picture+96.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 307px; height: 114px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiX_xnnn9HvSKypmeoWRDumn5ZVL0v-SstUVEU0wOQwaKlzO7kutCE5g1WsnuTKLocrWsLBI3xSyvohhcGVfMDAW1xateHoDn8uzC-DHN5xVGSiLTpsqP84LlXWQ2XvlqjM10vZnhm68tc/s320/Picture+96.png" alt="" id="BLOGGER_PHOTO_ID_5307253288323877330" border="0" /></a><br />Sound Grenade inspired us to create our own aggravating sound boards. Our first of these was <a href="http://bit.ly/12UKyG">Aggravate Nails on Chalkboard</a>. Now I totally admit, this is a ringtone app. It is free , scrape your finger down the screen and it makes the sound of a Nail scratching a chalkboard. My wife Hates It!! And some days that is funny. Apple doesn't think. And neither does she actually.<br /><br /><br /><br />Applying some quality metric they are able to distinguish between the annoying sound of Sound Grenade and Nails on Chalkboard. I got an email today saying they were removing it from the store because it does not provide enough functionality to be appropriate for the store.<br /><br />At the time of this writing the app has 75k Downloads, 1.75 Sessions per user has a CTR on the ads of 10% and was pulling in a whopping $20 a day!<br /><br />Now I admit the reviews on the app are abysmal, people don't think it sounds like a real chalkboard. I swear that it is a real chalkboard .. we even remastered the sound to make it better. And some people love it. Just not apple, or some reviewer at apple.<br /><br />Maybe they did me a favor and I should go back to making apps that are not just entertaining but useful as well.<br /><br />What does it mean? I guess I need to go record two awful sounds and offer that as an aggravating sound board? Would that be enough functionality?<br /><br /><br /><span style="font-weight: bold;">UPDATE</span><br /><br />Since the App is still available on the store the mystery of the app store rejection is still continuing. I don't think this letter is under NDA so I thought I would post it for all to get your opinion.<br /><br /><br /><blockquote><br />Dear Mr. Clements,<br /><br />We've reviewed your application, Aggravate Nails On Chalkboard, and we have determined that this application contains minimal user functionality and will not be appropriate for the App Store.<br /><br />If you would like to share it with friends and family, we recommend you review the Ad Hoc method on the Distribution tab of the iPhone Developer Portal for details on distributing this application among a small group of people of your choosing or if you believe that you can add additional user functionality to Aggravate Nails On Chalkboard, we encourage you to do so and resubmit it for review.<br /><br />Regards,<br /><br />iPhone Developer Program<br /><br /></blockquote><br />So who knows what this really means I guess. If I were apple and determined that something was not 'appropriate for the store'. I would remove it from the store. Trouble in the review process? Maybe the reviewer does not know that they are reviewing an update? Still no word from apple.,,,<br /><br /><br /><span style="font-weight: bold;">Latest Update: Aggravate 1.3 is live on the store<br /><span style="font-weight: bold;"><br /></span></span>So it<span style="font-weight: bold;"><span style="font-weight: bold;"> </span></span>appears that I misspoke. Or perhaps Apple mis-cut and pasted the rejection response.<span style="font-weight: bold;"><span style="font-weight: bold;"> </span></span>They never took Aggravate off the store and I didn't have to send adhoc builds to my friends and family for them to be Aggravated. And I didn't have to add a flashlight or farting to the app in order to get it approved.<br /><br />Aggravate 1.3 was approved a week ago and quickly rose to top 50 in its new category, Utilities. All I did was change the category and re-submit the application.<br /><br />Not sure what this means. Are the guidelines for utility apps different? Do apple reviewers not realize they are reviewing an update? Could I have re-submitted in Entertainment?<br /><br />Anyway, you can still aggravate your friends a little longer until the next update perhaps.<span style="font-weight: bold;"><span style="font-weight: bold;"><br /></span></span>Davehttp://www.blogger.com/profile/16335253725087209777noreply@blogger.com9tag:blogger.com,1999:blog-1176137253456608647.post-28457276530064843662009-02-03T19:24:00.000-08:002009-02-03T19:53:55.958-08:00Battling the Crackers is not good for your soulVery recently a piece of software was released that will make it very easy for average Iphone users to crack applications that they have purchased from the AppStore. To varying degrees developers are in an uproar about this and are beginning to have discussions on how best to battle this outrage.<br /><br />This particular cracking software, ( I am purposely not going to mention the name ), will do for app cracking what napster did for music piracy. The average person will start to see it as a normal means of attaining these applications.<br /><br />But all is not lost. Currently there are ways of detecting if your application has been cracked and there are many discussions starting around what to do in the case that your application detects that it has been cracked. Most of these discussions result in 'messing' with the user. Randomly crashing and reporting the user to apple are a few of these ideas.<br /><br />I want to encourage all developers to avoid these types of punitive action. It will only end in heart ache and wasted cycles. Software piracy has been around for a long time and will continue to evolve from where it is today. It is not a war won by indie developers. We have too little time and too many features to implement.<br /><br />So what can we do? Try to convert these users into paying customers. Treat these cracked apps as "Lite" versions and use the typical approaches to try and get them to pay using one of these methods:<br /><br /><ul><li>Put ads at the top of a cracked app</li><li>Detect when a user has opened the app more that five times and prompt them to go to the AppStore and purchase the app</li><li>Remove some features from the application when it has been cracked and let the user know.</li><li>Set timer that will turn the application off<br /></li></ul>Many people have been asking Apple to implement try before you buy support into the app store. I think that this is exactly what the crackers are giving us.<br /><br />Don't take it personally, don't feel threatened, this can be an opportunity.Davehttp://www.blogger.com/profile/16335253725087209777noreply@blogger.com0tag:blogger.com,1999:blog-1176137253456608647.post-49684513890815831722009-01-26T21:27:00.001-08:002009-01-27T12:52:42.880-08:00Follow over 100 Iphone Developers on Twitter<a href="http://twitter.com/timhaines">@timhaines</a> put out a call today for all Iphone developers that tweet to put there info into a google spreadsheet. Currently the list is over 160 developers and I thought I would be crazy and follow all of them.<br /><br />Coming from the Rails world I thought would do the right thing and DRY it up with a little script. So little it will fit right here for the world to grab:<br /><br /><pre class="textmate-source"><span class="source source_ruby"><span class="meta meta_require meta_require_ruby"><span class="keyword keyword_other keyword_other_special-method keyword_other_special-method_ruby">require</span> <span class="string string_quoted string_quoted_double string_quoted_double_ruby"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby">"</span>rubygems<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby">"</span></span></span><br /><span class="meta meta_require meta_require_ruby"><span class="keyword keyword_other keyword_other_special-method keyword_other_special-method_ruby">require</span> <span class="string string_quoted string_quoted_double string_quoted_double_ruby"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby">"</span>google_spreadsheet<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby">"</span></span></span><br /><span class="meta meta_require meta_require_ruby"><span class="keyword keyword_other keyword_other_special-method keyword_other_special-method_ruby">require</span> <span class="string string_quoted string_quoted_single string_quoted_single_ruby"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby">'</span>twitter<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby">'</span></span></span><br /><br />google_user <span class="keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby">=</span> <span class="string string_quoted string_quoted_double string_quoted_double_ruby"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby">"</span>XXXXXXXX<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby">"</span></span><br />google_pw <span class="keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby">=</span> <span class="string string_quoted string_quoted_double string_quoted_double_ruby"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby">"</span>XXXXXX<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby">"</span></span><br />twitter_user <span class="keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby">=</span> <span class="string string_quoted string_quoted_double string_quoted_double_ruby"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby">"</span>XXXXXXX<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby">"</span></span><br />twitter_pw <span class="keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby">=</span> <span class="string string_quoted string_quoted_double string_quoted_double_ruby"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby">"</span>XXXXXXX<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby">"</span></span><br /><br />session <span class="keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby">=</span> <span class="support support_class support_class_ruby">GoogleSpreadsheet</span><span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby">.</span>login<span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">(</span>google_user<span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby">,</span> google_pw<span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">)</span><br /><br />ws <span class="keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby">=</span> session<span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby">.</span>spreadsheet_by_key<span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">(</span><span class="string string_quoted string_quoted_double string_quoted_double_ruby"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby">"</span>p3LA_Q08eM-VAAyq03ZSjYQ<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby">"</span></span><span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">)</span><span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby">.</span>worksheets<span class="punctuation punctuation_section punctuation_section_array punctuation_section_array_ruby">[</span><span class="constant constant_numeric constant_numeric_ruby">0</span><span class="punctuation punctuation_section punctuation_section_array punctuation_section_array_ruby">]</span><br /><br />base <span class="keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby">=</span> <span class="support support_class support_class_ruby">Twitter</span><span class="punctuation punctuation_separator punctuation_separator_other punctuation_separator_other_ruby">::</span><span class="support support_class support_class_ruby">Base</span><span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby">.</span><span class="keyword keyword_other keyword_other_special-method keyword_other_special-method_ruby">new</span><span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">(</span>twitter_user<span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby">,</span> twitter_pw<span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">)</span><br /><br /><span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">(</span><span class="constant constant_numeric constant_numeric_ruby">1</span><span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby">..</span><span class="constant constant_numeric constant_numeric_ruby">1000</span><span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">)</span><span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby">.</span>each <span class="keyword keyword_control keyword_control_start-block keyword_control_start-block_ruby">do </span><span class="punctuation punctuation_separator punctuation_separator_variable punctuation_separator_variable_ruby">|</span><span class="variable variable_other variable_other_block variable_other_block_ruby">row</span><span class="punctuation punctuation_separator punctuation_separator_variable punctuation_separator_variable_ruby">|</span><br /> url <span class="keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby">=</span> ws<span class="punctuation punctuation_section punctuation_section_array punctuation_section_array_ruby">[</span>row<span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby">,</span><span class="constant constant_numeric constant_numeric_ruby">2</span><span class="punctuation punctuation_section punctuation_section_array punctuation_section_array_ruby">]</span><br /> matched_user <span class="keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby">=</span> url<span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby">.</span>match<span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">(</span><span class="string string_regexp string_regexp_classic string_regexp_classic_ruby"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_ruby">/</span>http:<span class="constant constant_character constant_character_escape constant_character_escape_ruby">\/\/.*</span>twitter.com<span class="constant constant_character constant_character_escape constant_character_escape_ruby">\/</span><span class="string string_regexp string_regexp_group string_regexp_group_ruby"><span class="punctuation punctuation_definition punctuation_definition_group punctuation_definition_group_ruby">(</span>.*<span class="punctuation punctuation_definition punctuation_definition_group punctuation_definition_group_ruby">)</span></span><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_ruby">/</span></span><span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">)</span><br /> <span class="keyword keyword_control keyword_control_pseudo-method keyword_control_pseudo-method_ruby">next</span> <span class="keyword keyword_control keyword_control_ruby">unless</span> matched_user<br /> matched_user <span class="keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby">=</span> matched_user<span class="punctuation punctuation_section punctuation_section_array punctuation_section_array_ruby">[</span><span class="constant constant_numeric constant_numeric_ruby">1</span><span class="punctuation punctuation_section punctuation_section_array punctuation_section_array_ruby">]</span><br /><br /> puts <span class="string string_quoted string_quoted_double string_quoted_double_ruby"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby">"</span>Attmepting to follow <span class="source source_ruby source_ruby_embedded source_ruby_embedded_source"><span class="punctuation punctuation_section punctuation_section_embedded punctuation_section_embedded_ruby">#{</span>matched_user<span class="punctuation punctuation_section punctuation_section_embedded punctuation_section_embedded_ruby">}</span></span><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby">"</span></span><br /><br /> <span class="keyword keyword_control keyword_control_ruby">begin</span><br /> base<span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby">.</span>create_friendship<span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">(</span>matched_user<span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">)</span><br /> puts <span class="string string_quoted string_quoted_double string_quoted_double_ruby"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby">"</span>success<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby">"</span></span><br /> <span class="keyword keyword_control keyword_control_ruby">rescue</span><br /> puts <span class="string string_quoted string_quoted_double string_quoted_double_ruby"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby">"</span>******* Failed <span class="source source_ruby source_ruby_embedded source_ruby_embedded_source"><span class="punctuation punctuation_section punctuation_section_embedded punctuation_section_embedded_ruby">#{</span><span class="variable variable_other variable_other_readwrite variable_other_readwrite_global variable_other_readwrite_global_pre-defined variable_other_readwrite_global_pre-defined_ruby"><span class="punctuation punctuation_definition punctuation_definition_variable punctuation_definition_variable_ruby">$</span>!</span><span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby">.</span>message<span class="punctuation punctuation_section punctuation_section_embedded punctuation_section_embedded_ruby">}</span></span><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby">"</span></span><br /> <span class="keyword keyword_control keyword_control_ruby">end</span><br /><span class="keyword keyword_control keyword_control_ruby">end</span></span></pre>You can grab the code from github at <a href="http://github.com/digidigo/iphone-dev-tweeters-/tree/master">http://github.com/digidigo/iphone-dev-tweeters-/tree/master</a><br /><br />You will need to grab a few ruby gems to make this work. Check out the google spreadsheet gem at <a href="http://github.com/gimite/google-spreadsheet-ruby/tree/master">http://github.com/gimite/google-spreadsheet-ruby/tree/master</a> . And then the twitter gem at <a href="http://twitter.rubyforge.org/rdoc/">http://twitter.rubyforge.org/rdoc/</a><br /><br />So go out there and be crazy like me and see what all of us Iphone devs are tweeting about.<br /><br /><br />If you get an error like this:<br /><br />ERROR: Error installing twitter: echoe requires RubyGems version >= 1.2<br /><br />You will need to update your rubygems. <span style="font-style: italic;"> gem update --system</span> should do the trick.Davehttp://www.blogger.com/profile/16335253725087209777noreply@blogger.com15tag:blogger.com,1999:blog-1176137253456608647.post-13651371801199159632009-01-20T20:48:00.001-08:002009-01-20T20:56:51.561-08:00Apple approves Iphone app in under 2 days!!<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjfxYJOzWsRxXyCkr3gP5WYF4ymMPd0IEF9HTea1X8_rwcZgBOpSgeRaxwycIEQCIzkG9lZDfrebtUIAlbFO8XeRALP7tEuztiKkrz9-8QKvh9117aIvNTvXvbZQWLLRgUprdOzPXajDcs/s1600-h/Picture+23.png"><img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 214px; height: 320px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjfxYJOzWsRxXyCkr3gP5WYF4ymMPd0IEF9HTea1X8_rwcZgBOpSgeRaxwycIEQCIzkG9lZDfrebtUIAlbFO8XeRALP7tEuztiKkrz9-8QKvh9117aIvNTvXvbZQWLLRgUprdOzPXajDcs/s320/Picture+23.png" alt="" id="BLOGGER_PHOTO_ID_5293604475438873106" border="0" /></a>I have to say those guys at the App Store are working hard. We are up to 15000 apps and there are 3 new farting apps a day. Those guys are cranking.<br /><br />And yet I have never noticed a slow down in app approval time. Most of the time a new app for me takes about 4 days and updates get approved in 3 or 4 days.<br /><br />But today I got a big suprise, <a href="http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=302890805&mt=8">Chatterbox a paper fortune teller</a> hit the store in under 40 hours. You gotta love that.<br /><br />Thanks guys!!<br /><br /><br />Here is the store text about Chatterbox --- My wife loves this app.<br /><br />Chatterbox is a fortune teller or a cootie catcher (sometimes called a scrunchie and a chatterbox in Australia) for your iPhone. It is an origami device used in fortune-telling games. Predicting your future using paper fortune tellers was a common pastime during the grade school years. Paper fortune tellers magically told who liked you, who hated you, if you would be rich some day, and even answered questions.<br /><br />We've made a fortune teller that can be customized by anyone. Included are a few sets, but there is room for you to make many more.<br /><br />Example of one of the included sets:<br /><br />DISASTROUS DATING FORTUNE SET (Quick ice breaker for those with a sense of humor)<br /><br />1. I lost my number, can I have yours?<br />2. Do you believe in love at first sight, or should I walk past you again?<br />3. Are you a parking ticket? (What?) You got fine written all over you.<br />4. Does my breath smell okay?<br />5. Is your dad a thief or something? Because someone stole the stars and put them in your eyes!<br />6. Here's 20$. Drink until I am really good looking, then come talk to me.<br />7. You sure have a great looking tooth.<br />8. You want me, I can smell it.<br /><br /><br /><br />The game could be used to cheer someone up (by writing a bunch of encouraging fortunes), to play a trick on someone (by writing all bad fortunes), to help with dating by perhaps writing eight fortunes that all tell the person you're interested in that they are "meant to dance with you". It's up to you. The game is a common pastime for kids in school but, make up your own sets of fortunes and you'll find that the fun of playing with a fortune teller doesn't diminish just because you're no longer in school.<br /><br />How to Play:<br /><br />A player asks a question, then chooses a color. The chatterbox shuffles, the player chooses a number and after the final shuffle the player chooses a final number. Their fortune or answer to their question is then revealed.Davehttp://www.blogger.com/profile/16335253725087209777noreply@blogger.com0tag:blogger.com,1999:blog-1176137253456608647.post-30072250716738346382009-01-02T19:44:00.000-08:002009-01-02T20:07:46.120-08:00Bug in App Store Causes Apps to DisappearA few app developers are reporting that their apps have disappeared from the App store. This happened to one of my apps, <a href="http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=290783429&mt=8">WristPop Coin Toss </a>, and has happened to one other app that I know of, <a href="http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=294280588&mt=8">Kana</a>. Customers attempting to purchase one of these applications were greeted with a message that the app is no longer available on the store.<br /><br />The bug that is causing this is in the Itunes Connect Management Application and can happen after changing the price of an application. Here is a screen grab of the pricing tab<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhhKoJOIgV1QYIvFunkorgeN41hxo2K5JngOYAYlnUVtAZtHo6jPxRNqrBauoMxGiaebKUnOiizc59CJIfwVVuVk68JH0nb37FzkOXahGjh1YR28pekyGNXrebbBqAWyWmfpFnS-NvWu0E/s1600-h/Picture+12.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 312px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhhKoJOIgV1QYIvFunkorgeN41hxo2K5JngOYAYlnUVtAZtHo6jPxRNqrBauoMxGiaebKUnOiizc59CJIfwVVuVk68JH0nb37FzkOXahGjh1YR28pekyGNXrebbBqAWyWmfpFnS-NvWu0E/s320/Picture+12.png" alt="" id="BLOGGER_PHOTO_ID_5286911457196890754" border="0" /></a><br />Notice that the availability date for this application is December 22nd 2009. If you hit save at this point your application will disappear from the store for almost a year. This is really a rookie HTML mistake, for some reason the current year is not in the select list and so the browser selects the first year in the list.<br /><br />All is not lost. If you made this mistake or you need to update your price for an application, you can select today's date from the drop downs and hit save. You application will reappear in the store within an hour. Your release date will not change.<br /><br />This happened to both of the apps mentioned above after the end of the <a href="http://www.newyearappblowout.com/">New Year's App Blowout, </a>which was great fun!<br /><br />A special thanks to <a href="http://twitter.com/majicDave">macgicDave</a> for passing this on and <a href="http://www.twitter.com">twitter</a> of course for bringing it into my ambient field.Davehttp://www.blogger.com/profile/16335253725087209777noreply@blogger.com0tag:blogger.com,1999:blog-1176137253456608647.post-36111272408709245042008-10-23T09:07:00.000-07:002008-10-23T09:33:46.248-07:00Apple approves Iphone app in under 10 hours!!I have been working on a app with Michael from <a href="http://www.onespokenimage.com/">SpokenImage</a> . The Signing Bowl Alarm Clock.<br /><div style="text-align: center;"><br /><span style="font-size:130%;">SUZU Wake Me Gently</span><br /><br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://phobos.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=294420813&mt=8"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 320px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjKsMP09c-QR2ffsZQc2ThVucKZ9KWJbvMbFNqg4mc4QHhC2cXejTkSnyf_s8ElAQj7GKsr9eoRw2nS0r5L8B8G3Dryo41edb1Ruaz_CzBNlF7BXGlJv0GN3aZO1RjOuHJUalYbMXxmxlM/s320/suzu_512.jpg" alt="" id="BLOGGER_PHOTO_ID_5260385933521860594" border="0" /></a><br /><div style="text-align: left;">It is pretty cool way to wake up. The thing that amazed me though is that Apple approved this app in under 10 hours. My previous appliction WristPop Coin Toss took 1 week to be approved and its successor PrezFlip is still in review limbo after 3 weeks, even with the election only 2 weeks away.<br /><br />So I am not sure what this means, maybe:<br /><ul><li>SUZU is unique enough that it got to the front of the line.</li><li>There aren't as many apps in the Utility Category</li><li>The App Store Reviewers have a lot of latitude and are very subjective</li></ul>I haven't done much research into what other peoples experience is , but I will say that my move to android is now on hold. <br /></div></div>Davehttp://www.blogger.com/profile/16335253725087209777noreply@blogger.com2tag:blogger.com,1999:blog-1176137253456608647.post-8553928158942009582008-10-16T09:35:00.001-07:002008-10-16T09:59:49.720-07:00There is no Gatekeeper at the App Store and why I am considering moving to AndroidA few weeks ago, during all the noise about PodCaster getting rejected from the App Store, I was vehemently defending Apple's Gatekeeper approach. <a href="http://twitter.com/aniero">Nathan</a> was talking to me about how Apple was shooting itself in the foot because developers won't stand for that kind of slap in the face, and it will deter people from developing apps for the Iphone. I stood up for Apple's right to protect the quality of the market place and I believed that developers would still put creative efforts into building applications for the Iphone because it will be the best and most profitable marketplace.<br /><br />Today I find myself changing my mind, but for a reason I didn't think of at the time. My original argument came mostly from the belief that people are going to follow the money. And since the Itunes store is going to be the best show in town, people will follow Steve wherever he wants us to go. That is what is known as being financially engaged, and that is only 1/2 the equation. The other half and prone to wild swings of the imagination is emotional engagement.<br /><br />What I realized, while I wait for my next "free" app to come out of "In review", is that there really isn't a Gatekeeper at the App Store. There is just a gate, and outside that gate is a crowd of nameless, faceless developers wondering what it is like on the Inside. Occasionally the gate opens and hand comes out and grabs an App out of one of these developers hands and takes it inside. You see, even if our Apps make it into the store, we still don't get to know what is going on "Inside", we are not really invited to the party , we are not Steve's guests, we are the entertainment.<br /><br />And so, since<br /><ul><li>There is no Gatekeeper to talk to</li><li>There are no guests coming out and telling us what it is like on the "Inside"<br /></li><li>There is only a black hole for my emails regarding the persistent "In Review" status</li></ul>I find my emotional engagement waning and I start downloading the Android SDK. Because even though Google isn't going to protect the marketplace and make us all rich. At least we will be poor together and the long tail will at least talk to us and tell us what we are doing wrong.<br /><br />So , Steve, my simple advice to you. <br /><ul><li>Hire some people to at least respond to emails regarding the review process</li><li>Create some more states for apps "In Review" like "pending" or "might suck" or "cool"</li><li>Create the "Reject Store" where all the rejected or pending apps can at least find an audience</li></ul>I the mean time if anyone wants an "Ad-Hoc" version of the<a href="http://www.gidigo.com"> McCain Obama Coin Toss</a> let me know. I would love some feedback on it before the election is over. I know it is silly but that is the point.Davehttp://www.blogger.com/profile/16335253725087209777noreply@blogger.com0tag:blogger.com,1999:blog-1176137253456608647.post-24769203592533054722008-10-09T13:09:00.000-07:002008-10-09T13:25:26.579-07:00Cracking is the best form of flatteryAbout a month ago I created and launched my first Iphone app, WristPop Coin Toss. <a href="http://phobos.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=290783429&mt=8&v0=WWW-NAUS-ITUHOME-NEWAPPLICATIONS">WristPop Coin Toss</a> is an app that does exactly what it sounds like. Pop your wrist and watch simulated Coin Toss. Pop your wrist harder and the coin will go higher and spin faster. It is complete with sound effects and 3Dish animations. You can even chose different coins. <br /><br />I am biased of course but it is by far the best coin simulation on the Iphone.<br /><br /><div style="text-align: right;"><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://www.gidigo.com/images/wristpop.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 188px; height: 354px;" src="http://www.gidigo.com/images/wristpop.png" alt="" border="0" /></a><br /></div><br /><br />The journey has been an interesting one , learning objective-c, learning the Iphone SDK, waiting while my application was in review , getting feedback from users in Croatia.<br /><br />And now it has all paid off, someone has cracked the binary and made it available on the net for download. Now I know that I have created something of eternal value and can go back to my day job. Thanks Crackers, I see you efforts as a true form of appreciation.<br /><br />Stay tuned for the McCain - Obama Coin Toss....Davehttp://www.blogger.com/profile/16335253725087209777noreply@blogger.com0tag:blogger.com,1999:blog-1176137253456608647.post-11395176925814098142008-08-21T14:15:00.000-07:002008-08-21T14:29:35.922-07:00SEO - Nofollow links by default in RailsI have been learning quit a bit about SEO these days. And one thing that I didn't realize is that "link juice" leaks from page to page. So in order to conserve you link juice you want to very carefully choose which pages should be the recipient of this precious juice. This actually went against my intuition which was to encourage the "bots" to follow every link that I have on my site.<br /><br />Since we already have a pretty complex site with many call to link_to, I decided to tell the "bots" to not follow links by default. This is done by adding the "rel=nofollow" attribute to you anchor tags, in rails this is handled by the call to link_to. This can be accomplished by overriding link_to in application_helper:<br /><br /><pre class="textmate-source"><span class='linenum'> 1</span> <span class="source source_ruby"> <span class="meta meta_function meta_function_method meta_function_method_with-arguments meta_function_method_with-arguments_ruby"><span class="keyword keyword_control keyword_control_def keyword_control_def_ruby">def</span> <span class="entity entity_name entity_name_function entity_name_function_ruby">link_to</span><span class="punctuation punctuation_definition punctuation_definition_parameters punctuation_definition_parameters_ruby">(</span><span class="variable variable_parameter variable_parameter_function variable_parameter_function_ruby">name<span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby">,</span> options<span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby">,</span> html_options <span class="keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby">=</span> <span class="punctuation punctuation_section punctuation_section_scope punctuation_section_scope_ruby">{}</span></span><span class="punctuation punctuation_definition punctuation_definition_parameters punctuation_definition_parameters_ruby">)</span></span> <br /><span class='linenum'> 2</span> <span class="keyword keyword_control keyword_control_ruby">if</span><span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">(</span> rel <span class="keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby">=</span> <span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">(</span>html_options<span class="punctuation punctuation_section punctuation_section_array punctuation_section_array_ruby">[</span><span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"><span class="punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby">:</span>rel</span><span class="punctuation punctuation_section punctuation_section_array punctuation_section_array_ruby">]</span> <span class="keyword keyword_operator keyword_operator_logical keyword_operator_logical_ruby">||</span> html_options<span class="punctuation punctuation_section punctuation_section_array punctuation_section_array_ruby">[</span><span class="string string_quoted string_quoted_double string_quoted_double_ruby"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby">"</span>rel<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby">"</span></span><span class="punctuation punctuation_section punctuation_section_array punctuation_section_array_ruby">]</span><span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">)</span> <span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">)</span><br /><span class='linenum'> 3</span> foo <span class="keyword keyword_control keyword_control_ruby">if</span><span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">(</span><span class="variable variable_other variable_other_constant variable_other_constant_ruby">RAILS_ENV</span> <span class="keyword keyword_operator keyword_operator_comparison keyword_operator_comparison_ruby">==</span> <span class="string string_quoted string_quoted_single string_quoted_single_ruby"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby">'</span>development<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby">'</span></span><span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">)</span><br /><span class='linenum'> 4</span> <span class="keyword keyword_control keyword_control_ruby">elsif</span><span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">(</span> <span class="keyword keyword_operator keyword_operator_logical keyword_operator_logical_ruby">!</span><span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">(</span>follow_link?<span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">(</span>options<span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby">,</span> html_options<span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">)))</span><br /><span class='linenum'> 5</span> html_options<span class="punctuation punctuation_section punctuation_section_array punctuation_section_array_ruby">[</span><span class="string string_quoted string_quoted_double string_quoted_double_ruby"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby">"</span>rel<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby">"</span></span><span class="punctuation punctuation_section punctuation_section_array punctuation_section_array_ruby">]</span> <span class="keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby">=</span> <span class="string string_quoted string_quoted_double string_quoted_double_ruby"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby">"</span>nofollow<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby">"</span></span><br /><span class='linenum'> 6</span> <span class="keyword keyword_control keyword_control_ruby">end</span><br /><span class='linenum'> 7</span> <span class="keyword keyword_control keyword_control_pseudo-method keyword_control_pseudo-method_ruby">super</span><span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">(</span>name<span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby">,</span> options<span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby">,</span> html_options<span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">)</span><br /><span class='linenum'> 8</span> <span class="keyword keyword_control keyword_control_ruby">end</span></span></pre><br /><br /><em> Ignore that 'foo' part, I just wanted to blow up if we are allready using the rel attribute somewhere in the codebase </em><br /><br />Now you can define the method follow_link? to be whatever the rules are for you domain.<br /><br /><pre class="textmate-source"><span class='linenum'> 1</span> <span class="source source_ruby"> <span class="meta meta_function meta_function_method meta_function_method_with-arguments meta_function_method_with-arguments_ruby"><span class="keyword keyword_control keyword_control_def keyword_control_def_ruby">def</span> <span class="entity entity_name entity_name_function entity_name_function_ruby">follow_link?</span><span class="punctuation punctuation_definition punctuation_definition_parameters punctuation_definition_parameters_ruby">(</span><span class="variable variable_parameter variable_parameter_function variable_parameter_function_ruby">options<span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby">,</span> html_options</span><span class="punctuation punctuation_definition punctuation_definition_parameters punctuation_definition_parameters_ruby">)</span></span><br /><span class='linenum'> 2</span> <span class="keyword keyword_control keyword_control_pseudo-method keyword_control_pseudo-method_ruby">return</span> <span class="constant constant_language constant_language_ruby">true</span> <span class="keyword keyword_control keyword_control_ruby">if</span> html_options<span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby">.</span>delete<span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">(</span><span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"><span class="punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby">:</span>follow</span><span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">)</span><br /><span class='linenum'> 3</span> <br /><span class='linenum'> 4</span> url <span class="keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby">=</span> url_for<span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">(</span>options<span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">)</span><br /><span class='linenum'> 5</span> <span class="keyword keyword_control keyword_control_ruby">if</span><span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">(</span>url<span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby">.</span>match<span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">(</span><span class="string string_regexp string_regexp_classic string_regexp_classic_ruby"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_ruby">/</span><span class="string string_regexp string_regexp_group string_regexp_group_ruby"><span class="punctuation punctuation_definition punctuation_definition_group punctuation_definition_group_ruby">(</span>.*?show.*?<span class="punctuation punctuation_definition punctuation_definition_group punctuation_definition_group_ruby">)</span></span>|<span class="string string_regexp string_regexp_group string_regexp_group_ruby"><span class="punctuation punctuation_definition punctuation_definition_group punctuation_definition_group_ruby">(</span>news$<span class="punctuation punctuation_definition punctuation_definition_group punctuation_definition_group_ruby">)</span></span>|<span class="string string_regexp string_regexp_group string_regexp_group_ruby"><span class="punctuation punctuation_definition punctuation_definition_group punctuation_definition_group_ruby">(</span>browse$<span class="punctuation punctuation_definition punctuation_definition_group punctuation_definition_group_ruby">)</span></span>|<span class="string string_regexp string_regexp_group string_regexp_group_ruby"><span class="punctuation punctuation_definition punctuation_definition_group punctuation_definition_group_ruby">(</span>page=<span class="constant constant_character constant_character_escape constant_character_escape_ruby">\d</span>+<span class="punctuation punctuation_definition punctuation_definition_group punctuation_definition_group_ruby">)</span></span>$<span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_ruby">/</span></span><span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">))</span><br /><span class='linenum'> 6</span> <span class="keyword keyword_control keyword_control_pseudo-method keyword_control_pseudo-method_ruby">return</span> <span class="constant constant_language constant_language_ruby">true</span><br /><span class='linenum'> 7</span> <span class="keyword keyword_control keyword_control_ruby">end</span><br /><span class='linenum'> 8</span> <span class="keyword keyword_control keyword_control_pseudo-method keyword_control_pseudo-method_ruby">return</span> <span class="constant constant_language constant_language_ruby">false</span><br /><span class='linenum'> 9</span> <span class="keyword keyword_control keyword_control_ruby">end</span></span></pre><br /><br />Now I specifically know which pages are important for the "bots" to index and the precious juice is being preserved.Davehttp://www.blogger.com/profile/16335253725087209777noreply@blogger.com0tag:blogger.com,1999:blog-1176137253456608647.post-62268893198436210572008-08-08T10:19:00.000-07:002008-08-08T10:32:56.861-07:00Bonus Screencast for Rails on FacebookGeoffery, from PeepCode, helped us put together a screencast to accompany the Rails On Facebook PeepCode PDF. It covers the specific details that you will need to setup the sample application Ruby Footprints. Check it out <a href="http://peepcode.com/products/rails-on-facebook">Rails on Facebook.</a>Davehttp://www.blogger.com/profile/16335253725087209777noreply@blogger.com0tag:blogger.com,1999:blog-1176137253456608647.post-21882144543118534762008-07-30T19:51:00.000-07:002008-07-31T20:48:16.951-07:00Rails on Facebook Book is out!<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://peepcode.com/system/uploads/2008/facebook-cover.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px;" src="https://peepcode.com/system/uploads/2008/facebook-cover.png" border="0" alt="" /></a><br />Time to announce the PeepCode book <a href="http://peepcode.com/products/rails-on-facebook">Rails on Facebook</a>. It is a no-nonsense, full of code , comprehensive PDF book on developing Facebook applications with the Rails Plugin <a href="http://github.com/mmangino/facebooker/tree/master">Facebooker.</a><br /><br /><a href="http://shanesbrain.net">Shane</a> and I have been working on it over the last few months and made sure that it covers a bunch of the latest design and platform changes.Davehttp://www.blogger.com/profile/16335253725087209777noreply@blogger.com1tag:blogger.com,1999:blog-1176137253456608647.post-11254971410628395012008-07-11T09:34:00.000-07:002008-07-11T09:44:33.828-07:00Add Custom Conditions to your Rails RoutesAt <a href="http://www.meetingwave.com">MeetingWave</a> we support both a <a href="http://apps.facebook.com/meetingwave">Social Network Application </a> and the main Web Application. On occasion we need to know which context we are in in order to direct the request to the correct controller/action pair. What we want is to be able to have a route that looks like this:<br /><br /><em> map.facebook_my_profile 'myprofile', :controller => 'member_profiles', :action => 'import_facebook_profile', <b> :conditions => {:context => "social_network" }</b><br /></em> <br /><br /><br />Currently, at least as of Rails 2.0 , the only condition that you can use is the request type ( e.g. <em> :conditions => {:method => "get"}</em>) . Maybe things are different in 2.1, we haven't made the plunge yet.<br /><br />Anyway here is some code, that I coerced from the Facebooker source, that will enable the route above to work:<br /><br /><pre class="textmate-source"><span class="source source_ruby"><span class="meta meta_module meta_module_ruby"><span class="keyword keyword_control keyword_control_module keyword_control_module_ruby">module</span> <span class="entity entity_name entity_name_type entity_name_type_module entity_name_type_module_ruby">TTB</span></span><br /><span class="meta meta_module meta_module_ruby"> <span class="keyword keyword_control keyword_control_module keyword_control_module_ruby">module</span> <span class="entity entity_name entity_name_type entity_name_type_module entity_name_type_module_ruby">RouteSetExtensions</span></span><br /> <span class="meta meta_function meta_function_method meta_function_method_with-arguments meta_function_method_with-arguments_ruby"><span class="keyword keyword_control keyword_control_def keyword_control_def_ruby">def</span> <span class="entity entity_name entity_name_function entity_name_function_ruby">self.included</span><span class="punctuation punctuation_definition punctuation_definition_parameters punctuation_definition_parameters_ruby">(</span><span class="variable variable_parameter variable_parameter_function variable_parameter_function_ruby">base</span><span class="punctuation punctuation_definition punctuation_definition_parameters punctuation_definition_parameters_ruby">)</span></span><br /> base<span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby">.</span>alias_method_chain <span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"><span class="punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby">:</span>extract_request_environment</span><span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby">,</span> <span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"><span class="punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby">:</span>context</span><br /> <span class="keyword keyword_control keyword_control_ruby">end</span><br /><br /> <span class="meta meta_function meta_function_method meta_function_method_with-arguments meta_function_method_with-arguments_ruby"><span class="keyword keyword_control keyword_control_def keyword_control_def_ruby">def</span> <span class="entity entity_name entity_name_function entity_name_function_ruby">extract_request_environment_with_context</span><span class="punctuation punctuation_definition punctuation_definition_parameters punctuation_definition_parameters_ruby">(</span><span class="variable variable_parameter variable_parameter_function variable_parameter_function_ruby">request</span><span class="punctuation punctuation_definition punctuation_definition_parameters punctuation_definition_parameters_ruby">)</span></span><br /> env <span class="keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby">=</span> extract_request_environment_without_context<span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">(</span>request<span class="punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby">)</span><br /> env<span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby">.</span>merge <span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"><span class="punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby">:</span>context</span> <span class="punctuation punctuation_separator punctuation_separator_key-value">=></span> request<span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby">.</span>parameters<span class="punctuation punctuation_section punctuation_section_array punctuation_section_array_ruby">[</span><span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"><span class="punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby">:</span>context</span><span class="punctuation punctuation_section punctuation_section_array punctuation_section_array_ruby">]</span><br /> <span class="keyword keyword_control keyword_control_ruby">end</span><br /> <span class="keyword keyword_control keyword_control_ruby">end</span> <br /><span class="keyword keyword_control keyword_control_ruby">end</span><br /><br /><span class="meta meta_class meta_class_ruby"><span class="keyword keyword_control keyword_control_class keyword_control_class_ruby">class</span> <span class="entity entity_name entity_name_type entity_name_type_class entity_name_type_class_ruby">ActionController::Routing::Route</span></span><br /> <span class="meta meta_function meta_function_method meta_function_method_without-arguments meta_function_method_without-arguments_ruby"><span class="keyword keyword_control keyword_control_def keyword_control_def_ruby">def</span> <span class="entity entity_name entity_name_function entity_name_function_ruby">recognition_conditions_with_context</span></span><br /> defaults <span class="keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby">=</span> recognition_conditions_without_context <br /> defaults <span class="keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_augmented keyword_operator_assignment_augmented_ruby"><<</span> <span class="string string_quoted string_quoted_double string_quoted_double_ruby"><span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby">"</span> env[:context] == conditions[:context] <span class="punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby">"</span></span> <span class="keyword keyword_control keyword_control_ruby">if</span> conditions<span class="punctuation punctuation_section punctuation_section_array punctuation_section_array_ruby">[</span><span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"><span class="punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby">:</span>context</span><span class="punctuation punctuation_section punctuation_section_array punctuation_section_array_ruby">]</span><br /> defaults<br /> <span class="keyword keyword_control keyword_control_ruby">end</span><br /> alias_method_chain <span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"><span class="punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby">:</span>recognition_conditions</span><span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby">,</span> <span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"><span class="punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby">:</span>context</span><br /><span class="keyword keyword_control keyword_control_ruby">end</span><br /><br /><span class="support support_class support_class_ruby">ActionController</span><span class="punctuation punctuation_separator punctuation_separator_other punctuation_separator_other_ruby">::</span><span class="support support_class support_class_ruby">Routing</span><span class="punctuation punctuation_separator punctuation_separator_other punctuation_separator_other_ruby">::</span><span class="support support_class support_class_ruby">RouteSet</span><span class="punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby">.</span>send <span class="constant constant_other constant_other_symbol constant_other_symbol_ruby"><span class="punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby">:</span>include</span><span class="punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby">,</span> <span class="support support_class support_class_ruby">TTB</span><span class="punctuation punctuation_separator punctuation_separator_other punctuation_separator_other_ruby">::</span><span class="variable variable_other variable_other_constant variable_other_constant_ruby">RouteSetExtensions</span></span></pre><br /><br /><br /><br />Someday I will get my Textmate code highlighting to work in here, sorry about that.Davehttp://www.blogger.com/profile/16335253725087209777noreply@blogger.com0tag:blogger.com,1999:blog-1176137253456608647.post-40708804527568366232008-07-08T15:34:00.000-07:002008-07-08T16:02:35.351-07:00Facebooker with Bebo SupportI think I promised this quite a few months ago and now with the wonders of GitHub I have completed it.<br /><br />I <a href="http://github.com/digidigo/facebooker/tree/master">forked</a> the main <a href="http://github.com/mmangino/facebooker/tree/master">repo</a> from mike and added support not only for Bebo but for running multiple Facebook apps within one Rails instance. The fork is hopefully only temporary as I think Mike will push this into the main repo once it is confiremed that it doesn't break backward compatibility. Anyone out there running on Bebo and want to kick the tires for me? If so you can grab it from :<br /><br /><a href="http://github.com/digidigo/facebooker/tree/master">http://github.com/digidigo/facebooker/tree/master</a><br /><br />Basically how it works is that you can add any number of config options to your facebooker.yml file now mine looks like this:<br /><br /><pre class="textmate-source"><span class="source source_yaml"><span class="meta meta_tag meta_tag_yaml"><span class="entity entity_name entity_name_tag entity_name_tag_yaml">development</span><span class="punctuation punctuation_separator punctuation_separator_key-value punctuation_separator_key-value_yaml">:</span><br /></span> <span class="string string_unquoted string_unquoted_yaml"><span class="entity entity_name entity_name_tag entity_name_tag_yaml">api_key<span class="punctuation punctuation_separator punctuation_separator_key-value punctuation_separator_key-value_yaml">:</span></span> <span class="string string_unquoted string_unquoted_yaml">b9f5233d4b7f8216253c0d27f60603ed</span></span><br /> <span class="string string_unquoted string_unquoted_yaml"><span class="entity entity_name entity_name_tag entity_name_tag_yaml">secret_key<span class="punctuation punctuation_separator punctuation_separator_key-value punctuation_separator_key-value_yaml">:</span></span> <span class="string string_unquoted string_unquoted_yaml">XXXXXXX</span></span><br /> <span class="string string_unquoted string_unquoted_yaml"><span class="entity entity_name entity_name_tag entity_name_tag_yaml">canvas_page_name<span class="punctuation punctuation_separator punctuation_separator_key-value punctuation_separator_key-value_yaml">:</span></span> <span class="string string_unquoted string_unquoted_yaml">mwavedev</span></span><br /> <span class="string string_unquoted string_unquoted_yaml"><span class="entity entity_name entity_name_tag entity_name_tag_yaml">callback_url<span class="punctuation punctuation_separator punctuation_separator_key-value punctuation_separator_key-value_yaml">:</span></span> <span class="string string_unquoted string_unquoted_yaml">http://staging.travelerstable.com:8888</span></span><br /> <span class="string string_unquoted string_unquoted_yaml"><span class="entity entity_name entity_name_tag entity_name_tag_yaml">bebo_api_key<span class="punctuation punctuation_separator punctuation_separator_key-value punctuation_separator_key-value_yaml">:</span></span> <span class="string string_unquoted string_unquoted_yaml">pZwnITIadEri1V0fNPxEMhSen9VBCoRf5jV9</span></span><br /> <span class="string string_unquoted string_unquoted_yaml"><span class="entity entity_name entity_name_tag entity_name_tag_yaml">bebo_secret_key<span class="punctuation punctuation_separator punctuation_separator_key-value punctuation_separator_key-value_yaml">:</span></span> <span class="string string_unquoted string_unquoted_yaml">XXXXXXX</span></span><br /> <span class="string string_unquoted string_unquoted_yaml"><span class="entity entity_name entity_name_tag entity_name_tag_yaml">bebo_canvas_page_name<span class="punctuation punctuation_separator punctuation_separator_key-value punctuation_separator_key-value_yaml">:</span></span> <span class="string string_unquoted string_unquoted_yaml">ttdev</span></span><br /> <span class="string string_unquoted string_unquoted_yaml"><span class="entity entity_name entity_name_tag entity_name_tag_yaml">bebo_adapter<span class="punctuation punctuation_separator punctuation_separator_key-value punctuation_separator_key-value_yaml">:</span></span> <span class="string string_unquoted string_unquoted_yaml">BeboAdapter</span></span><br /> <span class="string string_unquoted string_unquoted_yaml"><span class="entity entity_name entity_name_tag entity_name_tag_yaml">foo_api_key<span class="punctuation punctuation_separator punctuation_separator_key-value punctuation_separator_key-value_yaml">:</span></span> <span class="string string_unquoted string_unquoted_yaml">f688cbe01c465d71e4f9bed26722309a</span></span><br /> <span class="string string_unquoted string_unquoted_yaml"><span class="entity entity_name entity_name_tag entity_name_tag_yaml">foo_secret_key<span class="punctuation punctuation_separator punctuation_separator_key-value punctuation_separator_key-value_yaml">:</span></span> <span class="string string_unquoted string_unquoted_yaml">XXXXXX</span></span><br /> <span class="string string_unquoted string_unquoted_yaml"><span class="entity entity_name entity_name_tag entity_name_tag_yaml">foo_canvas_page_name<span class="punctuation punctuation_separator punctuation_separator_key-value punctuation_separator_key-value_yaml">:</span></span> <span class="string string_unquoted string_unquoted_yaml">sumobaby</span></span><br /> <span class="string string_unquoted string_unquoted_yaml"><span class="entity entity_name entity_name_tag entity_name_tag_yaml">foo_adapter<span class="punctuation punctuation_separator punctuation_separator_key-value punctuation_separator_key-value_yaml">:</span></span> <span class="string string_unquoted string_unquoted_yaml">FacebookAdapter</span></span><br /> <span class="meta meta_tag meta_tag_yaml"><span class="entity entity_name entity_name_tag entity_name_tag_yaml">tunnel</span><span class="punctuation punctuation_separator punctuation_separator_key-value punctuation_separator_key-value_yaml">:</span><br /></span> <span class="meta meta_tag meta_tag_yaml"><span class="entity entity_name entity_name_tag entity_name_tag_yaml">public_host_username</span><span class="punctuation punctuation_separator punctuation_separator_key-value punctuation_separator_key-value_yaml">:</span> <br /></span> <span class="meta meta_tag meta_tag_yaml"><span class="entity entity_name entity_name_tag entity_name_tag_yaml">public_host</span><span class="punctuation punctuation_separator punctuation_separator_key-value punctuation_separator_key-value_yaml">:</span> <br /></span> <span class="constant constant_numeric constant_numeric_yaml"><span class="entity entity_name entity_name_tag entity_name_tag_yaml">public_port<span class="punctuation punctuation_separator punctuation_separator_key-value punctuation_separator_key-value_yaml">:</span></span> 4007</span><br /> <span class="constant constant_numeric constant_numeric_yaml"><span class="entity entity_name entity_name_tag entity_name_tag_yaml">local_port<span class="punctuation punctuation_separator punctuation_separator_key-value punctuation_separator_key-value_yaml">:</span></span> 3000</span></span></pre> <br /><br /><br />Currenlty you need to set all 4 parameters , api_key, secret_key , canvas_page_name and adapter for any additional contexts. The way the code works is that there is a before filter added to the controller that looks at fb_sig_api_key and loads an adapter instance specified by the "#{key_base}_adapter" setting for that api_key.<br /><br />All of the API specific constants have been pulled out of the code base and are available via method on the Facebooker module.<br /><br />For example you call Facebooker.canvas_page_name and you will get the current adapters canvas_page.<br /><br />If you need to load an adapter specifically you call Facebooker.load_adapter(:config_key_base => "foo")<br /><br />All the tests are passing so I think the backward compatibility is fine. And there are new tests for all the adapter specific stuff.Davehttp://www.blogger.com/profile/16335253725087209777noreply@blogger.com8tag:blogger.com,1999:blog-1176137253456608647.post-1258995004133242892008-06-26T13:24:00.000-07:002008-06-26T13:24:01.917-07:00Make your own IM bot in Ruby, and interface it with your Rails app<a href="http://rubypond.com/articles/2008/06/26/make-your-own-im-bot-in-ruby-and-interface-it-with-your-rails-app">Make your own IM bot in Ruby, and interface it with your Rails app</a>: <blockquote>"What about your average Joe on the street, how come they get forced into having to log in to the site to update their data, etc.? Why not provide a means of carrying out simple tasks in an application they probably already have? And so an Instant Messaging interface was designed to send a instruction to a robot, and it’s relatively simple to get setup."</blockquote>I have been thinking a lot lately about providing API's through IM or Email. If you think about it, Unix geeks have interacted with complex systems with three letter commands, manpages and the every helpful -h option on everything. Why not allow users to the same flexibility, because believe it or not, you new fancy web 2.0 application is way simpler than 'ps' or 'top'.Davehttp://www.blogger.com/profile/16335253725087209777noreply@blogger.com0tag:blogger.com,1999:blog-1176137253456608647.post-90745902569496009382008-06-24T08:52:00.000-07:002008-12-09T19:38:58.111-08:00GitHub is Freaking Me Out!!<div style="text-align: center;"><span class="Apple-style-span" style="color:#0000EE;"><span class="Apple-style-span" style="text-decoration: underline;"><br /></span></span></div>I found myself perplexed and a little concerned last night while searching for the latest and greatest Rails authentication plugin. One of the general issues that I have with the current PlugScape for Rails is that it is difficult to determine quality and recency. I was overjoyed last night after finding an authentication plugin with OpenId support!! Yahoo!! And it had even been updated in May of this year!! But then I noticed something:<div><br /></div><div><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhMZzKTqcEmLrMkmj-Qyzmk45ddXO9IUcr9eC1HsjiKZXtOHNXra4mzEHEcs2fTSfn8oDjtkkQ18W2-It3tTCLX80wyoX9XlfbODc9RV18TrLwPMcB5l3ITcUEnbFUe2DIAbk_6H4E0akk/s320/2008-06-24_0953-1.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5215479008727756290" /></div><div>It seems to me that this will make it more difficult to ensure quality and, for those of us that don't read all the code in the installed plugin, this could even be dangerous. Thanks to GitHub and Google these three versions have equal footing. I guess I'll trust Google and click on I'm Feeling Lucky.</div><div><div style="text-align: center;"><br /></div><div><br /></div></div>Davehttp://www.blogger.com/profile/16335253725087209777noreply@blogger.com0tag:blogger.com,1999:blog-1176137253456608647.post-18136120439624939662008-06-04T12:35:00.000-07:002008-06-04T12:43:37.434-07:00SquirrelFish Makes the Day Just a Little Bit BetterOver at the <a href="http://webkit.org/blog/189/announcing-squirrelfish/">Surfin' Safari</a> Blog they just announced SquirrelFish, a super fast Javascript interpreter.<br /><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px;" src="http://webkit.org/blog-files/squirrelfish-webkit-graph.png" border="0" alt="" /><div style="text-align: center;"><br /></div><div style="text-align: left;">I just gave it a test drive on our site <a href="http://www.meetingwave.com/">MeetingWave</a>, and I have to say this thing is rockin!! I am going to use it from now on for all my browsing as well as functional sanity checks of the site. Anything javascript is running much faster and is most noticeable on our <a href="http://www.meetingwave.com/browse/map">Meeting Map</a> . </div><div style="text-align: left;"><br /></div><div style="text-align: left;">My work day just got a little better... Thanks SquirellFish...</div><div style="text-align: left;"><br /></div><div style="text-align: left;">Check out the MeemCloud I made for <a href="http://www.meemcloud.com/meme_clouds/279-Webkit--Blogs/latest/show">WebKit</a></div><div style="text-align: left;"><br /></div><div style="text-align: left;"><br /></div><div style="text-align: left;"><br /></div><div style="text-align: left;"><br /></div>Davehttp://www.blogger.com/profile/16335253725087209777noreply@blogger.com0tag:blogger.com,1999:blog-1176137253456608647.post-54114960585949688432008-05-21T08:03:00.000-07:002008-05-21T08:34:24.517-07:00We don't need a Web DesignerSitePoint had an article today relaying some thoughts about User Experience, the catalyst was an <a href="http://www.sitepoint.com/article/andy-budd-design-usability-css">interview</a> with Andy Budd. Basically he was talking about how web designers could learn a great deal by paying attention to how other industries manage user experience. It is an interesting read for sure, but what got my attention was the realization that I really don't know much about Design in general, and this isn't really a problem.<br /><br />I have seen a few rails projects go by where there is this resistance to hire a designer to be a part of the team. And I think this is understandable when a dev team manager looks at the deliverables. The reality here is that, on the web these days, the bar is set pretty low and a developer with a decent eye and knowledge of CSS and HTML and Javascript can put something together that even looks good. So we think this was a good decision, a designer would just cost more and get in the way. This approach inherently risky to any project.<br /><br />Most of the time developers and designers not only have different skill sets but they have trained their brains to look at problems differently. How many times have you seen a mock that has unintended features on it? That is a great thing and this is at the core of the issue. When you ask your developer to do design they are going to do it within the current constraints of the code base, and even worse they will do it within the constraint of their skill set. A designer will often not be inhibited by these things and you will get new or better ideas and the ideas will come from the desire to provide a positive User Experience.<br /><br />Many times your developer won't be willing or even interested in providing PhotoShop mocks of the intended design. He will dive right in and start coding it up, this is because he is a developer, he is interested in development , and as such he will pay attention to the implementation details. This can cause a considerable loss of efficiency, simply because many of the design ideas will not actually be accepted as features in the product. I have seen this happen again and again. And what is even worse than the feature not being in the product, is that code design decisions would have been made to support the feature. This is particularly unappealing because the code debt will live on , even without the feature and will be a constant distraction to the developers maintaining and adding to the project.<br /><br />I am sure there are many people out there that would be surprised the people don't believe that they need designers , since it is a standard in the industry, but there are a lot of new comers to the web space these days and they are only looking for the deliverable. They will happily allow their new application to look as if it emerged directly from the database and think that it is amazing.<br /><br />We are lucky at <a href="http://www.travelerstable.com">TravelersTable,</a> we have<a href="http://www.guod.net"> Doug Fales</a> at the helm. He is a very strong developer and is intensely interested in usability and design. So we are getting rid of the tabular , straight from the data model, design and going with something much more appealing. Don't fool yourself, unless you have a guy like this you will not know what you are missing out on.Davehttp://www.blogger.com/profile/16335253725087209777noreply@blogger.com0tag:blogger.com,1999:blog-1176137253456608647.post-64825990478412409872008-05-14T11:20:00.000-07:002008-05-14T11:43:31.208-07:00The shortest path takes too long to findAt first I named this blog Shortest Path, but I quickly realized that I am not oriented around finding the shortest path. The shortest path can often take too long to find, and often it isn't very fun getting there. I think there are lots of examples in modern software development philosophies that ring true to this idea.<br /><br />Premature Optimization, why is this generally held as a bad idea? Because the art of software development is complex, and we just don't know where we are going to end up at the end of the day. A great deal, maybe even a majority, of features that are added to applications either never get used by customers or worse never even make it into the product. So until you know that performance is a problem in your code and until you know that people will use it, don't bother. It is likely to be a waste of time and attention. Choose the short path, finish the feature and move on. <br /><br />Premature Feature Building, I think I touched on this above but I think this deserves its out shout out. More and more the successful software companies are building for people, and they include those people in the process of development. In Extreme Programming this is evident in the rule of having a customer as part of your development process. This is because more often than not your customer does not really even know what they want, and you as a developer or entrepreneur certainly don't know. So, instead of guessing, start small. Build out the minimal amount of features to get someone's attention. If you can't get their attention then iterate until you find a way to get their attention. Adding features is not a way to get someones attention, it may be a way to keep their attention for a while longer, but you won't get them to stay by giving them a long list of things that they could do with your software. Take the short path, you might end up building all the same features but do it from a place of informed strength.<br /><br />Test Driven Development, this is the best example of the difference between finding the shortest path and taking the short path. The shortest path would dictate the you always achieve complete code coverage with your tests. Some people even advocate throwing complete garbage at your code, or mixing up the decision tree to see that everything breaks in the correct way. It is believed that if you do this you will greatly accelerate your teams development because they will have a safety net of tests to protect them from lengthy bug cycles near the end of a release. I do believe that the tenets here are true, but I don't do it. I don't do it because it take a lot of attention to build out these test suites and keep them current. I think that the real advantage of writing tests is that it allows you to focus your attention on the specific problem that you are working through. Once you have tamed the problem, move on, take the short path. If you spend a couple more days getting code coverage you will probably find that in a week the features have changed or that entire business unit has closed down.Davehttp://www.blogger.com/profile/16335253725087209777noreply@blogger.com1