ActiveLdap, belongs_to, and "invalid filter syntax"

After I started using :adapter => 'net_ldap' in ActiveLdap, my belongs_to associations all broke with when constructing a search filter with Net::LDAP

invalid filter syntax (Net::LDAP::LdapError)

The classes look something like this:


 class Person  'uid', :prefix => 'ou=people', 
       :classes => ['top', 'mozillaAddressBookEntry']
   belongs_to :family, :class => 'Family', 
      :foreign_key => 'dn', :primary_key => 'member'
 end
 
 class Family  'uid', :prefix => 'ou=families', 
       :classes => ['top','family', 'mozillaAddressBookEntry']
   has_many :people, :class => 'Person', 
      :wrap => 'member', :primary_key => 'dn'
 end
 

As I found out per this thread, Ruby Net::LDAP apparently can’t handle search filters with “=” or “,” characters, and doesn’t allow escaping with “\3D” or the like.

I switched back to the default Ruby/LDAP adapter, and the belongs_to associations work as expected.

Capifying a Merb application

UPDATE: I was embarrassed that I actually get hits on this post, so I’m adding a stripped down example deploy.rb.

Create a directory named config in the Merb root (not inside dist).

Create your deploy.rb file inside the config directory. Here’s a stripped down version of what I have used:

# ./config/deploy.rb
# Do your merb daemon configuration in ./dist/conf/merb.yml

set :application, "awesome_thingummy"
set :scm_name, "thingummy"
set :repository, "svn://thelese.com/merb/#{scm_name}/trunk"
set :checkout, "checkout"

# =============================================================================
# ROLES
# =============================================================================

role :web, "slice1.automatthew.com"
role :app, "slice1.automatthew.com"

# =============================================================================
# OPTIONAL VARIABLES
# =============================================================================
set :deploy_to, "/var/www/apps/#{application}"
set :user, "deployer"            # defaults to the currently logged in user

# set :scm, :darcs                  # defaults to :subversion
set :svn, "/opt/local/bin/svn"      
set :merb, "/opt/local/bin/merb --merb-root #{deploy_to}/current"

task :spinner do
  run merb
end

task :restart do
  run "#{merb} -k all"
  run merb
end

task :update_code do
  run "#{svn} --quiet #{checkout} #{repository} #{release_path}"
end

task :after_update_code do
  run "ln -s #{shared_path}/log #{release_path}/log"
end

desc "Deploy the app"
task :deploy do
  transaction do
    update_code
    symlink
  end
  restart
end

Use Net::LDAP with ActiveLdap

Prior to version 0.8.2, ActiveLdap required Ruby/LDAP for its underlying connection. This posed an annoyance, if not a problem, as Ruby/LDAP does not exist as a gem. As of 0.8.2, ActiveLdap supports both Ruby/LDAP and the bona fide, gemified Net::LDAP.

The default connection is still Ruby/LDAP, however, and the official docs aren’t abundantly clear on how to make the connections with Net::LDAP. I couldn’t find an answer with Google until after I had puzzled it out myself and was about to write this post. Googling for the answer found for me this post to the ActiveLdap mailing list, which is mostly correct. The value for :adapter should be ‘net_ldap’, not ‘net-ldap’, according to the Constants list at the very bottom of the front page of the Rdocs for ActiveLdap.

Thus:


ActiveLdap::Base.establish_connection(
 :adapter => 'net_ldap',
 :host => 'localhost',
 :base => 'dc=mycooldomain,dc=com', 
 # doo wa doo shbop
 )

Environment-specific setup in Merb

Merb has production and development environments that act much like their Rails counterparts. While there aren’t separate files for environment-specific configuration, you can get the same effect using a case statement at the bottom of merb_init.rb like so.

This is also a good place to stick database configuration when your dev is different than your prod.

Managing PHP fastcgi with Launchd

Because I’m using PHPLDAPAdmin as a stopgap while I build a custom web directory application, I have gotten soiled a bit by PHP. I’m running everything on a headless Mac mini, and I chose to use Mac OS X as the OS for reasons I won’t go into here.

The front-end web server is nginx, which is proxying to php running as fcgi. Pardon me in advance if/when I get the terminology wrong. I tried using the instructions from the Homo Adminus blog, and while both the Bash script method and the spawn-fcgi method work, I could not figure out how to get launchd to manage them.

I hope that some of you are laughing at me at this point, because the problem was (and may still be) totally centered on my ignorance of the fastCGI usage of the php binary. I was being dense about launchd as well. Launchd doesn’t use spawn-fcgi or a custom shell script as the ProgramArguments. Rather, it completely obviates the need for them. This should have been obvious (a phrase that I promise will be common on this blog).

For the edification of the similarly ignorant, here’s a launchd plist that seems to work.

As I understand it, you set the server IP address and port number with the -b argument to the php binary. Homo Adminus adds the -q option (suppressing HTTP Header output) in his Bash script, so I did as well. To arrange for more than one listening process, you have to set the PHP_FCGI_CHILDREN environment variable.

deprec, capserverext, and Ubuntu 6.10 – "sh: [[: not found"

