Birds-Eye.Net
All things broadband and more...
 
Web Birds-Eye.Net

What's New?

Ruby on Rails (RoR)
Programming Reference


Models
External database connections
Passing current_user into model
Passing object into model
Using static lookup tables
Validates IF
Validates MongoMapper

Views
Dynamically delete form element
Edit create nested data
HTML form field check_box
Layout jQuery datatable module
Select array
Select cascading via JS
Text_area Array
Text_area listing submit
Text field format time

Controllers
Dynamic model selection
Including first item from a sorted desc table
Using from_unixtime on epoch dates
Custom SQL Query Examples

Rack
Integrated NTLM/Kerberos Authentication
Pass-through Authentication w/ NTLM

ActionMailer
Broken links in emails

Rails General
Add, Subtract, Multiply, and Divide
Calculate number of weekdays for date range
Date->Epoch & Epoch->Date
Calculate past/present payroll dates
Extract first letter of each word
Hash of hashes assignment
Using: variable as hash index

jQuery
jQuery accordion MongoDB

Rails Framework Examples

Apotomo Widget Using Erb

MySQL
Converting Julian Dates to Epoch

d3 Charting
Configuration to Work with Rails Apps
A simple bar chart example

Other
Setup VPN on iMac
SSH Key Generation

More to come

 

Dynamic Model Selection within a Controller

By: Bruce Bahlmann - Contributing Author (your feedback is important to us!)

In rails development, where you want to loop through various columns that reference specific models. Rather than create some large nested if or case statement to define each model and perform some method on that model, you can dynamically create a reference (or selection) which then can be used to access the data associated with the model.

Creating a model selection requires the following steps: create a common method across the models you want to select, create the loop that selects the models. In our case, we will show two tables: inventory and manufacturer. Manufacturer table is a lookup table for manufacturers that are associated with records within the inventory table.

[apps/models/manufacturer.rb]
class Manufacturer < ActiveRecord::Base
  establish_connection :apps
  set_table_name "global_manufacturer"

  def lname
    self.name
  end

  has_many :inventory

end

The model above creates a simple method called lname (lookup name). Since you are using dynamic selection, you probably have a number of these tables (like the one below), that reference a column in the main table.

For completeness sake, the following is the relevant aspects of the inventory model which points to the manufacturer table for a list of possible manufacturers available to its inventory records. IMPORTANT NOTE: you really need to use the RIGHT NAMING CONVENTION here for this to work. If you have a model named [Manufacturer] the foreign key used to access that table belonging to the model MUST BE, [manufacturer_id]. If you do not use this type of naming convention, you will find yourself writing a lot of extra code in vein - as the result will not only be ugly, but it won't work.

[apps/models/inventory.rb]
class Inventory < ActiveRecord::Base
...

  belongs_to :manufacturer, :foreign_key => :manufacturer_id
  validate :custom_validation

  def custom_validation

    ## validate 
    errors.add(:manufacturer_id, " - left blank - it is required to save ...") if manufacturer_id.nil?

    if errors.count > 0
      ## Any post processing of errors prior to returning back to edit/new page

    else 
      ## Proceed with any finished processing prior to saving

    end
  end

end

The point of showing the above is the linking to the static lookup table, as well as how to manage error handling for the static lookup table. The inventory table would look something like the following:

Moving now to the controller, we'll perform the task of the dynamic selection.

[apps/controllers/inventories_controller.rb]
...

  @inventory = Inventory.find(params[:id])

  ## Array of lookup tables used for logging changes
  ltArray = ["manufacturer_id","classification_id","location_id","disposition_id","vendor_id","warranty_id"]

  @inventory.attributes.each do |k,v|
    next if k == 'notes'
    next if k == 'lmodified'
    if @inventory.send(k).to_s != params[:inventory][k].to_s
      ## Mark lhash with key (indicating the instance array has been loaded)
      if ltArray.include?(k) 
        comparisonText += ", #{k} changed from ["+
                          "#{@inventory.send(k) == '' ? '' : k[0..-4].classify.constantize.find(@inventory.send(k)).lname}]"+
                          " to ["+
                          "#{params[:inventory][k] == '' ? '' : k[0..-4].classify.constantize.find(params[:inventory][k]).lname}]"
      else
        comparisonText += ", #{k} changed from [#{@inventory.send(k)}] to [#{params[:inventory][k]}]"
      end
    end
  end
  comparisonText.gsub!(/^\,\s/,'')
...

In the controller, we loop through the inventory table columns, and having defined which columns we want to treat special (see ltArray), we can then process these entries and use the column names to access the models associated with them. This can be done by first converting the text of the column name into a model (e.g. manufacturer_id). The conversion process begins with removing the [_id] part of the name - this is done using [0..-4] which is removed from the key [k] assigned in the loop [@inventory.attributes.each do |k,v|]. Once we have just the [manufacturer] key name, we can use classify and constantize to turn the string into the model name [Manufacturer] which can then be used with find, etc.

Note, we need to use [send] to access the object [@inventory] values which are used as arguments for the find. The above code can be used to translate lookup table indexes to common names so that the log shows what [real-world] value actually changed rather than simply show a certain column changed from index x to index y (which is meaningless without the table to make sense of the indexes).

Can Birds-Eye.Net help you or your Company?
Receive your Birds-Eye.Net articles and white papers hot off the presses by adding our RSS feed to your reader.

 

(C) Copyright Birds-Eye.Net, All rights reserved.
It is against the law to reproduce this content or any portion of it in any form without the explicit written permission of Birds-Eye Network Services, LLC. Federal copyright law (17 USC 504) makes it illegal, punishable with fines up to $100,000 per violation plus attorney's fees.