The evil of capitalism crushing the "common" folk and those that find it unfair.

When my migrant grandparents moved to Australia in the 1950s, they worked 7-day weeks, 12 hours per day, at least. My grandmother worked in a textile factory ran by a wealthy family of earlier migrants. My grandfather worked wherever there was work, often in the western outback for months at a time.

 

From the stories they told me, it wasn't fun. Noise, sweat, long hours, boredom from the repetive work. My grandmother did mention several tough, unfair and stingy (at least in the salary department) bosses. But, they were happy there was work, and they gladly took it. Overtime, they built up their savings and they didn't have to worry about all that, but they continued living a simple and self-sustainable life. They didn’t need much; some food on their table and a roof over their heads.


The world had just changed back then. It was the aftermath of the 2nd World War and of a civil war back home. Things were uncertain, but there was relative peace, relative safety, and plenty of work. In Australia, that is, because other parts of the world were either still devastated or dealing with other deadly and destructive wars and conflicts. The old country had yet to recover, and the United States and the Soviet Union dominated world politics. But my grandparents were simple people, they instinctively knew that given work and safety, every thing would  magically "work out". They didn’t expect much help, other than the aforementioned basics, from their bosses or their government or some other nebulous but powerful organisation. If they wanted a better life, it would have to be because of their hard work.


Fast forward to today, and we find ourselves amidst a tectonic change in the way that the world works. Europe is in crisis (really, nothing new here), regional wars raging, dictators waging their fists in rage, religious fundamentalism as powerful as back in the good old middle ages in many parts of the world, conspiracy theories “explaining” every new development in the economy or politics as the implementation of a plan by certain powerful elites (usual, bankers) to take over the world and turn humans into some sort of battery, and, gasp, the emergence of China and the Far East as the new economic center of gravity.


This essay was triggered by a discussion with a few friends about the apparent unfairness of the migration of manufacturing work to the East, and especially to China, which was itself triggered by this NY Times article. In this discussion, all of the above points were raised as if they are facts perfectly connected with each other. It all accumulates to this: it is in the interest of multinational organisations to reduce our standard of living, and we are powerless to do anything about it.


It started when a friend, disturbed by the ruthlessness of a certain multinational company, complained:


How do you reconcile the fact that workers making iphones for $17 per day, sleeping in the factory, a company that makes 75b profit saying that it has no responsibility to employ people in the US because of inflexible practices!


At first look, this really does seem unfair. Getting $17 per day for my work would not be enough for my train ticket to work. A rich company could certainly pay its workforce a little bit more. And the same company should certainly do more of its business in a particular country of the world as an indication of its loyalty and patriotism.


But on second examination, there are so many wrong assumptions in this statement that are so easy to overlook when you emotionally glance at it and not make the effort to look at the facts. For example, when I lived in Hong Kong for a short period of time back in 2006, sharing a dormitory room with two Chinese students, I would spent around $5 per day on three meals at the university canteen, and around $1 on the room. And Hong Kong is expensive compared to places like Schenzen where most of this company's products are made. It seems like $17 per day is good money for an unskilled 18yo worker from a village in central China. I doubt my grandparents were getting much more than that working in Australia as unskilled workers in the 1950s.


Then, the fact that a company is filthy rich, does not require this company to pay more unless it really has to. Securing plenty of unskilled labour in China does not seem to be a problem, therefore such labour can be secured for a very small price. Simple economics show that prices of any commodity, including labour, find an equilibrium with depends on the ratio of demand vs supply. This does not include the amount of cash in the buyer’s bank account.


Finally, it is common sense that organisations, just like people, will try to maximise their potential even if that means leaving the shores of their home country. My ancestors did that many times by migrating in 5 different countries around the world. And all of them are still deeply patriotic about their home country. Prosperity and patriotism does not seem to mutually exclude each other when it comes to people making important personal decisions; why should large organisations, which by definition are multinational due to the composition of their workforce, be any different?


