Graal Forums  

Go Back   Graal Forums > Development Forums > NPC Scripting > Code Gallery
FAQ Members List Calendar Today's Posts

Reply
 
Thread Tools Search this Thread Display Modes
  #1  
Old 03-26-2011, 11:57 PM
fowlplay4 fowlplay4 is offline
team canada
fowlplay4's Avatar
Join Date: Jul 2004
Location: Canada
Posts: 5,200
fowlplay4 has a reputation beyond reputefowlplay4 has a reputation beyond reputefowlplay4 has a reputation beyond reputefowlplay4 has a reputation beyond reputefowlplay4 has a reputation beyond reputefowlplay4 has a reputation beyond reputefowlplay4 has a reputation beyond reputefowlplay4 has a reputation beyond reputefowlplay4 has a reputation beyond reputefowlplay4 has a reputation beyond reputefowlplay4 has a reputation beyond repute
Active Record

What is Active Record?
My first experience with active record patterning was with Ruby on Rails, it was amazing to see all the SQL C(reate)R(ead)U(pdate)D(estroy) work disappear. You can read about it more here.

Feel free to ask any questions, comments, etc.

Advantages
- Automatically converts SQL data into their respective Object form
- Handles nearly all SQL business for you
- Dynamic Query Builder
- Easily Implemented

Disadvantages
- A little bit slower than directly implementing SQL due to Object generation, and dynamic query building. I haven't done that much testing but the biggest performance increase comes from disabling SQLite's file sync, after that I was able to create 10000 Objects in one run in 2~ seconds.
- No relationship (I.e: belongs to, has many) support yet, but if there's interest I will go that route.

Example Setup

DB-NPC: Object

