Categories
Code learning rails ruby

ActiveAdmin on Heroku (Rails 3.1)

I wrote a post detailing some issues I had with ActiveAdmin and Heroku with Rails 3.1.

It’s probably entirely out of date, but in case its of any use for you, it’s still archived here.

Categories
blog Code learning rails

Ruby on Rails: Get some random records

EDIT AGAIN: Much better..

To get a ‘num_reqd’ array of random objects, you can use something like this.

  named_scope :large, :conditions => ['image_file_name IS NOT ?', nil]
  named_scope :small, :conditions => ['small_image_file_name IS NOT ?', nil] 

  def self.get(num_reqd,features_arr=[],size="large")
    if size=="small"
      collection = Feature.small
    elsif size=="large"
      collection = Feature.large
    end
    
    return collection if collection.size <= num_reqd

    # num_reqd.times{feature=self.random(collection); features_arr.push(feature) unless features_arr.include?(feature)}
    features_arr = collection.find(:all, :limit => num_reqd, :order => 'rand()')

    if features_arr.size < num_reqd
      return Feature.get(num_reqd, features_arr, size)
    else
      return features_arr
    end
  end

EDIT: It's much cleaner and easier to use something in the form below, though the following is probably useful in some cases and is possibly interesting as a code snippet.

User.find(:all, :order => 'rand()')


---- end edit.

Working from a baseline of the code found here at almosteffortless.com I've extended a 'random record grabber' to get a specific number of unique records from a Rails data table.

Basically - the random method makes a database call to get the ids of a table, and sends back a random entry. self.get is a recursive method which provides a 'total number required' and a base array to start from (if you wish to specify entries to appear in the otherwise 'random' list). First year computer science should help get your head around the rest!

def self.random
    ids = connection.select_all("SELECT id FROM features")
    find(ids[rand(ids.length)]["id"].to_i) unless ids.blank?
  end

  def self.get(num_reqd,features_arr=[])
    num_reqd.times{feature=self.random; features_arr.push(feature) unless features_arr.include?(feature)}

    if features_arr.size < num_reqd
      return Feature.get(num_reqd, features_arr)
    else
      return features_arr
    end
  end

Be aware, there is more efficiency to be found in the database call (i.e. it should be cached). Also, you'll want to be sure there are at least 'num_reqd' items in the database.

Categories
learning meaningful labor rails ruby

Simple Thinking Sphinx on Dreamhost

*** Please note – this will probably not work (at all) (for more than a day of light use) without Cron use. And isn’t at all authorised by Dreamhost!! ***

For a recent client project I’ve used a Dreamhost unlimited account, which for value compared with the resources available and the fact that you don’t have to do any building or setting up of the server environment makes it an easy win for a site that’s not going to have a huge amount of traffic or a large amount of processing.

Post-launch I got to work putting together a basic search engine and here’s a quick run through of the steps it took to get a very simple Sphinx instance working on Dreamhost, and a few hurdles thrown in the way by various googled articles.

Development Environment

Using the guide from FG install Sphinx locally:

curl -O http://sphinxsearch.com/downloads/sphinx-0.9.8-rc2.tar.gz
tar zxvf sphinx-0.9.8-rc2.tar.gz
cd sphinx-0.9.8-rc2
./configure
make
sudo make install

then install the TS plugin into your application

script/plugin install git://github.com/freelancing-god/thinking-sphinx.git

Any problems with that, check out the FG page linked.

Getting a basic search going

Following tutorials such as the Sphinx Railscast will get you there pretty quick.

In your searchable model you need to define an index


class Page < ActiveRecord::Base
  define_index do
    indexes :title
    indexes :long
    indexes :short
  end ...

Run the indexer and start the Sphinx instance:


rake thinking_sphinx:index
rake thinking_sphinx:start

After this you'll be able to search on your object. So using script/console

@searched_pages = Page.search("query")

will return what you're looking for!

Setting up Dreamhost

First things first you need to install Sphinx in your local area, as posted by Hugh Evans:

cd ~/
mkdir -p local
wget http://sphinxsearch.com/downloads/sphinx-0.9.8.1.tar.gz
tar -xzf sphinx-0.9.8.1.tar.gz
cd sphinx-0.9.8.1/
./configure --prefix=$HOME/local/ --exec-prefix=$HOME/local/
make
make install

then set up the PATHs

echo "export PATH="$PATH:~/local/bin"" >> ~/.bash_profile
source ~/.bash_profile

You can choose to set up a CRON task at this point too, but I'm not going into that.

Also at this point in the there's talk of using Sphinx being anti TOS in DH's eyes... but we'll see does the process get killed or not!

Configuring Sphinx for DH

Create a file called sphinx.yml in the RAILS_ROOT/config/ folder.

Because Dreamhost uses an externally referenced MySQL server instead of localhost you need to set up the sql_* parameters:


  sql_host: "mysql.YOURDOMAIN"
  sql_port: 3306
  sql_user: "USER"
  sql_password: "PASSWORD"
  sql_database: "DATABASE"

And because you installed Sphinx in your local area:


  bin_path: '/home/YOURUSERNAME/local/bin'

