views:

153

answers:

6

I would like to populate various tables in my database after a new customer signs up to use our web application. I'm wondering what the best way to do this is, the main requirement being that it should not require any intervention by me. Most of the data is static (but can be changed by the customer later (like preferences for example)), but will obviously need the customer's ID as a way of linking the created records to this customer.

I considered putting a few

Object.create(:customer_id => @customer.id, :yummy => "maybe", :etc => true)

statements in the controller that handles signups, but that annoying little alarm bell that tells me there's a better way is going off again!

Thanks in advance for any suggestions!

Gav

A: 

two ways

  1. a trigger function in your database that does this
  2. a callback in your user model on creation
Omar Qureshi
+2  A: 

In your controller

class AccountController < ApplicationController
after_filter :populate_db  :only=>[:register] 
  def populate_db
    # whatever stuff
    Account.populate
  end
end

And put the logic inside your model:

class Account < ActiveModel::Base
  def populate
  # your logic
  end
end
khelll
Nice and clean, thank you very much!
Gav
+3  A: 

The problem with khelll's solution is that if you create a new Account using from outside of the register action (for example, in an admin module), it's database won't be populated.

So I'd prefer something like the following :

class Account < ActiveModel::Base
    def after_create
        populate
    end

    private
    def populate
        # Your logic
    end
end

The after_create callback will be called after any account creation.
That's more MVC and DRY compliant ;)

Damien MATHIEU
It's a good solution but only if the event is exactly attached to account creation.
khelll
Well apparently, Gav required to populate his database when the account is created.Anyway if you need to populate it every time your account is saved, an after_save callback would do the trick.
Damien MATHIEU
This would be a "business logic" to decide when to populate database, so having it in model rather than in controller feels more reasonable for me too. Be it in after_create event or hidden in somewhere else inside model functions.
Priit
A: 

Can you not just set defaults in your database?

Gareth
Sadly not. On account creation many of the tables need several records creating by default, as other application logic relies on this data being present to function properly.
Gav
A: 

@Omar Qureshi You shouldn't use trigger function in your database - there are many features that can be done by them, but ActiveRecord is database-agnostic and it has callbacks that handle such things that triggers can. Using something that links you to a specific DB system is wrong.

@dmathieu's answer seems to be the best. And you should consider using Factory girl - it's a great tool for populating the DB.

Using something that links you to a specific DB system is right more often than it is wrong. Perhaps you should do a little studying up on database performance tuning. Very few business applications need to be datbase agnostic.
HLGEM
What happens in 5 years time, when you aren't using Ruby on Rails but are using the super brand spanking new framework (Java in Jails?) the code that you have written in your callback is now used only for a reference to be repeated later on in life, however, the database which you now use is a lot less likely to change (chances are you will NEVER change your db) and as such the trigger that you used previously is now still valuable.I believe this is "Framework agnostic"?
Omar Qureshi
Java in Jail... classic :-)
Gav
@Omar Qureshi - we're speaking of rails which has a db-agnostic ORM and you really should stick with it. there are, of course, up and downsides of this way, but this is definitely the rails way. if you're trying to worry about changing framework(???) in 5 years, then you definitely should create your own app framework, orm, http server and database, probably.
A: 

I'm using a YAML file to populate more than ten tables in database during signup. This approach has some positive side-effects for me:

  1. I can easily change the contents of the seed data for new account
  2. It is very easy to add localized versions of initial content, i can let YAML files translated easily through 99translations.com
  3. I'm planning to add data import feature later on where new clients can import their data during or right after signup so they can just take the import file template and customize it for their own needs.

There have been some downsides too:

  1. Inevitably, when data schema changes, sometimes i have to modify all localized versions of these files.
  2. It is one piece of ugly code i have that maps the foreign keys between all the new records. Maybe i can use some schema descriptors here...

As i get around 300 new signups in a day, it's too early for me to worry about performance.

Priit