Nimbu.Object
Nimbu.Object is the base class for all data objects in Nimbu. It provides methods for creating, reading, updating, and deleting data across all channels and built-in data types.
Creating Objects
Basic Object Creation
js
// Create a new object for a channel
const blogPost = new Nimbu.Object('blog');
blogPost.set('title', 'My First Post');
blogPost.set('content', 'Hello World!');
await blogPost.save();Creating with Initial Data
js
const product = new Nimbu.Object('products', {
name: 'Widget',
price: 29.99,
stock: 100
});
await product.save();Creating Subclasses
For better code organization, create custom subclasses:
js
// Define a custom class
const Book = Nimbu.Object.extend('books');
// Use the custom class
const book = new Book();
book.set('title', 'The Great Gatsby');
book.set('author', 'F. Scott Fitzgerald');
await book.save();ES6 Class Syntax
js
class Book extends Nimbu.Object {
constructor() {
super('books');
}
isLong() {
return this.get('pages') > 300;
}
}
// Register the subclass
Nimbu.Object.registerSubclass('books', Book);
// Use it
const book = new Book();
book.set('pages', 450);
console.log(book.isLong()); // trueSetting Attributes
Basic Set
js
const customer = new Nimbu.Object('customers');
customer.set('name', 'John Doe');
customer.set('email', '[email protected]');
customer.set('age', 30);Setting Multiple Attributes
js
customer.set({
name: 'John Doe',
email: '[email protected]',
age: 30,
subscribed: true
});Setting Nested Objects
js
customer.set('address', {
street: '123 Main St',
city: 'New York',
zip: '10001'
});Setting Arrays
js
product.set('tags', ['electronics', 'gadgets', 'sale']);
product.set('colors', ['red', 'blue', 'green']);Getting Attributes
Basic Get
js
const name = customer.get('name');
const email = customer.get('email');
const age = customer.get('age');Getting with Default Value
js
const status = customer.get('status') || 'active';
const points = customer.get('loyalty_points') || 0;Checking if Attribute Exists
js
if (customer.has('email')) {
console.log('Email:', customer.get('email'));
}Saving Objects
Basic Save
js
const entry = new Nimbu.Object('blog');
entry.set('title', 'New Post');
await entry.save();
console.log('Saved with ID:', entry.id);Save with Error Handling
js
try {
await entry.save();
console.log('Save successful');
} catch (error) {
console.error('Save failed:', error.message);
}Save Specific Attributes
js
// Only save the 'status' field
await order.save({ status: 'shipped' });Updating Objects
Fetch and Update
js
// Fetch existing object
const product = await new Nimbu.Query('products').get(productId);
// Update attributes
product.set('price', 39.99);
product.set('stock', 50);
// Save changes
await product.save();Refresh from Server
js
// Reload latest data from server
await product.fetch();
// Now product has the latest data
const latestPrice = product.get('price');Deleting Objects
Delete (Destroy)
js
const entry = await new Nimbu.Query('blog').get(entryId);
await entry.destroy();
console.log('Entry deleted');Conditional Delete
js
const order = await new Nimbu.Query('orders').get(orderId);
if (order.get('status') === 'draft') {
await order.destroy();
} else {
console.log('Cannot delete non-draft order');
}Special Fields
Object ID
js
// Get the unique ID
const id = object.id;
// Or using objectId
const sameId = object.get('id');Created At
js
const createdAt = object.createdAt;
// or
const created = object.get('created_at');
console.log('Created:', createdAt.toLocaleDateString());Updated At
js
const updatedAt = object.updatedAt;
// or
const updated = object.get('updated_at');
console.log('Last updated:', updatedAt.toLocaleString());Check if Object is New
js
if (!object.id) {
console.log('This is a new object');
} else {
console.log('This object exists in the database');
}Counters and Atomic Operations
Increment Counter
js
// Increment by 1
await customer.increment('loyalty_points');
// Increment by specific amount
await customer.increment('login_count', 1);
await customer.increment('balance', 50);
await customer.save();Decrement Counter
js
// Decrement by 1
await product.increment('stock', -1);
// Or by specific amount
await product.increment('stock', -5);
await product.save();Why Use Counters?
Counters are atomic and prevent race conditions:
js
// BAD: Race condition possible
const current = product.get('stock');
product.set('stock', current - 1);
await product.save();
// GOOD: Atomic operation
await product.increment('stock', -1);
await product.save();Working with Relations
One-to-One Relations
js
// Create related objects
const author = new Nimbu.Object('authors');
author.set('name', 'Jane Doe');
await author.save();
const book = new Nimbu.Object('books');
book.set('title', 'My Book');
book.set('author', author); // Set relation
await book.save();
// Access related object
const bookAuthor = book.get('author');
console.log('Author:', bookAuthor.get('name'));Many-to-One Relations
js
// Multiple books can have the same author
const book1 = new Nimbu.Object('books');
book1.set('title', 'Book One');
book1.set('author', author);
const book2 = new Nimbu.Object('books');
book2.set('title', 'Book Two');
book2.set('author', author);
await book1.save();
await book2.save();Working with Nimbu.Relation
js
// For many-to-many relationships
const customer = new Nimbu.Object('customers');
const favoriteProducts = customer.relation('favorite_products');
// Add products to the relation
const product1 = await new Nimbu.Query('products').get(id1);
const product2 = await new Nimbu.Query('products').get(id2);
favoriteProducts.add(product1);
favoriteProducts.add(product2);
await customer.save();
// Query the relation
const favorites = await favoriteProducts.query().collection().fetch();
console.log(`Customer has ${favorites.length} favorite products`);Data Types
Supported Data Types
js
// String
object.set('name', 'John Doe');
// Number
object.set('age', 30);
object.set('price', 29.99);
// Boolean
object.set('active', true);
// Date
object.set('published_at', new Date());
// Array
object.set('tags', ['tag1', 'tag2']);
// Object
object.set('address', {
street: '123 Main St',
city: 'New York'
});
// Null
object.set('notes', null);
// Relations
object.set('author', authorObject);Unsetting Attributes
Remove an Attribute
js
// Remove an attribute completely
object.unset('temporary_field');
await object.save();Dirty Tracking
Check if Object Has Changes
js
if (object.dirty()) {
console.log('Object has unsaved changes');
await object.save();
}Get Changed Attributes
js
const changes = object.dirtyKeys();
console.log('Changed fields:', changes);Check Specific Field
js
if (object.dirty('price')) {
console.log('Price was changed');
}Common Patterns
Conditional Updates
js
const product = await new Nimbu.Query('products').get(productId);
if (product.get('stock') > 0) {
await product.increment('stock', -1);
await product.save();
} else {
throw new Error('Out of stock');
}Batch Creation
js
const entries = [];
for (let i = 0; i < 10; i++) {
const entry = new Nimbu.Object('blog');
entry.set('title', `Post ${i + 1}`);
entries.push(entry);
}
// Save all
for (const entry of entries) {
await entry.save();
}Safe Updates
js
async function updateProduct(productId, updates) {
try {
const product = await new Nimbu.Query('products').get(productId);
for (const [key, value] of Object.entries(updates)) {
product.set(key, value);
}
await product.save();
return { success: true, product };
} catch (error) {
return { success: false, error: error.message };
}
}Best Practices
1. Save Related Objects First
js
// Good: Save related objects before saving parent
const author = new Nimbu.Object('authors');
author.set('name', 'John');
await author.save(); // Save first
const book = new Nimbu.Object('books');
book.set('author', author);
await book.save(); // Then save parent2. Use Atomic Operations for Counters
js
// Good
await product.increment('views', 1);
await product.save();
// Avoid
const views = product.get('views') || 0;
product.set('views', views + 1);
await product.save();3. Handle Errors
js
try {
await object.save();
} catch (error) {
if (error.code === 101) {
console.error('Object not found');
} else {
console.error('Save failed:', error.message);
}
}4. Use Subclasses for Organization
js
// Define reusable classes
const Product = Nimbu.Object.extend('products');
const Customer = Nimbu.Object.extend('customers');
// Use them throughout your code
const product = new Product();
const customer = new Customer();Next Steps
- Learn about Nimbu.Query - Query and filter objects
- Explore Other Classes - Customer, Product, Order, etc.
- Review Callbacks - React to object changes