While trying to get Deprec and Capistrano Server Extensions (tutorial) working with Ubuntu 6.10, I ran into a number of hurdles. One was this error when running any variant of deploy (during the svn co command):

** [out :: hostname] sh: [[: not found

Googling got me this thread in the Slicehost forums. Capistrano assumes that the default shell is bash, but that is no longer true for recent versions of Ubuntu. Edgy onwards are apparently using dash as the default.

To fix this, add a task named :set_shell_to_bash to deploy.rb. You can then run this task at the appropriate time using an after_ or before_ callback:


task :after_setup_ssh_keys_for_admin_user do
set_shell_to_bash
end

desc "Make sure the deployment user's shell is bash"
task :set_shell_to_bash do
sudo_with_input "chsh -s `which bash` #{user}"
end

Update: Saimon, the author of Capistrano Server Extensions, informs me that the default shell on Edgy and upwards is not actually dash, something I should have checked before blathering about it.

I’m not sure why my deployment user had dash as the shell, but I will see if I can reproduce the situation.

"Retarded, verbose hunchback version of s-expressions"

XML, of course.

From Delusions of skill and grandeur

via Giles Bowkett

What’s better than ActiveMDB?

Most anything.

For instance, here is an article on how to use MDB Tools to export everything from your Access database and get it slurped into something sane.

The only reason I develop and use ActiveMDB is that I regularly run into Access dbs that are in something loosely resembling production. I can’t get rid of them, and I don’t want to keep doing the dump-migrate-report rigamarole. ActiveMDB lets me snoop around very easily, and it lets me extract data with Ruby.

How to use ActiveMDB in Ruby on Rails

First, let me say: You probably shouldn’t use ActiveMDB in Rails. ActiveMDB is intended for exploration and for exciting action-movie narrow escapes from Access databases.

ActiveMDB is READ ONLY.

If you really, really need to, though, here’s how:

Install MDB Tools http://mdbtools.sourceforge.net/

Install the ActiveMDB gem:
gem install activemdb

Require the library somewhere. ./config/environment.rb might work
require 'active_mdb'

In a model file (e.g. ./app/models/windows_malware.rb) create a model that subclasses ActiveMDB::Base.
Set the path to the .mdb file and the name of the table.

class WindowsVirus < ActiveMDB::Base
  set_mdb_file '/var/db/windows_support.mdb'
  set_table_name 'Windows_Virises'
end

You can use the ActiveMDB model in your controllers much like you would an ActiveRecord model. The only find methods at the time of this writing are find_all and find_first. These methods take a hash that specifies the conditions for the WHERE clause. The keys to the hash are symbols representing the field names in the Access database. ActiveMDB will let you use downcased-underscored versions of the field names from the db. E.g. you can use :executable_name for an Access field “Executable Name”. When the field type is text or char, the WHERE conditions use LIKE with wildcards before and after the search value.

viruses = WindowsVirus.find_all :executable_name => 'virus.exe', :severity => 2

Once you have an instance of an ActiveMDB class, you can use the same Rails-like field names as methods to retrieve attributes:

return unless viruses.first.executable_name =~ /exe/

How to use ActiveMDB in Ruby on Rails

First, let me say: You probably shouldn’t use ActiveMDB in Rails. ActiveMDB is intended for exploration and for exciting action-movie narrow escapes from Access databases.

ActiveMDB is READ ONLY.

If you really, really need to, though, here’s how:

Install MDB Tools http://mdbtools.sourceforge.net/

Install the ActiveMDB gem:
gem install activemdb

Require the library somewhere. ./config/environment.rb might work
require 'active_mdb'

In a model file (e.g. ./app/models/windows_malware.rb) create a model that subclasses ActiveMDB::Base.
Set the path to the .mdb file and the name of the table.

class WindowsVirus < ActiveMDB::Base
  set_mdb_file '/var/db/windows_support.mdb'
  set_table_name 'Windows_Virises'
end

You can use the ActiveMDB model in your controllers much like you would an ActiveRecord model. The only find methods at the time of this writing are find_all and find_first. These methods take a hash that specifies the conditions for the WHERE clause. The keys to the hash are symbols representing the field names in the Access database. ActiveMDB will let you use downcased-underscored versions of the field names from the db. E.g. you can use :executable_name for an Access field “Executable Name”. When the field type is text or char, the WHERE conditions use LIKE with wildcards before and after the search value.

viruses = WindowsVirus.find_all :executable_name => 'virus.exe', :severity => 2

Once you have an instance of an ActiveMDB class, you can use the same Rails-like field names as methods to retrieve attributes:

return unless viruses.first.executable_name =~ /exe/

Request for .mdb files

If there are any users of ActiveMDB out there (and rubyforge seems to indicate a few downloads), I would be much pleased to hear grievous complaints about how badly ActiveMDB works.

More importantly, if you have any .mdb files you’re willing to share, I would dearly love to see them.

Drop me a line: auto matthew at g mail dot com

ActiveMDB 0.2.2 released

gem install activemdb

Improvements mostly to documentation. I used ActiveMDB to migrate an Access db to LDAP, and that turned up lots of little bitsy problems that I fixed or patched up.