Monday, June 6. 2011Ruby's shallow copies of hashes
When you try to copy a Ruby hash using .dup or .clone, you get what is called a "shallow" copy. The data in the hash below the first level just seems to be referenced, so if you have a hash within the hash, and try to change a value in the deeper hash, the value is changed even for the original hash you ran the .dup on. To get a full ("deep") copy of a hash, you have to run an inelegant hack using Marshal to copy it: copy_hash = (Marshal.load(Marshal.dump(source_hash))). This apparently applies to arrays too. See the code below for an example, and I hope this saves you hours of debugging.
Saturday, January 29. 2011Rails validations with accepts_nested_attributes_for and _destroy
I was recently working on a Rails app that has a form with a parent item and child items on the same form. Ryan Bates' complex form examples is a good place to start with this. That code will give you a simple form setup with some Javascript for adding and removing rows of children.
It works pretty well, except that in my case, I needed to ensure that each parent had a minimum of one child. I had a validation which checked for this, but it only worked for creating new records. If I removed all the child rows during an edit, the form would still save successfully. It turns out that the key is in the Rails documentation: "Note that the model will not be destroyed until the parent is saved." So my validation was still happily finding a child row, even though it was set to be deleted. It took me some time before I found the right way to check for this, but the marked_for_destruction? method seems to do the trick. Here's my code:
class Project < ActiveRecord::Base
has_many :tasks
accepts_nested_attributes_for :tasks, :reject_if => :all_blank, :allow_destroy => true
def validate
# require a minimum of one task
undestroyed_task_count = 0
tasks.each { |t| undestroyed_task_count += 1 unless t.marked_for_destruction? }
errors.add_to_base 'There must be at least one task' if undestroyed_task_count < 1
end
end
Hope this helps someone! Thursday, November 25. 2010My first attempt at a mobile web app
Is this thing on? So it's been a forever since I've blogged, but we'll see if I still can. Happy Thanksgiving at least!
Anyway, I've been wanting to build stuff for my iPhone. While I've been experimenting with Objective C for a native app, I wanted to actually build and publish something. So I have abandoned my Objective C code snippets for now and decided to go with things I know and build a Ruby on Rails site. There are various libraries to let you style a site for mobile browsers. I went with jQTouch, which is covered pretty well by these Railscasts and Peepcode screencasts. I like using the German-English dictionary site Beolingus, but I wanted to use it more easily on my iPhone. It turns out the data is downloadable, so I decided to build a web application with mobile front-end. Here it is: Denglisch (that's a term for English and German mixed together) I really wanted to build the site in Rails 3, but most of my stuff is hosted on Dreamhost, and I've read about various problem getting those apps running right now. So it's done in Rails 2.3.10 instead. The Rails side is pretty simple, just one model for the data, a rake script to import the textfile into the database, one controller and two actions. Then there's a little bit of jQuery Javascript code to handle the Ajax form submission. ![]() Anyway, I've tested this on my iPhone...I'm curious to hear if it works for the iPad and other mobile devices. It was a good hobby project anyway. Have fun! Wednesday, June 17. 2009One of those Non-descriptive Errors
This one stumped me for a while today. I had an application to deploy which worked fine in development. Deploying to production led to this error:
/usr/local/lib/ruby/gems/1.8/gems/activesupport-2.0.5/lib/active_support/dependencies.rb:249:in `load_missing_constant': Expected /myapp/releases/20090617160914/app/models/widget.rb to define Widget (LoadError) Googling that error turned up lots of pages for Rails 1.2.x and issues with underscores in names. None of it applied. Widget was definitely being defined in widget.rb. Following the stack trace it appeared that the error was thrown in the Ultrasphinx plugin. After trying a lot of other things, I decided to comment out the Ultrasphinx code in the model and retry. The error changed to this, which was helpful: Errno::EACCES: Permission denied - /myapp/releases/20090617160914/public/widget/myfile This model was also using the file_column plugin, and the underlying error was just a permissions problem in the file attachment target directory. I fixed the permissions and put the Ultrasphinx code back in the model, and all was happy. If only that permissions error had shown up first! Thursday, January 29. 2009MAMP and the Ruby MySQL Gem
Update 2011-09-18: See here for the most up-to-date instructions (MAMP 1.9). I got it working on 2.0, but experienced some of the same problems other commenters noted). See also these instructions for MAMP 1.8.
After much frustration, I found a way to get the Ruby mysql Gem installed and talking to my MySQL server on MAMP. Credit goes largely to "Hootbah" who followed a similar path to get MAMP talking to Perl's MySQL library. Here's the steps I followed for MAMP 1.7.2:
Sunday, December 7. 2008Grepping from Ruby
I recently needed to run through one data file, pull a number, and look that number up in several other data files. So in Ruby, I first opened the initial file, pulled the number, and then opened the other files, iterating through every line until I found a match, then call break to move on. This worked, but it was sort of slow.
It occurred to me that I could use grep to see if the number was in the other files. So I had to figure out how to call it from Ruby. Here's what I came up with: The speed improvement depends on how many searches you're doing and the size of the files you're searching, but in a quick test the grep calls were 5x faster. Friday, October 10. 2008'Shoulda' Tested My App
Shoulda is a handy plugin for Rails (now a Gem), which makes writing tests easier. It's worth checking out. Shoulda has been very helpful with a big Rails project I've been working on all summer, and I submitted a couple small contributions and bug fixes. I was surprised to see my name mentioned in the newest release, but I appreciate it, and it was fun helping out!
Tuesday, September 16. 2008Rake and Constants
Here's a gotcha that I came across today: don't define a constant as something in one Rails rake task file, and then define the same constant as something different in another file, because the last constant will supercede them all:
a.rake: DATA = 'Hi there!' desc "Test A" task :test_a do puts DATA end b.rake: DATA = 'Hallo!' desc "Test B" task :test_b do puts DATA end $ rake test_a Hallo! $ rake test_b Hallo! I guess this happens because Rake is loading all of the task files before running the requested task. There's probably a way to namespace the constant, but I need to do more research on that. In the meantime I'll use different constant names! Thursday, May 22. 2008Git is Fun
I was initially disappointed when it was announced that Ruby on Rails was moving its version control system from Subversion to Git. There's enough to keep up with in Rails that I didn't relish having to keep up with this as well. It wasn't so much that Rails was moving, but related code began to move too, so we're currently in this limbo where many plugins have both git and soon-to-be-deprecated SVN repositories, and it's just another detail to keep track of. Hopefully there will be tools to sort all this out soon.
I like my SVN GUI tools, but it turns out that git works pretty well on Windows under Cygwin, if you can live with the command line. It's certainly sufficient for cloning plugin repositories. I could take or leave git by itself, but I love GitHub. They make it so easy to fork an existing project, make your own changes to it, and share it back with the world. Your changes can easily be pulled back into the original projects, too. I've been able to make a couple of small contributions to shoulda and acts_as_xapian. So git is fun after all, and I'm looking forward to using it more; especially when the GUI tools show up. Monday, March 10. 2008Determining Image File Types in Ruby
Today I came across a PNG file that had been uploaded from a browser with a .JPG extension and image/jpeg MIME type. It's too bad that MIME types are apparently unreliable when it comes to file uploads. I went looking for a way to determine the file type by actually reading the file. This is probably a solved problem, but I was unsuccessful Googling for the answer. I came up with the following Ruby method which decides the image file type using up to the first 10 bytes:
def image_type(file) case IO.read(file, 10) when /^GIF8/: 'gif' when /^\x89PNG/: 'png' when /^\xff\xd8\xff\xe0\x00\x10JFIF/: 'jpg' when /^\xff\xd8\xff\xe1(.*){2}Exif/: 'jpg' else 'unknown' end end This works well on a small set of test files (400+ from a browser temp files directory). Let me know if there's a case where this code doesn't work, or if there's a better solution in general. Update: This idea was expanded and found its way into a gem: ruby-imagespec. Credit for that goes to Brandon Anderson, Michael Sheakoski, and Dimitrij Denissenko.
(Page 1 of 2, totaling 14 entries)
» next page
|
CategoriesQuicksearchArchivesSyndicate This Blog |