Skip to content

The Attic Project

This is the start of my documentation of fixing up my attic in my house. My goal is to make it a “home theater” recroom. I’ll start by posting some pictures here of how it looks now.

This is the “Front” of the attic, facing where the stairs are.

This is the “back” of the attic, where the projector screen will come down from the ceiling.

Yeah, it’s basically nothing right now. I’m starting with the electrical wiring today/tomorrow. Will post pictures of those (very exciting, I know) when I am done.

Auto_Modeler 1.5 Release

I’ve released version 1.5 of my Auto_Modeler Kohana module today. This is a pretty big release. It provides built in support for in-model data validation. Here’s a list of all the changes:

Auto_Modeler:

  • Added support for in-model validation
  • Added a $rules member array variable (an array of rule arrays)
  • Added a $callbacks member array variable
  • Added a ‘fetch_some’ method to search for specific database rows with a where() array
  • Added comments =)

Auto_Modeler_ORM:

  • Fixed some bugs with many to many relationship setting
  • Added one to many support in find_related()
  • Added one to many support in find_parent()
  • Added one to many support in delete()
  • Added has_attribute()

The big change is the built in validation. Here’s an example of how I use it.
First, my model:

class Asset_Model extends Auto_Modeler_ORM {

	// Database table name
	protected $table_name = 'assets';

	// Database fields and default values
	protected $data = array('id'       =>  '',
	                                 'title'    => '');

	protected $has_many = array('files', 'countries');
	protected $belongs_to = array('categories');

	protected $rules = array('title' => array('required'),
	                         'description' => array('required'));

	// Overloading delete() to delete the physical file as well.
	public function delete()
	{
		// Delete all the files
		$files = Auto_Modeler_ORM::factory('file')->fetch_some(array('asset_id' => $this->data['id']));
		echo Kohana::debug($files);
		foreach ($files as $file)
		{
			$dest_dir = APPPATH.'views/assets/'.substr($file->filename, 0, 1).'/';
			$uploadfile = str_replace(' ', '_', $dest_dir.$file->filename);
			unlink($uploadfile);
		}

		parent::delete();
	}

	protected function check_country(Validation &$validation)
	{
		$validation->add_rules('country', 'required');
	}

	protected function check_category(Validation &$validation)
	{
		$validation->add_rules('category', 'required');
	}

	protected function check_file(Validation &$validation)
	{
		$validation->add_callbacks('file', array($this, 'validate_file_upload'));
	}

	public function validate_file_upload(Validation &$validation, $input)
	{
		if (isset($_FILES) AND $_FILES[$input]['error'])
			$validation->add_error($input, 'no_file');
		else if (count($this->db->getwhere('files', array('filename' => $_FILES[$input]['name']))))
			$validation->add_error($input, 'duplicate_filename');
	}
}

Now here’s the insert() method of my controller:

	public function insert()
	{
		if ( ! ($this->auth->logged_in('admin') OR $this->auth->logged_in('publisher')))
			Event::run('system.404');

		$asset = new Asset_Model();

		if ( ! $_POST)
		{
			$region = new Region_Model();
			$this->template->body = new View('asset/insert');
			$this->template->body->regions = $region->fetch_all();
			$this->template->body->errors = '';
		}
		else
		{
			$post = $this->input->post();

			$asset->title = $post['title'];
			$asset->description = $post['description'];

			try
			{
				// Save the asset
				$asset->save(
					array('country' => $this->input->post('country', array()), 'category' => $this->input->post('category', array())), // Additional data to validate with the form
					array('check_country', 'check_category', 'check_file') // Model callbacks to run
				);

				// Then upload the file
				$dest_dir = APPPATH.'views/assets/'.substr($_FILES['file']['name'], 0, 1).'/';
				$uploadfile = str_replace(' ', '_', $dest_dir.$_FILES['file']['name']);

				! is_dir($dest_dir) AND mkdir($dest_dir, 0777, TRUE);
				move_uploaded_file($_FILES['file']['tmp_name'], $uploadfile);

				foreach ($post['country'] as $country)
					$asset->countries = $country;

				$asset->category_id = $post['category'];

				$file = new File_Model();
				$file->filename = str_replace(' ', '_', $_FILES['file']['name']);
				$file->asset_id = $asset->id;
				$file->timestamp = time();
				$file->save();

				url::redirect('');
			}
			catch (Kohana_User_Exception $e)
			{
				$region = new Region_Model();
				$this->template->body = new View('asset/insert');
				$this->template->body->regions = $region->fetch_all();
				$this->template->body->errors = $e;
				$this->template->body->set($post);
			}
		}
	}

The important part of this block of code is in the try/catch block. The model does all the validation internally. So when it save()s, it will try and validate it’s internal data. If it fails, it will throw an exception that includes the error messages (this comes from views/form_errors.php).

The second new part of this code is the extra parameters in the save() method. This form has external requirements seperate from the assets table that are required (country and category). A file upload is also required.

Since this data has nothing inherintly to do with the asset model or database table, we pass them as callbacks. The model has callback methods to check the external data. So we pass the extra data in with the first parameter to save(), and the second parameter is the callbacks to run in addition to the built in validation.

If the save() succeeds, we continue our insert procedure, otherwise we skip to the catch{} block and display the form again with the invalida data and errors.

5-Color Worlds 2008 Preview

I am going to be playing in and running 5-Color Worlds 2008 this year, as always. I decided to move it away from GenCon this year because of all the distractions surrounding that convention these days. All the events there simply take too many of my players. Last year we had a paltry 22 players. What kind of world championship tournament only has 22 players?

The past year has seen a sharp decline in 5-Color activity, ranging from forum activity, article submissions and 5CRC votes. Players don’t know where the format is heading.

I’m going to try and bring the format into the modern times. I commissioned a new website layout, I’m recruiting regular article writers for the site,and will try and organize more events.

I’ll say I’m planning on running my old MUC deck. It hasn’t changed much in many months, but it’s built to straight destroy combo (Flash.dec). It doesn’t fare so well against aggro, but I’ll try and fix that before the tournament.

Afterwards, I plan to write an extensive tournament report with photos and all that good junk.

Kohana PHP 2.2 Released

Today is the big day. Kohana 2.2 was released to the public. This is a huge upgrade with so many benefits, we can’t even begin to describe them ;)

New router, captcha module, new and improved database methods, upload helper, many array helper methods, completely redesigned Auth module, ORM library…yeah, there’s a lot.

Also, we are now officially GOPHP5, which means we are only php 5.2+ now. yeah, screw you old php!

You can catch me on irc.freenode.net in #kohana yacking at everyone if you want to ask questions or need help upgrading your app to the new code.

Frist Post!?!?

Hello, this is my blog. Here I will post things that amuse me. Some content will be rated G, some not so rated G. Topics will range from computers to video games to sex to Magic: The Gathering to life and death.

If this disturbs you, just close this window now.

By the way, please click my sponsors on the right, they help pay for your ability (or inability) to read this.