PHP Code:
function onCreated() {

  
// DB Migrations
  
this.migrations = {
    {
"new""acct:string""number:integer"}, // Creates Table
    
{"seed"}, // Calls seed()
    
{"add_index""acct""number"},  // Adds Index to Table
    
{"echo""Migrations Completed!"// Optional Message
  
};
  
  
// Configuration
  
  // To Reset DB Set:
  //this.resetdb = true;
  
  // Table Prefix
  //this.table_prefix = "test_";
  
  // Set Exact Table
  //this.table = "some_table_name";
  
  // Model Object's Specific Class
  // Comment out if not-required
  
this.model_class "activerecord_object_" this.name.lower();
  
  
// Model Functionality
  
this.join("activerecord_model");
}

function 
seed() {
  
// Creates some example data
  
for (aallplayers) {
    
this.create({"acct=" a.account"number=" int(random(10000,90000))});
  }
  
// Alert RC
  
echo("Seeded " this.table " with " allplayers.size() @ " entries!");
  
// Successful
  
return true;
}

public function 
validations(obj) {
  
// Model specific validations
  
return true;
}

public function 
relationships() {
  
// Planned in future update if there's interest.
  // I.e: hasmany(objects, through_column)

class: activerecord_object_object

PHP Code:
// Returns the pretty string version of the object
public function pretty() {
  return 
0+this.number SPC this.acct;

Example

Just a small example showcasing the CRUD functionality.

PHP Code:
function onCreated() {
  
test_activerecord();
}

function 
test_activerecord() {
  
// Reset Query Builder
  
Object.reset();
  
// Create
  
for (temp.0temp.10temp.i++) {
    
temp.obj Object.create({"acct=fowlplay4""number=" 0+temp.i});
    
assert_not_null(temp.obj"Object Creation");
  }
  
// Read
  
temp.obj Object.first();
  echo(
temp.obj.pretty());
  
assert(temp.obj.pretty(), "Objects Pretty Method");
  
// Update
  
temp.obj.acct "Shenanigans";
  if (
temp.obj.save()) {
    echo(
"Object saved successfully!");
    
assert_success();
  } else {
    
assert_failure("Object saving");
  }
  
// Dump (Alternate Reading/Debug Function)
  
temp.obj.dump();
  
// Save ID for Verification Later
  
temp.obj_id temp.obj.id;
  
// Destroy
  
temp.obj.destruct();
  
// Verify Destroy
  
temp.obj Object.find(temp.obj_id);
  if (
temp.obj == NULL) {
    echo(
"Object was destroyed");
  }
  
assert_null(temp.obj"Object Destroyed");

Query Builder Example

In activerecord_model

PHP Code:
/*
   Query Building Functions
*/

// Current it just accepts an SQL SELECT clause
// I.e: select("id, name") or select("*")
public function select(args) {
  
this.clause_select args;
  return 
this;
}

// Currently it just accepts an SQL WHERE clause
// I.e: where("id = 3")
public function where(args) {
  
this.clause_where args;
  return 
this;
}

// Currently it just accepts an SQL ORDER BY clause
// I.e: order("name ASC")
public function order(args) {
  
this.clause_order args;
  return 
this
}

// Sets the query to delete mode
// Currently it just accepts an SQL WHERE clause
// I.e: del("id = 3") - Deletes row with id 3
//      del()         - WILL DELETE EVERY ROW IN TABLE
//                      UNLESS where clause specified
public function del(args) {
  
this.clause_delete true;
  if (
args) {
    
this.clause_where args;
  }
  return 
this;
}

// Limits the results retrieved
// It accepts an SQL LIMIT clause OR {startrow, endrow}
// I.e: limit("10")            - Rows 0 - 10
//      limit("10 OFFSET 100") - Rows 100 to 110
//      limit({10, 20})        - Rows 10 to 20
public function limit(args) {
  if (
args.size() == 2) {
    
args int(args[1] - args[0]) SPC "OFFSET" SPC int(args[0]);
  }
  
this.clause_limit args;
  return 
this;
}

/*
   Query Functions
*/

// Returns first result by setting limit to 1
public function first() {
  
this.clause_limit "1";
  return 
this.query();
}

// Returns all results by clearing any limit
public function all() {
  
this.clause_limit "";
  
temp.result this.query();
  return (
temp.result.size() > temp.result.link() : {temp.result});
}

// Resets query building values
// If you're unsure of your current queries clauses
// reset it beforehand.
public function reset() {
  
this.clause_select "";
  
this.clause_limit "";
  
this.clause_where "";
  
this.clause_order "";
  
this.clause_delete "";
  return 
this;
}

// Alias for reset
public function build() {
  return 
this.reset();
}

/*
   Query Aliases
*/

public function get() {
  return 
this.query();
}

public function 
go() {
  return 
this.query();
}

public function 
now() {
  return 
this.query();

Small Example Usage

PHP Code:
function onCreated() {
  
// Find all objects where acct is fowlplay4
  
temp.objs Object.where(format("acct = '%s'"player.account.escape())).all();
  
// Find the first 10 objects
  
temp.objs Object.limit({010}).get();
  
// Delete all objects
  
Object.del().now();

Attached Files
File Type: txt activerecord_model.txt (11.0 KB, 231 views)
File Type: txt activerecord_object.txt (2.4 KB, 191 views)
__________________
Quote:
Reply With Quote
  #2  
Old 03-27-2011, 12:09 AM
WhiteDragon WhiteDragon is offline
Banned
Join Date: Feb 2007
Posts: 1,002
WhiteDragon is a splendid one to beholdWhiteDragon is a splendid one to beholdWhiteDragon is a splendid one to beholdWhiteDragon is a splendid one to beholdWhiteDragon is a splendid one to behold
Good work. I'm personally not a fan of ORM or active records, but on the other hand I don't mind query builders to make writing the simple stuff a little less annoying.
Reply With Quote
  #3  
Old 03-27-2011, 12:32 AM
cbk1994 cbk1994 is offline
the fake one
cbk1994's Avatar
Join Date: Mar 2003
Location: San Francisco
Posts: 10,718
cbk1994 has a reputation beyond reputecbk1994 has a reputation beyond reputecbk1994 has a reputation beyond reputecbk1994 has a reputation beyond reputecbk1994 has a reputation beyond reputecbk1994 has a reputation beyond reputecbk1994 has a reputation beyond reputecbk1994 has a reputation beyond reputecbk1994 has a reputation beyond reputecbk1994 has a reputation beyond repute
Send a message via AIM to cbk1994
Interesting. I've never used something like this but I can see the advantages to it.
__________________
Reply With Quote
  #4  
Old 03-27-2011, 02:06 AM
Crono Crono is offline
:pluffy:
Join Date: Feb 2002
Location: Sweden
Posts: 20,000
Crono has a reputation beyond reputeCrono has a reputation beyond reputeCrono has a reputation beyond reputeCrono has a reputation beyond reputeCrono has a reputation beyond reputeCrono has a reputation beyond reputeCrono has a reputation beyond reputeCrono has a reputation beyond reputeCrono has a reputation beyond reputeCrono has a reputation beyond reputeCrono has a reputation beyond repute
lol the 3 guise i wish i had in my university group all postin back 2 back
__________________
Reply With Quote
Reply


Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +2. The time now is 01:25 AM.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2025, vBulletin Solutions Inc.
Copyright (C) 1998-2019 Toonslab All Rights Reserved.