In any case, the friend’s argument seemed to be mainly targeting the unfairness of the corporation against “exploited workers”. A little bit like my grandparents sixty years ago. But look at what happened to my grandparents after they gratefully took that money, put their head down, and worked to their limits: many of their descendants are now living in an affluent society expecting to be paid handsomely for working as little as possible so they can live a comfortable and secure life, free of worries about what tomorrow brings.  These decedents are also fortunate enough to be able to show signs of sympathy for others who, like their grandparents, are today working in similar (a relative term since no Shenzen equivalent has ever existed in Australia) conditions to build their own future so that their own descendants can one day live the lives we live.


It is also easily forgotten that it is because of people like my grandparents that the average modern latte-sipping 40-year old expects that their employer is obliged to pay them to drink lattes and engage in philosophical discussions about fair and unfair trade practices or evil and good enterprises, pay their mortgages and get their kids through private schools. My grandparents, with all their hard work, created generations of people that expect that things will always be as they used to be, safe, wealthy, easy.


But my friend countered:


What goes around comes around, lets see what you do when wage deflation hits your front door....while the people asking you to cut eat more than ever!


A common defence of people without strong arguments to support their position is the claim that enough time, their position will be justified. They believe that 15,000 years of "civilised" human history and society haven't got anything to teach us about modern affairs, and that this present argument of the evil of capitalism and unfairness of the changing global economic dynamics cannot be analysed or settled with the data available now. Loosing our hard earned privileges due to others working longer and harder is so unfair. They are masking their own fear of loss of the quality of life given to them by their ancestors by pretending to worry about the quality of life of those workers in far away places who aspire to a better life.


The fact is that when you knock on other people's doors for a wage, you have to get what you are given; if you don’t like it and you have the options or the conviction you can refuse the terms and move on. Rules and laws that protect workers work well when everything is going well, but as soon as a society comes under strain, these rule break down. They have to break down because they are not sustainable, they are not natural; they are designed and imposed to work under certain conditions, like all laws are. Change those conditions, and the rules under which a society operates have to change.


If you want to eat like never before, as the bosses of multinationals or large business apparently do, go build your own Apple (if you dare to do it).


Of course, most people would never do what Googler #13 (Steve Schimmel) did, because that would be not cool, or safe, or comfortable, or even possible (“they” will not allow it) to do. Working like Alex Payne (Twitter)? Or learning something new (Tracy Osborne)? No! The world may be changing but hard-earned habits don't. For most, the best thing to do is to stay put and complain about it instead on steaming ahead as the times demand. Staying put is so much easier that, say, innovating your way out of a tectonic change in world order! For respectable latte-sippers everywhere, complaining is so much more dignified, in case a wealthy benefactor or an enlightened government hears their plea. For some that can, complaining of the changes in the world order manifest also by extremes such as striking, which involves unilaterally cutting down services by abusing a position of power, blocking economic activities for others, demanding that the evil capitalists and/or the rest of the society looks after them, all while they sip cafe-lattes and watching the cricket.


We have to understand that the people that pay our wages don't have an obligation to look after our well being unless it makes economical sense. Reality does hurt. We have to take responsibility for our own path in life just like my grandparents did sixty years ago... Like the Schimmels, Paynes and Osbornes do today.


The world is changing and is, as always, full of opportunities for those that are brave (and crazy) enough to chase them.


For the rest of us, we can complain about the unfairness of it all.

Testing

Spent two full days writing tests to automatically stress model and controller code in my Rails app. I suddenly feel peaceful!

Steve Jobs resigns

Although I knew that Steve Jobs would have to step down soon after he announced taking medical leave earlier this year, it is still sad to hear he has now decided to resign the post of Apple CEO.

Rarely can individuals be both as visionary and successful in achieving their vision as Steve Jobs has been.

Any flaws of his character, of which many people seem to know so much, only underline his humanity.

Steve, thank you for sharing the vision of what computing can be with us through the market.

You have inspired many more than you have angered (jealousy is a human flaw after all), and thanks to that sharing I am sure many more good things will follow from Apple and others.

Happy 2011 Geek Pride Day!

In this 2011 Geek Day, I take price in copying and pasting the Geek Manifesto from Wikipedia. Happy Geek Pride Day to all my fellow geeks!

