Archive for January 2012
Cocoa Programming for Mac OS X, 4th Edition: Chapter 3 Challenge
Howdy. I previously wrote some entries about the solutions to the challenges in the Cocoa Programming book, 3rd Edition, by Aaron Hillegass. The 4th edition is good. Like the first edition, however, I find the description of the challenges to be a little vague.
I think he does that on purpose. The solutions usually are simpler than they appear.
The Chapter 3 challenge is, “NSDateFormatter’s setDateFormat:
to customize the format string on the date objects in your LotteryEntry
class.”.
Here’s what you do.
- Look for
NSDateFormatter
in the Xcode documentation. Once you find it, search for thesetDateFormat:
method. You’ll find that you have to send a string to the method. Perhaps most useful is a link at the top of the class to the “Data Formatting Guide.” Once there, click to the “Date Formatters” page. Aha… here’s where the good info it. - Search again for the method name — but only search on this page — for
setDateFormat:
. You’ll find examples of the type of string that you can use for the date formatter. Copy one of those strings. It will look something like:@"yyyy-MM-dd 'at' HH:mm"
or@"yyyy'-'MM'-'dd'T'HH':'mm':'ss"
- Open LotteryEntry.m in your editor window and find the
- (NSString *)description
method implementation. - What you’re going to do is to replace the formatting that you entered during the chapter with your new format. Your previous method looked like:
- (NSString *)description { NSDateFormatter *df = [[NSDateFormatter alloc] init]; [df setTimeStyle:NSDateFormatterNoStyle]; [df setDateStyle:NSDateFormatterMediumStyle]; NSString *result; result = [[NSString alloc] initWithFormat:@"%@ = %d and %d", [df stringFromDate:entryDate], firstNumber, secondNumber]; return result; }
- You want to replace the messages that your sending to your date formatter. Your new method should look like this (with the date string you found):
- (NSString *)description { NSDateFormatter *df = [[NSDateFormatter alloc] init]; [df setDateFormat:@"yyyy-MM-dd 'at' HH:mm"]; NSString *result; result = [[NSString alloc] initWithFormat:@"%@ = %d and %d", [df stringFromDate:entryDate], firstNumber, secondNumber]; return result; }
That’s it! Run your program and look at the log to see the new format. You can browse through the documentation a bit more to learn more about creating custom formats.
Paperclip, S3 & Delayed Job in Rails on Heroku – Jan 2012
Edit: I forgot to mention here that with Paperclip 2.4.5 you have to use the ‘paperclip-aws’ gem in order for Paperclip to work with Amazon’s newer ‘aws-sdk’ gem. That is no longer true with Paperclip 2.5.
I followed this good tutorial on how to push paperclip image processing to the background with delayed_job. My Rails app is deployed to Heroku on the cedar stack. I’ve had problems with the NoMethod errors using delayed_job 3.0.0, so I downgraded to 2.1.4. Also using paperclip version 2.4.5. In the end, I found that I could ditch the struct presented in the aforementioned tutorial and just call handle_asynchronously on my reprocessing method. This is what the codes looks like:
class Image < ActiveRecord::Base attr_accessible :profile_pic, :caption, :note, :pic_file_name, :pic_content_type, :pic_file_size, :pic_updated_at, :pic, :pic_attributes, :processing belongs_to :imageable, :polymorphic => true # Added for paperclip-aws def self.s3_config @@s3_config ||= YAML.load(ERB.new(File.read("#{Rails.root}/config/s3.yml")).result)[Rails.env] end has_attached_file :pic, :styles => { :large => "500x500>", :thumb => "100x100>", :tiny => "50>x50>", :smallest => "24>x24>" }, :default_url => '/:attachment/:style/missing.png', # Added for paperclip-aws :storage => :aws, :s3_permissions => :authenticated_read, :path => "images/:id/:style/:filename", :s3_credentials => { :access_key_id => self.s3_config['access_key_id'], :secret_access_key => self.s3_config['secret_access_key'] }, :bucket => self.s3_config['bucket'], :s3_protocol => "https" validates_attachment_content_type :pic, :content_type => [ /^image\/(?:jpeg|gif|png)$/, nil ] # How to implement on Heroku with processing in the background # http://madeofcode.com/posts/42-paperclip-s3-delayed-job-in-rails # cancel post-processing now, and set flag... before_pic_post_process do |image| if !image.processing && image.pic_changed? image.processing = true false # halts processing end end # call method from after_save that will be processed in the background after_save do |image| if image.processing processImageJob(image) end end def processImageJob(image) image.regenerate_styles! end handle_asynchronously :processImageJob # generate styles (downloads original first) def regenerate_styles! self.pic.reprocess! self.processing = false self.save(:validations => false) end # detect if our source file has changed def pic_changed? self.pic_file_size_changed? || self.pic_file_name_changed? || self.pic_content_type_changed? || self.pic_updated_at_changed? end end