Showing posts with label rubyrails. Show all posts
Showing posts with label rubyrails. Show all posts

Monday, April 11, 2011

ImageMagick, Homebrew, the NEWS.txt error


Seems like everyone has trouble installing ImageMagick, but everyone has a slightly different problem. In my case I was getting the error:

Error: No such file or directory - /usr/local/Cellar/imagemagick/6.6.7-10/share/ImageMagick/NEWS.txt
To fix this, do "brew edit imagemagick" (or "sudo brew edit imagemagick" if that's how you brew) and find these lines:

# We already copy these into the keg root
%w[NEWS.txt LICENSE ChangeLog].each {|f| (share+"ImageMagick/#{f}").unlink }
and comment out that line of Ruby. Re-run "brew install imagemagick" and it should work.

Tuesday, January 27, 2009

Rails: Database-less ActiveRecord models


It's not unusual in Rails projects to have one or two model classes that don't inherit from ActiveRecord and don't require an associated table in the database. But what if we want half of that? What if we want a model that does descend from ActiveRecord but doesn't exist in the database? I finally found some code for doing exactly that. Here's an example:


class Feedback < ActiveRecord::Base
  validates_presence_of :mailfrom, :comment

  def self.columns
    @columns ||= []
  end

  def self.column(name, sql_type = nil, default = nil, null = true)
    columns << ActiveRecord::ConnectionAdapters::Column.new(name.to_s, default, sql_type.to_s, null)
  end

  column :id
  column :mailfrom
  column :comment
  column :ipaddr
end
I derived this from the code at Caboose's blog. He says he got it from Techoweenie but I can't find it on Technoweenie's site anymore.

So anyway, why would you want this? In Rails, the ActiveRecord class is super powerful. It is of course an ORM first and foremost, but it has other great features. Also, other parts of Rails, ActionView in particular, function at their best if you can provide them with an object descended from ActiveRecord. If you don't have an ActiveRecord object, you have to use form_tag() instead of form_for(), text_field_tag() instead of text_field(), etc. You don't get to use error_messages_for() and you don't get the nifty pre-fills of the model's existing values when you error flash back to the same form.

In my case, I was creating a very simple feedback form so a visitor could provide their email address and leave a comment. The comment would be mailed to the site admins via ActionMailer. I actually had a seperate model, which was descended from ActiveRecord, that made a database record of the time, date, and IP address, but there was no requirement to store the comment itself in the database, so I thought that the Feedback object didn't need to inherit from ActiveRecord. Mistake! Cutting myself off from the best helpers that ActionView offers, something that should have been a dead-simple one-page form became a tedious slog[1] to program. I finally came to my senses and googled around until I found the above code.

I've used ActiveRecord-less models before, so at first I was surprised by my unpleasant experience. Then I thought about it and realized that none of my previous ActiveRecord-less models involved user interaction. They were all "plumbing" and I never needed, or missed, the ActionView helpers. If you're making a view for a model, and that model doesn't inherit from ActiveRecord, you're not doing it The Rails Way.

 [1] "Tedious slog" being relative. I find that Rails raises the bar for ease of (web) programming, to the point where it's actually a shock to deal with the same level of drudgery that PHP inflicts on me on a good day.

Friday, January 23, 2009

EventMachine: a TCP server module for Ruby


I just discovered EventMachine. EM is, at its least, an event-driven library around which you can build a custom TCP server. The nitty-gritty of listening, sending and receiving, and multiplexing connections is all done for you.

That's selling it short, though, because EventMachine can do a lot more. In its own words, EventMachine "provides event-driven I/O using the Reactor pattern." It can be used for other client/server models like serial ports or even interactive keyboard I/O. But it really stands out for abstracting away the low-level hassles of writing a TCP daemon.

Here's a simple Echo service built using EventMachine. (Borrowed from the README file)


require 'rubygems'
require 'eventmachine'

module EchoServer
  def receive_data data
    send_data ">>>you sent: #{data}"
    close_connection if data =~ /quit/i
  end
end

EventMachine::run {
  EventMachine::start_server "192.168.0.100", 8081, EchoServer
}
Here's an example I made. You can pass a class to EventMachine::start_server, and each new connection will create a new instance of your class. That allows you to use instance variables to record distinct state for each connection. This example buffers up the client input until the client sends a ".<CRLF>" a la SMTP, or a maximum of 10 lines.


require 'rubygems'
require 'eventmachine'

class DataBuffer < EM::Protocols::LineAndTextProtocol
  def initialize
    puts "init'ing new instance of #{self.class.to_s}"
    @line_ctr = 0
    @databuf = []
  end

  def receive_data(data)
    @databuf << data
    @line_ctr += 1
    if data == ".\r\n" || @line_ctr == 10
      if data == ".\r\n"
        @databuf.pop
      end
      send_data(@databuf.to_s)
      reset_databuf()
    end
  end

  private
  def reset_databuf
    @line_ctr = 0
    @databuf = []
  end
end

EventMachine::run {
  EventMachine::start_server "127.0.0.1", 8081, DataBuffer
}
And the best part is, I've only been playing with EventMachine for about an hour! I've only begun to understand what it can do.

So, yeah. EventMachine is badass. You should check it out.