(Republished without permission from http://en.wikipedia.org/wiki/Geek_Pride_Day)

Rights:

  1. The right to be even geekier.
  2. The right to not leave your house.
  3. The right to not like football or any other sport.
  4. The right to associate with other nerds.
  5. The right to have few friends (or none at all).
  6. The right to have as many geeky friends as you want.
  7. The right to be out of style.
  8. The right to be overweight and near-sighted.
  9. The right to show off your geekiness.
  10. The right to take over the world.

Responsibilities:

  1. Be a geek, no matter what.
  2. Try to be nerdier than anyone else.
  3. If there is a discussion about something geeky, you must give your opinion.
  4. To save and protect all geeky material.
  5. Do everything you can to show off geeky stuff as a "museum of geekiness."
  6. Don't be a generalized geek. You must specialize in something.
  7. Attend every nerdy movie on opening night and buy every geeky book before anyone else.
  8. Wait in line on every opening night. If you can go in costume or at least with a related T-shirt, all the better.
  9. Don’t waste your time on anything not related to geekdom.
  10. Try to take over the world!

Xcode ad-hock provisioning certificate pains.

In a previous article, http://blog.futureshock-ed.com/2011/01/ios-ad-hock-app-distribution-for-beta...., I documented how I managed to produce a testing version iOS app that I needed to distribute to testers. To do this, I needed to create a ad-hock provisioning certificate on Apple's Developer's Provisioning Portal.

While the method I described worked back then, and I thought I had a decent undersrtanding of the certificate creation and application signing process, when I tried to repeat it last week, it all fell apart. 

I tried Xcode 3, Xcode 4, deleting and creating all certificates, editing the Xcode project configuration by text editor, and repeating everything hundeds of times over two days, the bloody thing didn't want to work. I kept getting errors like:

  • Code Sign error: Provisioning profile  can't be found
  • Code Sign error: Provisioning profile '2B29F6DB-B03A-4882-A405-40BB6A2377EC' can't be found
  • XCode could not find a valid private-key/certificate pair for this profile in your keychain.
  • profile doesn’t match Application Identifier xyz

and many others. 

I finally started suspecting that I was innocent of incompetence, and that there was something NOT FUNNY going on with Apple's signing process, especiall the part where in Xcode, you Build and Archive the app, then in the Organizer you Share the archived app by choosing the appropriate code-signing identity.

I decided to find out whether this process really worked. 

Reading the documentation (http://developer.apple.com/library/ios/documentation/Xcode/Conceptual/iphone_... discovered that there is a utility that inspects a built application and reports a few interesting statistics and settings, including the certificate used to sign the app.

This utility is called 'codesign'. I tried running it first against the .ipa file that the Organizer creates, but failed. The documentation only had examples with .app files, those produced by the Xcode build process. So I decided to just build the app in Xcode, then browsed to the build directory, and applied the tool to the new .app file. This is what I got:

$ codesign -dvv myApp.app

Executable=/Users/me/programming/iPhone/myApp/build/Beta-iphoneos/myApp.app/myApp

Identifier= myApp.

Format=bundle with Mach-O universal (armv6 armv7)

CodeDirectory v=20100 size=1900 flags=0x0(none) hashes=87+5 location=embedded

Signature size=4337

Authority=iPhone Distribution: Awesome Enterprises Pty Ltd

Authority=Apple Worldwide Developer Relations Certification Authority

Authority=Apple Root CA

Signed Time=26/03/2011 6:24:21 PM

Info.plist entries=24

Sealed Resources rules=3 files=71

Internal requirements count=1 size=144

That was interesting. The distribution certificate was correct, as specified in my testing profile. This file *should* work if I tried to install it on an iOS device with this certificate installed, as long as the device's UUID was valid for this certificate. With no time wasted, I just drag-droped the .app file onto iTunes; my testing iPod Touch with the correct certificate installed was already connected. Clicked Synced, waited for a few seconds, an there you go, app installed, no worries!

It seems that the Organizer was messing around with the certificates. I don't know exactly how, I might investigate further if time permits, but what was happening just did not make sense for a systemt that one would expect would be throroughly debbuged and working as expected. It seems like this isn't.

So lesson learned: only sign apps in Xcode, forget about archiving in Organizer. Note that the Share Archived Application in the Designer has the option 'Don't Resign". This might produce a properly working archive if in fact it doesn't touch the signing that Xcode did prior to archiving. But with what I have learned about the reliability of all this, I will be staying away from archiving via the Organizer.

HTTP status code symbols for Rails

Thanks to Cody Fauser for this list of HTTP responce codes and their Ruby on Rails symbol mappings. This table is sure to save me a lot of time when I need one of these.

 

Status CodeStatus MessageSymbol
1xx Informational
100 Continue :continue
101 Switching Protocols :switching_protocols
102 Processing :processing
 
2xx Success
200 OK :ok
201 Created :created
202 Accepted :accepted
203 Non-Authoritative Information :non_authoritative_information
204 No Content :no_content
205 Reset Content :reset_content
206 Partial Content :partial_content
207 Multi-Status :multi_status
226 IM Used :im_used
 
3xx Redirection
300 Multiple Choices :multiple_choices
301 Moved Permanently :moved_permanently
302 Found :found
303 See Other :see_other
304 Not Modified :not_modified
305 Use Proxy :use_proxy
307 Temporary Redirect :temporary_redirect
 
4xx Client Error
400 Bad Request :bad_request
401 Unauthorized :unauthorized
402 Payment Required :payment_required
403 Forbidden :forbidden
404 Not Found :not_found
405 Method Not Allowed :method_not_allowed
406 Not Acceptable :not_acceptable
407 Proxy Authentication Required :proxy_authentication_required
408 Request Timeout :request_timeout
409 Conflict :conflict
410 Gone :gone
411 Length Required :length_required
412 Precondition Failed :precondition_failed
413 Request Entity Too Large :request_entity_too_large
414 Request-URI Too Long :request_uri_too_long
415 Unsupported Media Type :unsupported_media_type
416 Requested Range Not Satisfiable :requested_range_not_satisfiable
417 Expectation Failed :expectation_failed
422 Unprocessable Entity :unprocessable_entity
423 Locked :locked
424 Failed Dependency :failed_dependency
426 Upgrade Required :upgrade_required
 
5xx Server Error
500 Internal Server Error :internal_server_error
501 Not Implemented :not_implemented
502 Bad Gateway :bad_gateway
503 Service Unavailable :service_unavailable
504 Gateway Timeout :gateway_timeout
505 HTTP Version Not Supported :http_version_not_supported
507 Insufficient Storage :insufficient_storage
510 Not Extended :not_extended

strftime for date/time formating in Ruby - parameters

In Ruby, I often need to format time and date strings to make them look decent. I use strftime, which aparently is used in other languages, like PHP.

In Ruby, you would do something like this:

puts (inspection.date + HOURS_FROM_UTC.hours).strftime('%e-%b-%Y, %H:%M')

The formatting parameters (starting with the percentage sign) are many and not to intuitive to remember. 

I found one post with a list of most of them here, but I also include them here for quick reference:

%a - abbreviated weekday name according to the current locale
%A - full weekday name according to the current locale
%b - abbreviated month name according to the current locale
%B - full month name according to the current locale
%c - preferred date and time representation for the current locale
%C - century number (the year divided by 100 and truncated to an integer,
   range 00 to 99)
%d - day of the month as a decimal number (range 01 to 31)
%D - same as %m/%d/%y
%e - day of the month as a decimal number, a single digit is preceded by
   a space (range ' 1' to '31')
%g - like %G, but without the century.
%G - The 4-digit year corresponding to the ISO week number (see %V).
   This has the same format and value as %Y, except that if the ISO week
   number to the previous or next year, that year is used instead.
%h - same as %b
%H - hour as a decimal number using a 24-hour clock (range 00 to 23)
%I - hour as a decimal number using a 12-hour clock (range 01 to 12)
%j - day of the year as a decimal number (range 001 to 366)
%m - month as a decimal number (range 01 to 12)
%M - minute as a decimal number
%n - newline character
%p - either `am' or `pm' according to the given time value, or the
   corresponding strings for the current locale
%r - time in a.m. and p.m. notation
%R - time in 24 hour notation
%S - second as a decimal number
%t - tab character
%T - current time, equal to %H:%M:%S
%u - weekday as a decimal number [1,7], with 1 representing Monday
%U - week number of the current year as a decimal number, starting with
   the first Sunday as the first day of the first week
%V - The ISO 8601:1988 week number of the current year as a decimal
   number, range 01 to 53, where week 1 is the first week that has at
   least 4 days in the current year, and with Monday as the first day
   of the week. (Use %G or %g for the year component that corresponds
    to the week number for the specified timestamp.)
%W - week number of the current year as a decimal number, starting with
   the first Monday as the first day of the first week
%w - day of the week as a decimal, Sunday being 0
%x - preferred date representation for the current locale
   without the time
%X - preferred time representation for the current locale
   without the date
%y - year as a decimal number without a century (range 00 to 99)
%Y - year as a decimal number including the century
%Z or %z - time zone or name or abbreviation
%% - a literal `%' character

 

iPhone - Beware of case sensitivity when enabling data model versioning

In an app I'm building, I decided it was about time to start thinking about data model versioning as a way to protect user data from database schema changes. Without versioning, every time I updated the app's schema, the user's data would have to be wiped out. Not good.

Any way, I consulted various sources on how to do this, including my beloved More iPhone 3 Development and Apple's Introduction to Core Data Model Versioning and Data Migration Programming Guide.

I made the minor changes to my code in the persistentStoreCoordinator and managedObjectModel, and tested in the Simulator. Great, nothing was broken, the changes worked just as advertised.
I continued coding, and a few hours later decided it was time to test on the device.
Bummer, I got this error message:

2011-02-10 14:23:12.470 myApp[9241:307] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[NSURL initFileURLWithPath:]: nil string parameter' 
*** Call stack at first throw: 

0 CoreFoundation 0x33ac0987 __exceptionPreprocess + 114 
1 libobjc.A.dylib 0x3347b49d objc_exception_throw + 24 
2 CoreFoundation 0x33ac07c9 +[NSException raise:format:arguments:] + 68 
3 CoreFoundation 0x33ac0803 +[NSException raise:format:] + 34 
4 Foundation 0x3362b54f -[NSURL(NSURL) initFileURLWithPath:] + 70 
5 Foundation 0x33650157 +[NSURL(NSURL) fileURLWithPath:] + 30 
6 myApp 0x00003537 -[myAppAppDelegate managedObjectModel] + 138 
7 myApp 0x000036fb -[myAppAppDelegate persistentStoreCoordinator] + 302

8 myApp 0x00003407 -[myApp AppDelegate managedObjectContext] + 62 

9 myApp 0x0000302f -[iNspectorAppDelegate application:didFinishLaunchingWithOptions:] + 78 
10 UIKit 0x3209ebc5 -[UIApplication _callInitializationDelegatesForURL:payload:suspended:] + 772 
11 UIKit 0x3209a259 -[UIApplication _runWithURL:payload:launchOrientation:statusBarStyle:statusBarHidden:] + 272 
12 UIKit 0x3206648b -[UIApplication handleEvent:withNewEvent:] + 1114 
13 UIKit 0x32065ec9 -[UIApplication sendEvent:] + 44 
14 UIKit 0x32065907 _UIApplicationHandleEvent + 5090 
15 GraphicsServices 0x33b0ef03 PurpleEventCallback + 666 
16 CoreFoundation 0x33a556ff __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 26 
17 CoreFoundation 0x33a556c3 __CFRunLoopDoSource1 + 166 
18 CoreFoundation 0x33a47f7d __CFRunLoopRun + 520 
19 CoreFoundation 0x33a47c87 CFRunLoopRunSpecific + 230 
20 CoreFoundation 0x33a47b8f CFRunLoopRunInMode + 58 
21 UIKit 0x32099309 -[UIApplication _run] + 380 
22 UIKit 0x32096e93 UIApplicationMain + 670 
23 myApp 0x00002fb3 main + 70 
24 myApp 0x00002f68 start + 40 

Tried again in the simulator, it worked.
Looking at the error trace, something was happening in the managedObjectModel function, and the error message in the first line indicated that the NSURL string was nil. The offending block of code was this:

NSString *path = [[NSBundle mainBundle] pathForResource:@"Datamodel" ofType:@"momd"];
NSLog(@"path: %@", path);
NSURL *momURL = [NSURL fileURLWithPath:path];

I added the NSLog line to print out the contents of the `path` variable, and discovered that it was not nil when running in the simulator, but nil when running on the device.

I went to have a look at the application assets in

/Users/peter/Library/Application Support/iPhone Simulator/4.2/Applications/F2854B27-4750-4DC8-8CB6-A22B036F5DC9\myApp.app

by right-clicking and selecting "Show Package Contents", and noticed that the data model versioning directory was named `DataModel.momd`.
However in my code, the path variable was `Datamodel` (loading a resource of type `momd`), whereas the directory containing the model versions was `DataModel`.
Yeap, this was another case of the simulator and the device behaving differently, this time in how they handle file name cases.

Once I changed my code to
NSString *path = [[NSBundle mainBundle] pathForResource:@"DataModel" ofType:@"momd"];

and ran on the device, it worked.

iOS: ad-hock app distribution for beta testing

I needed to distribute two copies of a new app I'm building to beta testers, and a process Ithough should only take 30 minutes or so, took me half a day.

Apple's iOS Provisional Portal has these instructions (https://developer.apple.com/ios/manage/distribution/distribution.action):


1. Create and Download an iOS Distribution Certificate
2. Create and Download an Ad Hoc Distribution Provisioning Profile
3. Build your application with Xcode
4. Share your application file and the Ad Hoc Distribution Provisioning Profile with the owner of each device
5. Recipients of the application will need to drag the application file and Ad Hoc Distribution Provisioning Profile into iTunes, then sync their iPhone, iPad or iPod touch to iTunes to install
Well, that didn't work. Although I was able to produce a built, create a zip archive of the .app file, install it on the beta tester's iTunes (along side the provisional certificate), after syncing the phone I was getting error messages about either the app not being signed, or the entitlements being incorrect.

After lots of reading, trial and error, I managed to get a configuration that worked, documented here. Thanks to the many authors who helped out, including:


How to create an Ad-hock distribution
Media_http4bpblogspot_malci

I will start from the end of the process so that you know what you should be aiming for. A bit of an anti-climax, I know, but I find it useful to know what my target is.

xCode 3.2.5 has got a very nice distribution feature, accessible via the Build menu.

Once the project is configured properly for this feature to work, Build and Archive will create an .ipa archive that can be opened by iTunes on Windows or Mac. The file can be found in the Organizer. The Organizer can even help you email it to your beta testers, save it to disk, or distribute to an enterprise (that sounds cool, but don't know exactly what it does). Before this feature was put in xCode, people had to do everything manually, and some even wrote their own scripts trying to automate the process.
Media_http2bpblogspot_cqent

For Build and Archive to work, you must build using on the device, not the simulator. If your selected target is the simulator, the Build and Archive option will be disabled. Yep, this cost me an hour.

Steps for getting your ad-hock distribution

1. You can have up to 100 ad hock deployments of your app. For each one, you need the UUID of the beta tester's iphone or ipod touch. This can be found by connecting the device to itunes and accessing its property page. See here for details. Then proceed to the iOS Provisioning Portal, click on "Devices", "Manage", and "Add devices". Fill the blanks with the information you have.

2. You will need a distribution provisioning profile. This can be obtained by going to the iOS Provisioning Portal, click on Provisioning, and then on the Distribution tab. Click on "Create new profile", then fill in the blanks ensuring that Distribution Method is set to "Ad Hock". Submit, refresh a couple of times until you see the Download link, then download the certificate and put is aside for now.

3. Start xCode and open your project. Click on the Resources folder, and with it selected, click on File, New File. Under Code Signing, select Entitlements, and click Next.

4. Name the file "Entitlements.plist", and click "Finish".

5. Find the Entitlements.plist file in Resources, and open it. Add a new row so that the file now has these contents (make sure "Can be debugged" is not checked":

Media_http2bpblogspot_tclgo
6. Go to "Project", "Edit project settings" and scroll down to the code signing section. You need to edit the Code Signing Entitlements with the name of the file you created in step 5, and the Code Signing Identity rows with your valid developer certificate.

Ad-hock-1


7. You are now ready to create the distribution file. Click on Build, Build and Archive. The file is created and the Organizer pops-up. Click on the file to select it, then click on Share. Select the correct distribution identity from the drop-down, and then Save to Disk (or E-mail if you prefer).

8. Attach the .ipa file you created in step 7, along with the distribution provisioning profile from step 2 in an email, USB drive, network drive, or any other distribution method you like, and sent it to your beta tester.

9. With their device connected to iTunes, your beta tester needs to drag-drop the provisioning profile on the iTunes library. Then, double-click on the .ipa file. Once the app is installed on iTunes, it's icon will be visible in the apps library. He can now sync the device to get the app installed.

This worked for me and have done a few deployments without problems. Let me know how it worked for you, or if you came across problems.

UPDATE: Checkout a related post if you are still having trouble with getting your ad-hock distribution to work: http://blog.futureshock-ed.com/xcode-ad-hock-provisioning-certificate-pains

Mongomapper with Rails 3

These are some notes I have taken while creating my first Rails 3 application with MongoDB/Mongomapper as the back end.

After installing RVM, Ruby 1.9.2dev, and Rails 3.0.0.beta4, I followed the instructions here to update a bunch of files (assuming you are running MongoDB locally):

config/initializers/mongo.rb

MongoMapper.connection = Mongo::Connection.new('localhost', 27017)
MongoMapper.database = "#myapp-#{Rails.env}"

if defined?(PhusionPassenger)
PhusionPassenger.on_event(:starting_worker_process) do |forked|
MongoMapper.connection.connect_to_master if forked
end
end

Gemfile:

source 'http://rubygems.org'

gem 'rails', '3.0.0.beta4'

gem 'mongo_mapper'
gem 'rails3-generators'

config/application.rb
(only first 8 lines shown, not change to the rest of the file)

require File.expand_path('../boot', __FILE__)

#require "rails/all"

require "action_controller/railtie"
require "action_mailer/railtie"
require "active_resource/railtie"
require "rails/test_unit/railtie"

Then, I went on to create a model, and to do that I used kristianmandrup's rails3-generators gem:

sudo gem install rails3-generators
rails generate model Book --skip-migration --orm=mongomapper

Edit this model to contain at least one MongoDB key:
class Book
include MongoMapper::Document

key :title, String
key :author, String

timestamps!

# Validations :::::::::::::::::::::::::::::::::::::::::::::::::::::
# validates_presence_of :attribute

# Assocations :::::::::::::::::::::::::::::::::::::::::::::::::::::
# belongs_to :model
# many :model
# one :model

# Callbacks :::::::::::::::::::::::::::::::::::::::::::::::::::::::
# before_create :your_model_method
# after_create :your_model_method
# before_update :your_model_method

end


We'll need a controller to access the Book model:
rails generate controller Book

This creates an empty controller file. Edit book_controller.rb to look like this:

class BookController < ApplicationController
def index
@books = Book.all
end
end

Create a view for this controller and action in app/views/book/index.erb:

<% if notice %>
<p id="notice"><%= notice %></p>
<% end %>
<h1>Books</h1>
<% @books.each do |book| %>
<div class="entry">
<h3><%= book.title %></h3>
</div>
<% end %>

Add the Book routes in the routes.rb file:

Inspector::Application.routes.draw do |map|
resources :books
end

Start the server to see if the application works so far:
rails server

Navigate your browser to http://localhost:3000/books/index. If you get a blank page with "Books" only displayed, then you are doing well, no worries. There are no errors, but also there are no records to display. The easiest/quickest way to add some books at this point is to use the console. Type "rails console", and add a couple of books:

book1 = Book.create(:title => "title 1", :author => "author 1")
=> true
book2 = Book.create(:title => "title 2", :author => "author 2")
=> true

Finally, make sure the rails server is running, and try to access http://localhost:3000/books. If all went well, the two entries we just made will be listed.

PS. Good resources on this subject:
http://www.mongodb.org/display/DOCS/MongoDB+Data+Modeling+and+Rails
http://blog.bitzesty.com/mongodb-with-mongomapper-and-ruby-on-rails

About

Twitter