Just some notes.
(1) If you see the text
ActivityManager: Error: Activity class {org.chuck/org.chuck.Hello} does not exist.
When you recompile - you are doomed. You can find some stuff in the Android Beginner Groups but all you will learn is that no one knows the answer to this. The solution is to start a new project and paste your code into that new project.
(2) Do not use the XML editor built into Eclipse to add attributes - it seems incapable of editing XML except when you change attributes. Just use some other editor like vi or notepad to edit the XML. Then use right-click on the XML file and "Refresh" in Eclipse to get Eclipse to re-read it and re-generate the R.java file and compile the rest of your app. You *can* change attribute values - just not add new attributes. What I really need to do is tell Eclipse to just open the dang file without their little helper so you can edit the XML directly.
(3) Do not shutdown and restart the emulator - you should only start the emulator once per Eclipse session. If you shut it down, Eclipse will start it back up - but something will be subtly wrong. No big deal if you close the emulator. Just close and restart Eclipse.
(4) The Log.i is the best way to get debugging output. System.out.println should go to the log - grrr. AH well - just use the log.
(5) The Mac stuff is Intel-only.
Outstanding issues
(1) I do not know how to completely reset the emulator - I would like to have it not sure the programs are 100% gone between downloads - it makes me nervous - but it is not fatal.
That is all for now. I am off and running to write a Pong game based on a hack of the Lunar Lander. I have Twitter and reading and parsing RSS in Android working - it needs a completely new UI - but the networking is working and the XML parsing is working - so I am satisfied for now. That tool will be evolved into that IMS Tool interoperability for the Android - but I really want the last SI543 assignment to be a pong assignment to match our pong assignment in regular Java. So I will work on Android Pong before Android IMS Tool Interoperability.
Well - I have a simple Google Android application that read an RSS feed and parses out the title of the first item and displays it.
The cool thing is that my XML map parser works in Android too! Pretty printing broke so I will have to rewrite that bit.
Now I need to write a pong game in Android and then IMS Tool Interoperability in Android.
I think that I just taught the first lecture in a for-credit college course (SI 543 at University of Michigan) that is about Google Android!! It is recorded - when it goes up I will post a URL. The first Android homework is already complete by a number of the students in the course in tonight's lab based on the
Installing and testing Android on Windows podcast
I am going to Newport beach after all - I will arrive Friday evening and leave Monday evening so I can be back to teach Tuesday. So I will go to the project coordination meeting mostly. See you there.
This code did not work with files with spaces in the name:
foreach i ( `find . -name '*.java'` )
ls -l "$i"
This code did work:
foreach ii ( `find . -name '*.java' | sed 's/ /@@@@/g'` )
set i=`echo $ii | sed 's/@@@@/ /g'`
ls -l "$i"
I was quite pleased - I almost resorted to using walk in Python - but that was averted. Somehow Sakai's assignments tool (in mid semester) changed the format of the "Download all for grading" ZIP file. I am sure it is an improvement - but it broke my C-Shell scripts I use for grading.
I do not know what I did - but Plaxo *just* started working on my Mac OS 10.5 Leopard box. Now I need to sync all the way to my iPhone... That would be awesome to have it working again.
Just some notes - I am trying to build a python script to fix the dates on my files. I mistakenly use cp instead of tar to restore my home directory during my upgrade to Leopard. So now I have to go through and patch all of the files modification times from the backup.
It should be a fun exercise in Python. Notes below
walk(p, visit, arg) Calls the function visit with arguments(arg,dirname,names) for each directory recursively in the directory tree rooted at p (including p itself if it's a dir.) The argument dirname specifies the visited directory, the argument names lists the files in the directory. The visit function may modify names to influence the set of directories visited belowdirname, e.g., to avoid visiting certain parts of the tree
>>> from datetime import datetime
>>> now = datetime.utcnow()
>>> z = datetime.utcfromtimestamp(x)
>>> print z
2007-11-09 21:14:36
>>> print z.year
2007
>>>
-t Change the access and modification times to the specified time.
The argument should be in the form ``[[CC]YY]MMDDhhmm[.SS]''
where each pair of letters represents the following:
CC The first two digits of the year (the century).
YY The second two digits of the year. If ``YY'' is
specified, but ``CC'' is not, a value for ``YY''
between 69 and 99 results in a ``CC'' value of 19.
Otherwise, a ``CC'' value of 20 is used.
MM The month of the year, from 1 to 12.
DD the day of the month, from 1 to 31.
hh The hour of the day, from 0 to 23.
mm The minute of the hour, from 0 to 59.
SS The second of the minute, from 0 to 61.
I wrote some Ruby code to convert from Meeting Maker to iCal's VCARD format. Then I sent it to Trek Glowaki and he rewrote it.
Here is my Original Version. Trek's much cleaner version is below - it shows some pretty Ruby idioms.
#!/usr/bin/ruby
# add some magic to Nil objects to simplify .empty? calls below
class NilClass
def empty?
true
end
end
# ask for a file path and remove \r \n and \s from the end
puts "Path to meeting maker export:"
f = gets.chomp!.strip!
contacts = File.read(f).split("\n")
# first two lines are junk
2.times { contacts.shift }
# 3rd line is header data. Map to hash of value => position (e.g. "First Name" => 1)
h = {}
contacts.shift.split("\t").each_with_index {|contact,i| h[contact] = i}
contacts.each do |contact|
contact = contact.split("\t")
# skip the nameless ones
next if contact.at(h["First Name"]).empty? && contact.at(h["Last Name"]).empty?
# begin printing vcard
puts "BEGIN:VCARD"
puts "VERSION:3.0"
# Name, which is a litle oddly formatted because of data presence / absence
print "N:"
print contact.at(h["Last Name"]) unless contact.at(h["Last Name"]).empty?
print ";"
print contact.at(h["First Name"]) unless contact.at(h["First Name"]).empty?
print ";;;\n"
print "FN:"
print contact.at(h["First Name"]) unless contact.at(h["First Name"]).empty?
print " " unless ( contact.at(h["First Name"]).empty? || contact.at(h["Last Name"]).empty? )
print contact.at(h["Last Name"]) unless contact.at(h["Last Name"]).empty?
print "\n";
# Address, also a little odd
unless contact.at(h["Address"]).empty? && contact.at(h["City"]).empty? && contact.at(h["State"]).empty? && contact.at(h["ZIP"]).empty? && contact.at(h["Country"]).empty?
print "item1.ADR;type=WORK;type=pref:;;"
# Assume they are contiguous
for index in h["Address"]..h["Country"] do
print contact.at(index) unless contact.at(index).empty?
print ";"
end
print "\n"
end
# The one liners, pretty easy
contact.each_with_index do |datum, i|
case h.index(i)
when "Company"
puts "ORG:" + datum + ";"
when "Title"
puts "TITLE:" + datum + ";"
when "Email"
puts "EMAIL;type=INTERNET;type=WORK;type=pref:" + datum
when "Work Phone"
puts "TEL;type=WORK;type=pref:" + datum
when "Home Phone"
puts "TEL;type=HOME;type=pref:" + datum
when "Mobile Phone"
puts "TEL;type=CELL;type=pref:" + datum
end
end
puts "END:VCARD"
print "\n"
end
We are redoing our basement and wanted to put one of these really cool sofa's with a recliner at each end and really fluffy - for the kids to site on while playing video games and even to sleep over - bu reclining the couch back and throwing on a blanket. Teenagers are tough. So we bought a nice Lane reclining sofa from Sams Club for $600 and brought it home.
But this thing was big and bulky and it did not look like it would go down the stairs or through a window. But we bought it anyways and let it sit in the garage for a week measuring things to see if it could go down the stairs or through a window. There seemed to be no solution until my brother Scott came over one evening and I told him this sad story of how we were going to take back the couch because it would not fit down the stairs.
Scott went into the living room where we had a similar couch and flipped it over - and pointed out that the three sections were simply bolted together and held together with two metal bars running across the bottom of the sofa. Eight easy-to-reach bolts and it would be in three pieces.
So we went back to the new couch and tore off the packaging - that probably meant that I could not take it back to Sam's and get my money back. We flipped over the new Lane sofa and indeed it had the same construction as the Berkline sofa in the living room.
We removed the eight bolts and the three separatre couch pieces went easily down the basement stairs (it was much lighter). In 10 minutes I had it reassembled and up in the basement.
It just goes to show you that sometimes there is a simple solution hiding amongst all the complex solutions.
http://joehewitt.com/files/iphone/navigation.html.
This will cause me to lose a *LOT* of sleep! I will find it hard to focus on everyday tasks because of this. Good thing I have a few days off for Thanksgiving.
Just random notes.
Goal: Save a set of web pages to the local drive and interlink them intelligently leaving some links to the internet for known dynamic content.
So far it looks like the Firefox web page complete format is the best and most flexible local copy format.
Here are some things to investigate:
FireFox - Save as Web Complete
Can this be controlled by an extension? Can we script this?
I like this because the HTML and files are very obvious and accessible.
http://developer.mozilla.org/en/docs/Extensions
I cannot find the API to figure out whether the "save as web page complete" functionality is available to plugins or extensions.
An Application that Pulls down Sites:
Offiline Explorer - This was recommended as the best site downloader - the key is whether or not we can get at the data once the download is finished to adjust the files. This needs investigating.
http://www.metaproducts.com/
Other possibilities - need investigation
IE - Make available offline
http://support.microsoft.com/kb/196646
Web Site Downloader for Windows
http://winwsd.uw.hu/
Local Web Site Archive
http://www.aignes.com/lwa.htm
Web Site Downloaders
http://www.snapfiles.com/Freeware/downloader/fwoffline.html
This URL says it all:
http://tr.openmonkey.com/articles/2006/01/23/conditional-periodically_call_remote-in-rails
Quoting, "...but if any of these pages use the periodically_call_remote helper, then these periodical calls may persist longer than you would like."
When you are setting a foreign key in an object you can do it using the id directly or through the helper method. In this example comments belong_to users.
# Using an object reference
u = User.get(1234)
c = Comment.new
c.user = u
# Old school
x = Comment.new
x.user_id = 1234
Yeah - that is what I like to see - a framework that respects programmer intelligence and gives us choices!
Well - it was not nearly as easy as one would expect to make this work - but lots of folks have muddled their way through and I followed in their footsteps and fell into a few holes.
Smart folks should just use this code / plugin - which is pretty and clean
http://inplacericheditor.box.re/demos
I have not used it - but the demos are gorgeous.
So in this post, I do it the hard way. I won't go into detail - it is all in the code below. Someday this might make a nice plugin - but it still has a flaw that I compensate for. Here is the basic outline: (1) include TinyMCE in the portal once - also init TinyMCE in portal.rhtml like this:
<%= javascript_include_tag "tiny_mce/tiny_mce.js" %>
tinyMCE.init({
mode : "none",
theme : "simple"
});
(2) In the div that will hold the editor - at the end of the output put in some Javascript to activate TinyMCE on the textarea in question, (2A) While you are there resize the columns so the text area is nice and wide, (2B) - before activating TinyMCE - figure out if TinyMCE has been pithed by too much Ajaxing - if a getInstanceById throws an error (even if not found it should return a null) - throwing an error indicates that MCE can't even tell if something is *not* there. We declare MCE hosed, don't even try to make it work - because it actually works half way, (2C) if it turns out getInstanceById works (returning null is OK) - we assume MCE is alive and activate MCE on the text area in question.
The next trick is catching the Save and Cancel (1) First we do a save from TinyMCE back to the div with a catch block so that when we are not even using TinyMCE because is unconscious - we will not confuse Prototype throwing errors, then (2) once the Ajax request is complete (onSuccess) we deactivate the TinyMCE attached to out textarea (again in a try/catch to eat errors if MCE has been knocked silly). Putting this in onSuccess is perfect because by then the server is updated and we are milliseconds away from wiping out the div - so we de-associate the MCE from the text area *just* before it vanishes in a puff of smoke.
So what puts MCE into a sleep-like state? When you are on an exit screen and you overwrite the div containing the editor from an external navigation operation. In Toozday - this is like going into Wiki, Editing a page, and then without pressing Save or Cancel you switch to Profile (oops - MCE left in limbo), then when you come back to Wiki and Edit - MCE is in a state unresponsiveness - waiting forever for its lost textarea to come back to it - which will never happen :(
I detect this in the Javascript and simply don't use a zoned-out MCE - let users type in a text area I say! I warn the user to press Save or Cancel before continuing - hey if I charge their credit card twice - it is their fault!! Sooner or later users will learn to press Save or Cancel.
This condition is naturally reset when the whole page is refreshed - in Tooz this is on a Refresh, All Sites, or Site to Site Navigation. So MCE will start working again - leaving the user to wonder about the IQ of the system they are dealing with! MCE seems to come and go almost on a whim :)
Someday I will figure this out - but it is now on to more other fun stuff. Golly - everything I do ends up with some sticky wicket. Ah that is the fun of it all!
Below is the sweet code - with a lot of cool helpful urls that saved my arse and led me to the solutions. The URL to source is http://toozday.rubyforge.org/svn/trunk/app/
<form action="<%= url_for :action => "edit", :id => @wiki.id %>"
method="post"
onsubmit="try{tinyMCE.triggerSave();}catch(err1){};new Ajax.Updater('<%= portal_get_div %>',
'<%= url_for :action => "edit", :id => @wiki.id %>',
{asynchronous:true, evalScripts:true,
onSuccess: function(transport) {
try {
tinyMCE.execCommand('mceFocus', false, 'umap_content');
tinyMCE.execCommand('mceRemoveControl', false, 'umap_content');
} catch(err2) {}
},
parameters:Form.serialize(this)});return false;">
<p>
<textarea cols="20" id="umap_content"
name="umap[content]" rows="20">
<%= @wiki.content %></textarea> </p>
<input type="submit" name="commit" value="Save"
onclick="try{tinyMCE.triggerSave();}catch(err3){}" /> |
<a href="#" onclick="new Ajax.Updater('<%= portal_get_div %>',
'<%= url_for :action => "view", :id => @wiki.pagename %>',
{asynchronous:true,
onSuccess: function(transport) {
try {
tinyMCE.execCommand('mceFocus', false, 'umap_content');
tinyMCE.execCommand('mceRemoveControl', false, 'umap_content');
} catch (err4) {}
},
evalScripts:true}); return false;">Cancel</a>
</form>
<p id="mce-error-message">
Note:You should press "Save" or "Cancel" before navigating away from this screen.
</p>
<!-- We need all the try/catch's because if the javascript fails, the Ajax.Updater punts and puts
the output in the main div. So we eat all the errors in the above code. -->
<!-- http://groups.google.com/group/rubyonrails-spinoffs/web/wysiwyg-for-script-aculo-us-inplaceeditor-using-tinymce -->
<!-- http://tinymce.moxiecode.com/punbb/viewtopic.php?pid=20212
http://www.technoticmedia.com/ -->
<!-- http://wiki.moxiecode.com/index.php/TinyMCE:Turn_tinyMCE_into_an_Ajax_editor -->
<!-- http://www.faqts.com/knowledge_base/view.phtml/aid/5846 -->
<!-- http://www.daniweb.com/forums/thread28365.html -->
<!-- http://tinymce.moxiecode.com/punbb/viewtopic.php?pid=22977 -->
<script type="text/javascript">
try {
myWidth = document.getElementById('<%= portal_get_div %>').offsetWidth / 9.0;
} catch (err5) {
myWidth = 20;
}
if ( myWidth < 20 ) myWidth = 20;
// alert(myWidth);
document.getElementById('umap_content').cols = myWidth;
isOK = false;
try {
if (tinyMCE.getInstanceById('umap_content') != null) {
tinyMCE.execCommand('mceRemoveControl', false, 'umap_content');
// alert('Found old instance - removed');
}
isOK = true;
} catch (err6) {
document.getElementById("mce-error-message").innerHTML = "The text editor could not be activated.";
// alert("Can't even look up an instance - TinyMCE is hosed - don't bother");
}
// Only activate if the TinyMCE seems operational
if ( isOK ) {
try {
tinyMCE.execCommand("mceAddControl", false, 'umap_content');
tinyMCE.triggerSave(); // Generate the save error now, rather than later so we put out a message
} catch (err7) {
// A last gasp - can we do this without the control - likely will fail
try {
tinyMCE.execCommand('mceRemoveControl', false, 'umap_content');
} catch (err8) {}
document.getElementById("mce-error-message").innerHTML = "Problems encountered activating the text editor.";
}
}
</script>
For the past five days I have been struggling with a bug in the route code in rails 1.2.3. I finally monkey patched url_for to essentially force it to do the obvious.
In this blog post, I describe the bug and how I reproduced it and then the patch to work around the bug.
There is a 10% chance that the routes is actually working and I just do not understand it. I read in the Agile book something about routes trying to use the shortest URL where possible - but the problem is that I have these long URLs to pass bits of session-like information around between my ajax calls - particularly when I want to go cross domain with my Ajax (i.e. I want to use a Rails tool from one server included into a web page from another server where cookies and session information will not be usable).
The bug comes down to when I call something with a long url with lots of stuff defined and then I generate a new url adding an id which is always at the end of the routes, url_for decides to "forget" the stuff that was to the left of it in the incoming request URL. Changing action only generates the *right* url while changing the action and id generates the wrong URL.
My Urls have three basic forms
/imsti.fe828-12345-bfea.1.right-content/comments/ajaxstart
/ajax.1.right-content/comments/ajaxstart
/comments/ajaxstart
The first two are for use in divs and never shown to the user. The imsti one both establishes a session and sets up the context and div name when the tool is being used cross-domain. The second is used when you are not going cross-domain and cookies are available to establish session because the ajax and the enclosing container are coming from the same server - so incoming ajax requests get the cookies.
Here is my routes.rb - the three routes in question are the ones that freak Rails url generation out - even though I never use not generate Urls with the imsti prefix - other URLs are incorrectly generated as you will see in this short sad story.
map.connect '', :controller => "portal"
# Problem causing routes
map.connect 'imsti.:imssession.:context.:div/:controller/:action/:id.:format'
map.connect 'imsti.:imssession.:context.:div/:controller/:action/:id'
map.connect 'imsti.:imssession.:context.:div/:controller/:action'
#
map.connect 'ajax.:context.:div/:controller/:action/:id.:format'
map.connect 'ajax.:context.:div/:controller/:action/:id'
map.connect 'ajax.:context.:div/:controller/:action'
map.connect ':controller/:action/:id.:format'
map.connect ':controller/:action/:id'
map.connect ':controller/:action'
The bug happens when I go to a page with a Url like this
/ajax.1.right-content/comments/ajaxstart
And then in the view for this page I do this:
<%= link_to_remote 'view', :update=> portal_get_div,
:url => { :action => 'view', :id => comment.id } %>
Simple enough - I am changing the action and adding an ID - it should inherit the rest since in all my routes id and action are at the end.
Here is the problem - when I do not have the three imsti routes in my routes.rb all works well - the link_to_remote generates this url:
/ajax.1.right-content/comments/view/1
If I add the three imsti prefixed routes to my routes.rb the same code when called from the same url:
/ajax.1.right-content/comments/ajaxstart
Makes this URL:
/comments/view/1
Aargh! And on the same page in the same view, this code:
<%= link_to_remote 'Manage', :update=> portal_get_div,
:url => { :action => 'manage' } %>
Makes beautiful URLs like this regardless of what version of the routes.rb I use:
/ajax.1.right-content/comments/manage
So what the heck is happening - it works for action and fails when you do action+id - clearly the addition of an :id is triggering some deep stupid behavior in the url_for.
A key here is that I am never calling nor using a route that starts with imsti - the mere adding of the routes causes things to break.
I have played for hours and at one point removed my three routes and had a single route that would cause the evil behavior. I lost the exact single route that broke it - but it looked something like this:
map.connect 'routesbiteme/:controller/:action'
It had an action but no id - and yet it caused url generation to blow its brains out. I need to look at the Rails source code. One day I will download my own copy and start hacking on Rails - but I will save that for when I have more time.
So here is the monkey patch to fix it:
module ApplicationHelper
include Osids
include Portal
protected
# This is inspired by another monkey patch for support in browsers
# without cookies - but since cookie_only >= false seems broken
# that patch while useful to read is not much help
#
# http://www.edgesoft.ca/blog/read/2
#
# Funny - sometimes options is a string - in this view code
#
# <% form_remote_for :umap, @user, :update=> portal_get_div,
# :url => { :action => "add" } do |f| %>
#
# options comes in as a string like this:
#
# /ajax.1.main-content/users/add
#
# I am sure this is yet another bug. But we need to simply
# not patch the Hash unless it is really a hash
#
def url_for(options = {}, *parameters_for_method_reference)
if options.class == Hash
if options[:div] == nil && params[:div] != nil
options[:div] = params[:div]
end
if options[:context] == nil && params[:context] != nil
options[:context] = params[:context]
end
if options[:imssession] == nil && params[:imssession] != nil
options[:imssession] = params[:imssession]
end
end
super
end
end
Effectively if the parameters are on the request, and not in options, I force them into options. Somehow this convinces the recalcitrant url generation to really see the parameters.
I wasted about 15 hours on this one - I guess I learned something from it. I cannot wait to see the ugly code in url generation or secret undocumented back-door feature that broke this.
P.S. I am still struggling with how to set the Rails session id from a URL - my other reason to be peeved at the Rails folks - don't get me started on cookie_only and Rails developers rushing to put in security fixes without thinking about real impact. For now I have a hack to do IMS TI sessions in my own framework without using Rails sessions - to get on to cross-domain Ajax testing.
Just some meaningless notes.
ssh samovar.dmc.dc.umich.edu
cd toozday
ruby script/server -p 3001
This becomes console - to stop press CTRL-C
http://samovar.dc.umich.edu:3001/
Make a new account by pressing login and new account. Make an account named admin to be super-user
In another window
ssh samovar.dmc.dc.umich.edu
cd toozday
To play with the portal:
pico app/views/portal/index.rhtml
pico public/stylesheets/ple-style.css
To play with tools - I would start with users - it is very un-styled. After that take a look at comments - comments was styled by a student - and it looks nicer but he was a bit heavy handed in his approach - so I would like that restyled as well.
$ ls -l app/views/users/
ls -l app/views/comments
Just cleaning off my desktop - now that projects are all started...
SI539 Project Ideas
SiteMaker
Gridsphere - list portlet
Look at LAMS
Review paper - Chuck
Announcements - RSS Feed
Blog - RSS Feed
Poll Gadget
Open Sync
http://developers.sun.com/mobility/midp/articles/syncml/
Quizzing Gadget
SiteMaker - Table Builder
Bookmarking Application
RSS Feed Maker
Things to think of
Swiss Bank Account Number for flow-through authorization
Views / perspectives
Tagging
Hotspots
Just do IMS TI - Framework - Service Oriented Archiecture
Rails is pretty awesome - but it is clearly a moving target in terms of how it works. Things work and then they break in different versions.
Today I am playing with routes and all I want it to do is check the routes in the priority order from first to last - but it seems to get confused when I add routes that don't match at all in the routes.rb.
Yesterday's bug was the breakage of the cookie_only feature by people who were intent on "fixing" a security bug - their fix broke a feature.
I get the sense that the bright folks in Rails have been working on 2.x for a while and that the second string in doing the maintenance on the 1.x.
I have a bad feeling that I will be checking out a copy of the rails source and fixing the damn bugs myself. Perhaps I should upgrade to the latest rails. I just don't know - stuff that is solidly documented in the Agile development book is simply broken in the versions of rails that I run across.
Perhaps I am just down after wasting 20+ hours - first doubting myself and trying 50 ways to see if something was my fault - only to realize that it was a bug in the Rails framework.
# Adding these seems to confuse the route resolution for urls being created
# when imsti-session to the url - uncommment these when testing ims only - and
# figure out later why rails route priority seems simply broken
# The funny thing is that urls starting with imsti-session do the priority
# right - it is almost like route gets confused if it loks through too many
# wrong routes.
#map.connect 'imsti-session.:imssession.:controller/:context/:div/:action/:id.:format'
#map.connect 'imsti-session.:imssession.:controller/:action/:id.:format'
#map.connect 'imsti-session.:imssession.:controller/:context/:div/:action/:id'
#map.connect 'imsti-session.:imssession.:controller/:action/:id'
#map.connect 'imsti-session.:imssession.:controller/:context/:div/:action'
#map.connect 'imsti-session.:imssession.:controller/:action'
# End of the bug-exposing routes
map.connect ':controller/:context/:div/:action/:id.:format'
map.connect ':controller/:action/:id.:format'
map.connect ':controller/:context/:div/:action/:id'
map.connect ':controller/:action/:id'
map.connect ':controller/:context/:div/:action'
map.connect ':controller/:action'
The key for a rails application in SVN is to make sure not to check in stuff that is part of the run time. Rails could organize this better - but it is not so bad. This post describes how I did it. Here are some references:
Howto User Rails With Subversion
My process is a variant of the above link.
First I check out my place in SVN that I want to add the application below. If I need to add a new directory - I make the directory and commit it.
Then I go into the empty directory and copy in my rails app.
Then I run these commands in the directory before checkin:
rm tmp/*/*
rm log/*
rm `find . -name '.DS_Store'`
rm `find . -name '*~'`
rm `find . -name '*.sqlite3' `
rake db:migrate VERSION=0
I just made a little script to do this so I don't forget steps.
Then I do an
svn add
svn commit -m "Initial commit"
Then after the commit I do a bunch of propsets
svn propset svn:ignore "*.log" log/
svn propset svn:ignore "*" tmp/sessions tmp/cache tmp/sockets
svn propset svn:ignore "*.rb\n*.sqlite3" db
svn propset svn:ignore ".DS_Store" .
svn commit -m "Setup initial ignores"
Edit your ~/.subversion/config and add this line:
global-ignores = *.o *.lo *.la #*# .*.rej *.rej .*~ *~ .#* .DS_Store *.sqlite3 schema.rb *.log
So folks can develop and not be bothered in their svn status output
when their running ruby system makes files.
If you want see all this cleverness in action - run the checked out app and then do this:
svn status --no-ignore
You will see something like this:
I log/development.log
I db/development.sqlite3
I tmp/sessions/ruby_sess.33f0133496165daf
Which means it is working.
Some Rails/SVN experts would suggest that you do not check in the database.yml and a few bits of public like dispatch.cgi and dispatch.fcgi.
Sure - I see the point there. But I erred on the side of making the developer's life easier and having a fully functional sqlite3 version when it comes out of SVN. Since we will have lots of developers and a fewer production instances - I figured that the right choice was to have production folks make the overlay rather than every single developer. Or perhaps make the overlay happen as part of the build of a release - which is a complex script anyways. Make it easy for the developer I always say.
Here is my Leopard dock:
From left to right - these folders are my outreach, research, personal, publishing, rails, and teaching folders...
The trick is getting the image to show in the dock.
In each folder put an image named aaaa-something.gif so it sorts to the top.
Then tell the dock to view the folder sorted by name.
Your image wil be the icon!
I upgraded to Leopard again - this time I did it the way I have always done it. Back everything up - blast the hard drive completely and then a fresh install.
I figured that some clever gadget would help me restore my home directories from my backup - perhaps I just cannot figure out newfangled gadgets. So here was my process - feel free to educate me.
Boot into the CD and run the Disk Utility
Make an image from my main partitions onto a USB drive - I did not really want an image - but it was all Disk Utility wanted to let me do.
Blast the main disk in my laptop and install Leopard
Create a new account called "csevadmin" as part of the install - do not create the all important "csev" account yet.
Once log in is complete, you are logged in as csev admin.
Make a new account called "csev" - make it an admin.
Still in csevadmin pop up a terminal window (finally a decent user interface) - Become root
sudo sh
cd /Users
mv csev csev.org
cp -r /Volumes/Blah/Users/csev /Users
Note: Using cp was a bad mistake - I reset all my dates. I should have read my own blog post and done this instead:
cd /Volumes/Blah/Users
tar cf - csev | ( cd /Users ; tar cfv - )
That would have saved my file dates . Ah well onward and upward. Once the directory /Users/csev is in place ou need the magic chown command - which is now different in Leopard.
chown -R csev:staff csev
The "staff" is new - it makes a lot more sense than making a group for every user - but it is different. Also I now learned the modern ":" form of the chown so I don't get nicked for using deprecated syntax every 18 months.
All in all I am much happier with a clean install - even though it took me hours to reinstall all the apps - I lost media for iWork06 so I went and bought iWork08 and I will need to go buy iLife 08 as well because of lost media - heck I need to upgrade anyways.
Oh yeah - and Time Machine is working - It was easy to exclude my Final Cut Express Documents. It did not work on the first try - but I went to sleep - in the morning all was better. I like that kind of software. I have never really ever backed up my computer until now - thanks Apple.
Really cool trick with Leopard - Drag a directory into the doc and put an image in the directory named aaa-something.gif so it is the first thing in the directory - then the doc will see it and the image will appear on the folder - my rails_apps folder on my dock has the cute rails logo on it using this technique by naming the image aaa-rails.png
I am so loving the Rails and Ruby install on Leopard.
Plaxo still does not work - even with a fresh install of everything. I guess I will just book mark Google calendar on my iPhone and give up using my iPhone's calendar - too bad - Plaxo was sweet while it worked (4 weeks). Plaxo felt like such a Rube Goldberg contraption byways - it is not surprising that the wheels came of on on OS upgrade.
Luckily - Google Calendar has an iPhone view.
I will let the dust settle on calendars - if Spanning Sync releases a 10.5 version - I may just buy - it some things you should pay for to motivate folks to work.
Here is my holiday wish for Apple:
In the migration tool - Allow me to (a) mount disk images and (b) find the place where the old /User's directory is. The current UI is too simple and does not handle the common case - it really wants to back up and restore onto the *same* computer - not an external drive.
Also - we need new operating system releases more often so I don't forget how to upgrade my system in between releases. Next time it will be too long nd I won't even come back and read this blog post. And again I will be whining - but oh well.
Here is my New Years Resolution:
Since I am an AppleSeed Participant - I promise to test the upgrades for the next O/S - this last released I focused on testing the X/Server stuff - next release I will test the desktop stuff as well.
I won't rant about the lack of a rebuild all mailboxes in Mac OS/X's Mail application. Entourage had it - but Mail does not. I also won't rant about how the conversion from 10.4 to 10.5 left my mail in a strange state that required the hand-rebuilding of about 300 folders. And I am also not going to rant about how Automator is impossible to figure out - If Automator was easy to use, I should have been able to do a "rebuild all my mail boxes" in Automator in about 5 minutes. And I am also not going to rant about how AppleScript is the weirdest language on the planet - it is like perl - if someone gives you code that works - sweet - if you want to change it to do something every so slightly different it is impossible.
This post is a positive post and has some really cool info that will make it so that all the things above fade into quiet background grumbling.
Make a key that does the work for you. Damn sweet.
System Preferences -> Keyboard and Mouse - Keyboard Shortcuts -> Press the + to make a new One -> In the add new pop up -> Pick the Mail Application -> Enter the menu item exactly as shown - In my case it was "Rebuild" no quotes - and then pick a key - I picked Apple-Y.
Then restart Mail - and look!!! The menu now has a shortcut it never had before. Click on a mailbox and press Apple-Y - viola - your mail box rebuilds!
Since Mail does the rebuild in the background - you can click the next one and press Apple-Y as fast as you can go - I got a whole page ahead of the rebuilds once - than sat sipping coffee watching it catch up.
Now Mail search works through all the boxes.
After about 10 minutes I am half way through my mailboxes- and I have rebuilt the key stuff I look and search regularly. Now I have an important task to do when I don't want to think much - building the 200+ mailboxes I have yet to rebuild.
I do like the new Leopard mail - particularly the feedback at the bottom as it tells you what is going on instead of just staring dumbly at you when it is busy doing something in the background.
I am amazed at the flexibility of Rails. I needed a way to dispatch between the portal and a tool and communicate which "context" / "site" the tool is supposed to operate in.
In Sakai we have complex stuff like a request filter and obtuse code buried in portal to accomplish this.
In Ruby it is trivial...
In my portal's view - I add this line:
<%= link_to_remote 'Users', :update=> 'main-content',
:url => { :action => 'ajaxstart', :controller=>'users',
:div => 'main-content', :context => 1} %>
The context is the site id.
In my routes.rb file it looks like this:
map.connect '', :controller => "portal"
map.connect ':controller/:context/:div/:action/:id.:format'
map.connect ':controller/:context/:div/:action/:id'
map.connect ':controller/:context/:div/:action'
map.connect ':controller/:action/:id'
map.connect ':controller/:action'
Rails adds the context to the URL when the portal generates the link URL and when the application makes a url using the url_for helper - the context (and div) are pre-pended to every URL - with zero changes to the application.
the urls look like
/controller/site-id/div-name/action
Both the URL made by the portal and the url made by views in the tool.
Abstraction abstraction abstraction - lots of flexibiltiy - lots of power.
I have had some problems with my Leopard upgrade on my Desktop. I did this from my 9A581 disks which are claimed to be clones of the released software (which I believe to be true).
If your Home directory is under a different partition in Mac OS/X
I have my home directory on a separate partition /Volumes/UserHome/Users/csev - I wonder how much of my problems are related to that. It is funny that part of the reason to do the external home directory is to make upgrades easier - hmmm.
After the upgrade, when I logged in for the first time I had an empty Desktop, etc. I finally fixed it below - some damage was done to my configuration in the process - to give you the best chance of success if you keep your home directory on a separate partition - I would try the steps below.
Before your Leopard upgrade, make another admin account on the local drive. After the upgrade - do not log into your normal account - instead log into this other account using your fresh admin user. Then use System Preferences -> Accounts -> (Unlock) -> Control-Click on the User and bring up Advanced Options -> Change the Home Directory to the new place -> Like /Volume/UserHome/Users/csev - save the account then logout of the admin account and log into the account on the external partition. Some other folks might figure out how to ditto the /Users resource fork so all new accounts are made on the partition - but since the niutil command is gone - all the mojo that used to work - no longer works. - this is your best chance for success as best I can tell.
If you are reading this blog *after* you did an upgrade and encountered a problem like I did - well - the process works - and I even did it to my account from the account I was logged in. The above process will let you get to the point where you can log in and see your desktop and then start fixing the broken bits.
The rest of these issues *may* be related to my rocky start finding my home directory.
Lots of little things the I know are because logging in before fixing home directory
These are not Leopard's fault - things just got messed up because I logged in before fixing my home directory. If you follow the above procedure, you should not encounter these problems - because I did this with another account (pointing the account to the right home before logging into the account) and saw none of these problems.
There may be others - little things seem to vanish if you log in and have your home directory pointed wrongly.
Leopard Conversion Problems - Mail
After I got my home directory reconnected and logged in and ran mail, A dialog popped up to convert my account - I said "yes" - seemed to work. A few glitches so far:
For my main account - the conversion lost my outbound mail server could not send mail immediately after the upgrade. Easy to fix in the settings. It is funny that it remembered where to send the mail - it was just not selected.
All of my 4GB of locally stored mail boxes appeared to exist by had no messages - panic - Thankfully doing a rebuild fixes this. Funny how a complete copy of all your mail on Gmail makes one more relaxed about these things. I think that everyone should have several copies of their whole mail corpus. I wish Apple mail had a rebuild all mailboxes.
Lost my second mail account (Comcast) - no big deal - I just had to re-add it. On Comcast, I had some trouble getting it to "get mail" - it still refuses to retrieve any "old mail" that had already been viewed. But it did get new mail that arrived after the conversion. Since this is low-volume - no big deal for me.
I used "automatically configure" account feature to add my Comcast account - pretty slick.
One neat feature is that in the control panel it knows the link to some help inside of Comcast. This new documentation made it so my iPhone can actually send mail to Comcast (unrelated to Leopard)
http://www.comcast.net/help/faq/index.jsp?faq=EmailMail_(Mac)18530
Leopard Conversion Problems - Calendar / Plaxo
My Calendar is lost/empty Plaxo seems unable to refill it. Still working on this one.
http://forums.plaxo.com/showthread.php?p=12671
I am going to suppose for the moment that this is a Plaxo problem - I have reinstalled Plaxo a bunch of times - still no luck. I will just sit and wait - thankfully Google Calendar and Plaxo and my iPhone all seem to have perfect copies of my calendar for now. Synchronization is just broken.
Those of you who have heard me talk and seen my soon to be published journal article titled The Coming Functionality Mashup In Personal Learning Environments have heard how I suggested that Google will respond with some vigor to the Facebook API work. My feeling was that Facebook had one-upped Google pretty badly on this and the Google would not sit back and let Facebook keep the first-mover advantage for long.
Just this morning Joseph sent me this article:
Open Social Opens New Can of Worms
In a move that was anticipated for weeks, Google has unveiled a set of application program interfaces (APIs) that allow third-party programmers to build widgets that take advantage of personal data and profile connections on a social-networking site. But instead of limiting the project to its own social-networking property, Orkut, Google has invited other sites along for the ride--including LinkedIn, Hi5, Plaxo, Ning, and Friendster.
Here is a quote from a June 2007 version of The Coming Functionality Mashup In Personal Learning Environments journal article:
While developing and improving standards for functionality mashups in a learning context are important efforts, general-purpose functionality mashups are likely to be promoted by market-leading web development companies such as Google. Much like current VLE producers use their proprietary extensions to gain and hold market share companies like Google and Facebook are trying to convince developers to write application extensions for their particular form of application functionality mashup.
While Google Applications have been around for some time, their scope is narrower then the functionality mashup proposed above. Google applications are effectively a new form of portlet, i.e., functionality can be placed and configured but there is no concept of a context under the control of the consumer where a set of applications / portlets inherit common authentication, authorization, etc.
The recently announced Facebook Platform [24] is a significant step towards functionality beyond Google Applications. Facebook applications begin to explore the notion of context. Each Facebook application operates in the
context of the given Facebook entry.The initial set of APIs which Facebook Platform provides to developers is obviously influenced by the social networking aspects that form the core of Facebook software. However other APIs are completely general purpose and are very commonly found in today's VLE systems. Applications can (when permitted) access and modify Facebook information using these APIs.
Using Facebook to produce a learning context might be as simple as building a Facebook entry for a class and then associating a number of Facebook applications with the context. While initially Facebook will seem a poor substitute for a high-functionality VLE system, all of the architectural elements are already in place to potentially replace VLE and other collaborative systems. The only question is which direction Facebook will evolve their APIs.
Currently it seems unlikely that Facebook will put much effort into building learning-centric capabilities into their framework. A more likely scenario is that Google Applications will realize that they have been "one-upped" by Facebook and competition will ensue. It is likely that features that support teaching and learning will not be seen by either Google or FaceBook as strategic priorities in the short to medium term. However, if competition ensues, Google, Facebook and others will continue to refine, improve, and richen the concept of context. Perhaps PLE developers and users can shim learning applications onto these efforts when contexts become rich enough.
Apple's recent announcement of the ability to extend the iPhone by writing Web 2.0 applications will potentially stimulate yet another thread of innovation around the notion of context, at least the notion of personal context.
So now it is "game on" - I have been thinking about Functionality Mashup for many years now - mostly spurred by my involvement in IMS Tool Interoperability and the amazing potential I see in true functionality mashup. At times it has felt like no one cared about this model - certainly very few would invest developer time to make this happen or be willing to try it on their campus.
Until now, it was a weird situation to see Google uncomfortably catching up with *any* technology company - usually Google is years ahead of the game - kudos to Facebook - but rest assured that the FB advantage will likely be short-lived - because Google moves very quickly and moves to the right location in the market very quickly. Google realizes that what is important is knowing "what to do?" - classic management issues like "how to do it?" or "how much will it cost?" or "how will I make money off it?" are secondary issues if you want to be a real leader in technology. Folks who sit back and ponder the the management issues are forever doomed to be behind Google.
Functionality Mashup is now moving into the fast lane - time for me to sit back and watch and enjoy it all unfold.
References:
Here is a couple of my recent Functionality Mashup talks:
Functionality Mashup - Edinburgh, Scottland May 2007
Functionality Mashup - Barcelona Spain, October 2007