Magic timestamps with Rails and CakePHP

Published on and tagged with cakephp  feature  ruby on rails

Both frameworks provide the feature of automatically setting the creation/modification datetime of a database record. For this feature to work, you have to add datetime columns to your tables which follow some naming conventions. For some reason, CakePHP uses different conventions for this feature than Rails…

In CakePHP, the names of those “magic” columns are:

created
modified / updated

In Rails, on the other hand, the respective column names are:

created_at / created_on
updated_at / updated_on

Fortunately, the other database-related naming conventions seem to be the same in both frameworks.

8 comments baked

  • Abhimanyu Grover

    Hey, thats a nice trick. Thanks

  • cakebaker

    @Abhimanyu: You are welcome!

  • John

    Hi Daniel

    I always stick in a couple of extra columns for modified_by and created_by which corespond to users. Its a shame that thses couldn’t be added as magic columns too.

    I just have a liitle hack in my app_model

    function beforeSave() {
      if(isset($_SESSION['Auth']['User']['id'])){
        $user_id = $_SESSION['Auth']['User']['id'];
    	
        if(isset($this->data[$this->name]['id'])){ // this is modified
    	
    	  $this->data[$this->name]['modified_by'] = $user_id;
    	
        } else {
    	  $this->data[$this->name]['modified_by'] = $user_id;
    	  $this->data[$this->name]['created_by'] = $user_id;
        }
      }
    
      return true;
    }

    I feel bad calling the session directly in app_model as it breaks the MVC – but having looked some of the solutions people have posted up about the place to this exact problem, their solutions although very clever, seemed to overcomplicate things.

    On the other hand I think this is the only instance I do somthing like this – as a rule I reckon sticking rigidly to the conventions has really really helped me learn as a programmer and certainly write better code.

    Cheers

  • cakebaker

    @John: Thanks for your comment!

    An alternative to your approach could be to have a class like

    class AuthenticatedUser {
        public static $id = null;
    }

    If the user is authenticated, the controller sets the $id of this class, and in your model you can then read this value. But I’m not sure if it is really worth the effort ;-)

    And yes, it is (almost) always good to follow the conventions.

  • Brandon P

    I’m quite surprised that this functionality has not moved over into a Behavior. Isn’t this functionality really what behaviors are designed to abstract?

    Further, a “Timestampable” behavior would actually be quite helpful in cases where developers want to define their own columns for each:

    array(
    ‘insert’ => array(‘column’ => ‘special_column_name’),
    ‘update’ => array(‘updateOnEmpty’ => false);
    );
    }
    ?>

    Oh, and the ‘updateOnEmpty’ key… I’m unsure if this has changed, but in prior versions if you save()’d data but NO rows were affected, it would still incriment the ‘modified’ column:

    https://trac.cakephp.org/ticket/382
    (Wow, i opened that 3 years ago… where has the time gone! :)

  • Brandon P

    Oops forgot code tags:

    <?php
    class AppModel extends Model
    {
        public $actsAs = array('Timestampable' => array(
            ‘insert’ => array(’column’ => ’special_column_name’),
            ‘update’ => array(’updateOnEmpty’ => false)
        );
    }
    ?>
  • John

    @Daniel – Why are good ideas obvious in retrospect? Thanks.

  • cakebaker

    @Brandon: Yes, this timestamp functionality is definitely a candidate for a behavior. I don’t know why it hasn’t been moved to a behavior, though I guess there are more important things than the configuration of automagic column names ;-)

    @John: You are welcome :)

Bake a comment




(for code please use <code>...</code> [no escaping necessary])

© daniel hofstetter. Licensed under a Creative Commons License