Finally, after setting whatever memory/fine tuning settings you wish/require set up the locations for the Sphinx files:


  config_file: "/home/YOURUSERNAME/DOMAIN.co.uk/shared/production.sphinx.conf"
  searchd_log_file: "/home/YOURUSERNAME/DOMAIN.co.uk/shared/log/searchd.log"
  query_log_file: "/home/YOURUSERNAME/DOMAIN.co.uk/shared/log/searchd.query.log"
  pid_file: "/home/YOURUSERNAME/DOMAIN.co.uk/shared/log/searchd.production.pid"
  searchd_file_path: "/home/YOURUSERNAME/DOMAIN.co.uk/shared/db/sphinx"

That should be you ready to start deploying.

Deploying

Using Git + Capistrano for deployment (and Passenger for the http server) my deploy.rb's namespace area looks like this:


namespace :deploy do
  task :restart do
    after_symlink
    restart_sphinx
    run "touch #{deploy_to}/current/tmp/restart.txt"
  end
  
  task :start do 
    # nothing  (this avoids the 'spin' script issue)
  end
  
  desc "Re-establish symlinks"
  task :after_symlink do
    run <<-CMD
      rm -fr #{release_path}/db/sphinx &&
      ln -nfs #{shared_path}/db/sphinx #{release_path}/db/sphinx
    CMD
  end
  
  desc "Stop the sphinx server"
  task :stop_sphinx , :roles => :app do
    run "cd #{current_path} && rake thinking_sphinx:stop RAILS_ENV=production"
  end

  desc "Start the sphinx server" 
  task :start_sphinx, :roles => :app do
    run "cd #{current_path} && rake thinking_sphinx:configure RAILS_ENV=production && rake thinking_sphinx:index RAILS_ENV=production && rake thinking_sphinx:start RAILS_ENV=production"
  end

  desc "Restart the sphinx server"
  task :restart_sphinx, :roles => :app do
    stop_sphinx
    start_sphinx
  end

end

There's probably a neater way to do this, but basically this makes sure Sphinx's indexes and conf files live in the shared deployment folder.

I recommend you try all this in a staging area first, obviously... and you can use Dreamhost's control panel to set up a staging subdomain with a new database in whatever fashion you prefer.

Any problems with this script flag them up, please! This is as much for my future reference as you googlies out there.

Categories
learning meaningful labor rails

Ruby Uninitialized Constant Error (Mental Note)

The reason I always get initialized constant errors occurring in Ruby is accidentally naming models the plural form of the database table name and not letting Rails automatically create the pluralisations.

script/generate scaffold contact_skill contact_id:integer skill_id:integer description:string
not
script/generate scaffold contact_skills ...

(This reason is one I constantly forget, and Google never helps me. Now I will not forget)

—–

edit: I’ve had a LOAD of google hits from this search query in the last few days, if this helps you or doesn’t please leave a comment to make this article more complete.

Categories
apple brands learning reciprocal affection

Sony Ericsson Phone Mac Crash Bug

Courtesy of this fella http://www-users.kawo2.rwth-aachen.de/~razzfazz/k750igrabber/ and thanks to this fella (via google search)
http://www.mattheweaves.co.uk/2005/10/25/sony-ericsson-k750i-quickshare-mobile-phone-mac-osx-104-tiger-kernal-panic-crash-fix/
it appears there is indeed a way to stop my k800i crashing whenever I unplug it’s usb lead from my macbook pro. This little driver package disables the unused ports in the usb interface (with the sony ericsson devices). Next time I reboot I’ll confirm if it works or not, but this is good – hopefully I can recharge my phone and not risk a black curtain of doom each time!

–update–

So it appears it isn’t working (at all) but I’ll look into it again soon. Hope it might work for you.

Categories
accessibility learning rant xhtml

Getting around QOL (aka JavaScript execution in Safari)

QOL is Queen’s University Belfast’s student intranet system which allows centralised delivery of lecture content and course material to enrolled students. Unsurprisingly it doesn’t work properly in Safari as it relies heavily on (old school) JavaScript to build page content (not just modify its appearance in a delightfully DOM manner)

node_1 = node.addItem(new TreeNode('node_1','doc.gif','doc.gif','',false,true));
element = node_1.addElement(new elemHyperLink('Student Handbook-2007-08.doc','JavaScript:downloadResource(289314);','','','Student Handbook'));

element = node_1.addElement(new elemText('(92.50 KB)',''));
element = node_1.addElement(new elemImageLink('Download Times', '../images/clock.gif','',0,'top','JavaScript:showDownloadTimes(94720,289314)'));

Yuck. From the image below you can see the Lectures folder has been clicked to fold it out, but due to the JavaScript issue it does not.Queen's Online has some accessibility issues with javascriptYou can see there is an element: JavaScript:downloadResource(289314); in the code which is the type of link behind any given resource. I’ve never noticed this before, but if you extract that link from the page source (Cmd+Alt+U in Safari, Cmd+U in Firefox) and enter it into the Page Address bar, click enter, it will execute the JavaScript right there and download the file to your default location.