Skip site navigation (1)Skip section navigation (2)

FreeBSD Manual Pages

  
 
  

home | help
Rose::DB::Object::HelpUser3Contributed Perl DocumeRose::DB::Object::Helpers(3)

NAME
       Rose::DB::Object::Helpers - A mix-in class containing convenience
       methods for Rose::DB::Object.

SYNOPSIS
	 package MyDBObject;

	 use Rose::DB::Object;
	 our @ISA = qw(Rose::DB::Object);

	 use Rose::DB::Object::Helpers 'clone',
	   { load_or_insert => 'find_or_create'	};
	 ...

	 $obj =	MyDBObject->new(id => 123);
	 $obj->find_or_create();

	 $obj2 = $obj->clone;

DESCRIPTION
       Rose::DB::Object::Helpers provides convenience methods from use with
       Rose::DB::Object-derived	classes.  These	methods	do not exist in
       Rose::DB::Object	in order to keep the method namespace clean.  (Each
       method added to Rose::DB::Object	is another potential naming conflict
       with a column accessor.)

       This class inherits from	Rose::Object::MixIn.  See the
       Rose::Object::MixIn documentation for a full explanation	of how to
       import methods from this	class.	The helper methods themselves are
       described below.

FUNCTIONS VS. METHODS
       Due to the "wonders" of Perl 5's	object system, any helper method
       described here can also be used as a Rose::DB::Object::Util-style
       utility function	that takes a Rose::DB::Object-derived object as	its
       first argument.	Example:

	 # Import two helpers
	 use Rose::DB::Object::Helpers qw(clone_and_reset traverse_depth_first);

	 $o = My::DB::Object->new(...);

	 clone_and_reset($o); #	Imported helper	"method" called	as function

	 # Imported helper "method" with arguments called as function
	 traverse_depth_first($o, handlers => {	... }, max_depth => 2);

       Why, then, the distinction between Rose::DB::Object::Helpers methods
       and Rose::DB::Object::Util functions?  It's simply a matter of context.
       The functions in	Rose::DB::Object::Util are most	useful in the context
       of the internals	(e.g., writing your own	column method-maker) whereas
       Rose::DB::Object::Helpers methods are most often	added to a common
       Rose::DB::Object-derived	base class and then called as object methods
       by all classes that inherit from	it.

       The point is, these are just conventions.  Use any of these subroutines
       as functions or as methods as you see fit.  Just	don't forget to	pass a
       Rose::DB::Object-derived	object as the first argument when calling as a
       function.

OBJECT METHODS
   as_json [PARAMS]
       Returns a JSON-formatted	string created from the	object tree as created
       by the as_tree method.  PARAMS are the same as for the as_tree method,
       except that the "deflate" parameter is ignored (it is always set	to
       true).

       You must	have the JSON module version 2.12 or later installed in	order
       to use this helper method.  If you have the JSON::XS module version
       2.2222 or later installed, this method will work	a lot faster.

   as_tree [PARAMS]
       Returns a reference to a	hash of	name/value pairs representing the
       column values of	this object as well as any nested sub-objects.	The
       PARAMS name/value pairs dictate the details of the sub-object
       traversal.  Valid parameters are:

       allow_loops BOOL
	   If true, allow loops	during the traversal (e.g., A -> B -> C	-> A).
	   The default value is	false.

       deflate BOOL
	   If true, the	values in the tree will	be simple scalars suitable for
	   storage in the database (e.g., a date string	like "2005-12-31"
	   instead of a	DateTime object).  The default is true.

       exclude CODEREF
	   A reference to a subroutine that is called on each
	   Rose::DB::Object-derived object encountered during the traversal.
	   It is passed	the object, the	parent object (undef, if none),	and
	   the	Rose::DB::Object::Metadata::Relationship-derived object
	   (undef, if none) that led to	this object.  If the subroutine
	   returns true, then this object is not processed.  Example:

	       exclude => sub
	       {
		 my($object, $parent, $rel_meta) = @_;
		 ...
		 return	1  if($should_exclude);
		 return	0;
	       },

       force_load BOOL
	   If true, related sub-objects	will be	loaded from the	database.  If
	   false, then only the	sub-objects that have already been loaded from
	   the database	will be	traversed.  The	default	is false.

       max_depth DEPTH
	   Do not descend past DEPTH levels.  Depth is an integer starting
	   from	0 for the object that the as_tree method was called on and
	   increasing with each	level of related objects.  The default value
	   is 100.

       persistent_columns_only BOOL
	   If true, non-persistent columns will	not be included	in the tree.
	   The default is false.

       prune CODEREF
	   A reference to a subroutine that is called on each
	   Rose::DB::Object::Metadata::Relationship-derived object encountered
	   during traversal.  It is passed the relationship object, the	parent
	   object, and the depth.  If the subroutine returns true, then	the
	   entire sub-tree below this relationship will	not be traversed.
	   Example:

	       prune =>	sub
	       {
		 my($rel_meta, $object,	$depth)	= @_;
		 ...
		 return	1  if($should_prune);
		 return	0;
	       },

       Caveats:	Currently, you cannot have a relationship and a	column with
       the same	name in	the same class.	 This should not happen	without
       explicit	action on the part of the class	creator, but it	is technically
       possible.  The result of	serializing such an object using as_tree is
       undefined.  This	limitation may be removed in the future.

       The exact format	of the "tree" data structure returned by this method
       is not public and may change in the future (e.g., to overcome the
       limitation described above).

   as_yaml [PARAMS]
       Returns a YAML-formatted	string created from the	object tree as created
       by the as_tree method.  PARAMS are the same as for the as_tree method,
       except that the "deflate" parameter is ignored (it is always set	to
       true).

       You must	have the YAML::Syck module installed in	order to use this
       helper method.

   clone
       Returns a new object initialized	with the column	values of the existing
       object.	For example, imagine a "Person"	class with three columns,
       "id", "name", and "age".

	   $a =	Person->new(id => 123, name => 'John', age => 30);

       This use	of the "clone()" method:

	   $b =	$a->clone;

       is equivalent to	this:

	   $b =	Person->new(id => $a->id, name => $a->name, age	=> $a->age);

   clone_and_reset
       This is the same	as the clone method described above, except that it
       also sets all of	the primary and	unique key columns to undef.  If the
       cloned object has a db attribute, then it is copied to the clone	object
       as well.

       For example, imagine a "Person" class with three	columns, "id", "name",
       and "age", where	"id" is	the primary key	and "name" is a	unique key.

	   $a =	Person->new(id => 123, name => 'John', age => 30, db =>	$db);

       This use	of the "clone_and_reset()" method:

	   $b =	$a->clone_and_reset;

       is equivalent to	this:

	   $b =	Person->new(id => $a->id, name => $a->name, age	=> $a->age);
	   $b->id(undef);   # reset primary key
	   $b->name(undef); # reset unique key
	   $b->db($a->db);  # copy db

   column_values_as_json
       Returns a string	containing a JSON representation of the	object's
       column values.  You must	have the JSON module version 2.12 or later
       installed in order to use this helper method.  If you have the JSON::XS
       module version 2.2222 or	later installed, this method will work a lot
       faster.

   column_values_as_yaml
       Returns a string	containing a YAML representation of the	object's
       column values.  You must	have the YAML::Syck module installed in	order
       to use this helper method.

   column_accessor_value_pairs
       Returns a hash (in list context)	or reference to	a hash (in scalar
       context)	of column accessor method names	and column values.  The	keys
       of the hash are the accessor method names for the columns.  The values
       are retrieved by	calling	the accessor method for	each column.

   column_mutator_value_pairs
       Returns a hash (in list context)	or reference to	a hash (in scalar
       context)	of column mutator method names and column values.  The keys of
       the hash	are the	mutator	method names for the columns.  The values are
       retrieved by calling the	accessor method	for each column.

   column_value_pairs
       Returns a hash (in list context)	or reference to	a hash (in scalar
       context)	of column name and value pairs.	 The keys of the hash are the
       names of	the columns.  The values are retrieved by calling the accessor
       method for each column.

   dirty_columns [ NAMES | COLUMNS ]
       Given a list of column names or
       Rose::DB::Object::Metadata::Column-derived objects, mark	each column in
       the invoking object as modifed.

       If passed no arguments, returns a list of all modified columns in list
       context or the number of	modified columns in scalar context.

   forget_related [ NAME | PARAMS ]
       Given a foreign key or relationship name, forget	any previously loaded
       objects related by the specified	foreign	key or relationship.
       Normally, any objects loaded by the default accessor methods for
       relationships and foreign keys are fetched from the database only the
       first time they are asked for, and simply returned thereafter.  Asking
       them to be "forgotten" causes them to be	fetched	anew from the database
       the next	time they are asked for.

       If the related object name is passed as a plain string NAME, then a
       foreign key with	that name is looked up.	 If no such foreign key
       exists, then a relationship with	that name is looked up.	 If no such
       relationship or foreign key exists, a fatal error will occur.  Example:

	   $foo->forget_related('bar');

       It's generally not a good idea to add a foreign key and a relationship
       with the	same name, but it is technically possible.  To specify the
       domain of the name, pass	the name as the	value of a "foreign_key" or
       "relationship" parameter.  Example:

	   $foo->forget_related(foreign_key => 'bar');
	   $foo->forget_related(relationship =>	'bar');

   has_loaded_related [	NAME | PARAMS ]
       Given a foreign key or relationship name, return	true if	one or more
       related objects have been loaded	into the current object, false
       otherwise.

       If the name is passed as	a plain	string NAME, then a foreign key	with
       that name is looked up.	If no such foreign key exists, then a
       relationship with that name is looked up.  If no	such relationship or
       foreign key exists, a fatal error will occur.  Example:

	   $foo->has_loaded_related('bar');

       It's generally not a good idea to add a foreign key and a relationship
       with the	same name, but it is technically possible.  To specify the
       domain of the name, pass	the name as the	value of a "foreign_key" or
       "relationship" parameter.  Example:

	   $foo->has_loaded_related(foreign_key	=> 'bar');
	   $foo->has_loaded_related(relationship => 'bar');

   init_with_column_value_pairs	[ HASH | HASHREF ]
       Initialize an object with a hash	or reference to	a hash of column/value
       pairs.  This differs from the inherited init method in that it accepts
       column names rather than	method names.  A column	name may not be	the
       same as its mutator method name if the column is	aliased, for example.

	   $p =	Person->new; # assume "type" column is aliased to "person_type"

	   # init() takes method/value pairs
	   $p->init(person_type	=> 'cool', age => 30);

	   # Helper takes a hashref of column/value pairs
	   $p->init_with_column_value_pairs({ type => 'cool', age => 30	});

	   # ...or a hash of column/value pairs
	   $p->init_with_column_value_pairs(type => 'cool', age	=> 30);

   init_with_json JSON
       Initialize the object with a JSON-formatted string.  The	JSON string
       must be in the format returned by the as_json (or
       column_values_as_json) method.  Example:

	   $p1 = Person->new(name => 'John', age => 30);
	   $json = $p1->as_json;

	   $p2 = Person->new;
	   $p2->init_with_json($json);

	   print $p2->name; # John
	   print $p2->age;  # 30

   init_with_deflated_tree TREE
       This is the same	as the init_with_tree method, except that it expects
       all the values to be simple scalars suitable for	storage	in the
       database	(e.g., a date string like "2005-12-31" instead of a DateTime
       object).	 In other words, the TREE should be in the format generated by
       the as_tree method called with the "deflate" parameter set to true.
       Initializing objects in this way	is slightly more efficient.

   init_with_tree TREE
       Initialize the object with a Perl data structure	in the format returned
       from the	as_tree	method.	 Example:

	   $p1 = Person->new(name => 'John', age => 30);
	   $tree = $p1->as_tree;

	   $p2 = Person->new;
	   $p2->init_with_tree($tree);

	   print $p2->name; # John
	   print $p2->age;  # 30

   init_with_yaml YAML
       Initialize the object with a YAML-formatted string.  The	YAML string
       must be in the format returned by the as_yaml (or
       column_values_as_yaml) method.  Example:

	   $p1 = Person->new(name => 'John', age => 30);
	   $yaml = $p1->as_yaml;

	   $p2 = Person->new;
	   $p2->init_with_yaml($yaml);

	   print $p2->name; # John
	   print $p2->age;  # 30

   insert_or_update [PARAMS]
       If the object already exists in the database, then update it.
       Otherwise, insert it.  Any PARAMS are passed on to the call to save
       (which is supplied with the appropriate "insert"	or "update" boolean
       parameter).

       This method differs from	the standard save method in that save decides
       to insert or update based solely	on whether or not the object was
       previously loaded.  This	method will take the extra step	of actually
       attempting to load the object to	see whether or not it's	in the
       database.

       The return value	of the save method is returned.

   insert_or_update_on_duplicate_key [PARAMS]
       Update or insert	a row with a single SQL	statement, depending on
       whether or not a	row with the same primary or unique key	already
       exists.	Any PARAMS are passed on to the	call to	save (which is
       supplied	with the appropriate "insert" or "update" boolean parameter).

       If the current database does not	support	the "ON	DUPLICATE KEY UPDATE"
       SQL extension, then this	method simply calls the	insert_or_update
       method, passing all PARAMS.

       Currently, the only database that supports "ON DUPLICATE	KEY UPDATE" is
       MySQL, and only in version 4.1.0	or later.  You can read	more about the
       feature here:

       <http://dev.mysql.com/doc/refman/5.1/en/insert-on-duplicate.html>

       Here's a	quick example of the SQL syntax:

	   INSERT INTO table (a, b, c) VALUES (1, 2, 3)
	     ON	DUPLICATE KEY UPDATE a = 1, b =	2, c = 3;

       Note that there are two sets of columns and values in the statement.
       This presents a choice: which columns to	put in the "INSERT" part, and
       which to	put in the "UPDATE" part.

       When using this method, if the object was previously loaded from	the
       database, then values for all columns are put in	both the "INSERT" and
       "UPDATE"	portions of the	statement.

       Otherwise, all columns are included in both clauses except those
       belonging to primary keys or unique keys	which have only	undefined
       values.	This is	important because it allows objects to be updated
       based on	a single primary or unique key,	even if	other possible keys
       exist, but do not have values set.  For example,	consider this table
       with the	following data:

	   CREATE TABLE	parts
	   (
	     id	     INT PRIMARY KEY,
	     code    CHAR(3) NOT NULL,
	     status  CHAR(1),

	     UNIQUE(code)
	   );

	   INSERT INTO parts (id, code,	status)	VALUES (1, 'abc', 'x');

       This code will update part id 1,	setting	its "status" column to "y".

	   $p =	Part->new(code => 'abc', status	=> 'y');
	   $p->insert_or_update_on_duplicate_key;

       The resulting SQL:

	   INSERT INTO parts (code, status) VALUES ('abc', 'y')
	     ON	DUPLICATE KEY UPDATE code = 'abc', status = 'y';

       Note that the "id" column is omitted because it has an undefined	value.
       The SQL statement will detect the duplicate value for the unique	key
       "code" and then run the "UPDATE"	portion	of the query, setting "status"
       to "y".

       This method returns true	if the row was inserted	or updated
       successfully, false otherwise.  The true	value returned on success will
       be the object itself.  If the object overloads its boolean value	such
       that it is not true, then a true	value will be returned instead of the
       object itself.

       Yes, this method	name is	very long.  Remember that you can rename
       methods on import.  It is expected that most people will	want to	rename
       this method to "insert_or_update", using	it in place of the normal
       insert_or_update	helper method:

	   package My::DB::Object;
	   ...
	   use Rose::DB::Object::Helpers
	     { insert_or_update_on_duplicate_key => 'insert_or_update' };

   load_or_insert [PARAMS]
       Try to load the object, passing PARAMS to the call to the load()
       method.	The parameter "speculative => 1" is automatically added	to
       PARAMS.	If no such object is found, then the object is inserted.

       Example:

	   # Get object	id 123 if it exists, otherwise create it now.
	   $obj	= MyDBObject->new(id =>	123)->load_or_insert;

   load_or_save	[PARAMS]
       Try to load the object, passing PARAMS to the call to the load()
       method.	The parameter "speculative => 1" is automatically added	to
       PARAMS.	If no such object is found, then the object is saved.

       This methods differs from load_or_insert	in that	the save method	will
       also save sub-objects.  See the documentation for Rose::DB::Object's
       save method for more information.

       Example:

	   @perms = (Permission->new(...), Permission->new(...));

	   # Get person	id 123 if it exists, otherwise create it now
	   # along with	permission sub-objects.
	   $person = Person->new(id => 123, perms => \@perms)->load_or_save;

   load_speculative [PARAMS]
       Try to load the object, passing PARAMS to the call to the load()	method
       along with the "speculative => 1" parameter.  See the documentation for
       Rose::DB::Object's load method for more information.

       Example:

	   $obj	= MyDBObject->new(id =>	123);

	   if($obj->load_speculative)
	   {
	     print "Found object id 123\n";
	   }
	   else
	   {
	     print "Object id 123 not found\n";
	   }

   new_from_json JSON
       The method is the equivalent of creating	a new object and then calling
       the init_with_json method on it,	passing	JSON as	an argument.  See the
       init_with_json method for more information.

   new_from_deflated_tree TREE
       The method is the equivalent of creating	a new object and then calling
       the init_with_deflated_tree method on it, passing TREE as an argument.
       See the init_with_deflated_tree method for more information.

   new_from_tree TREE
       The method is the equivalent of creating	a new object and then calling
       the init_with_tree method on it,	passing	TREE as	an argument.  See the
       init_with_tree method for more information.

   new_from_yaml YAML
       The method is the equivalent of creating	a new object and then calling
       the init_with_yaml method on it,	passing	YAML as	an argument.  See the
       init_with_yaml method for more information.

   strip [PARAMS]
       This method prepares an object for serialization	by stripping out
       internal	structures known to contain code references or other values
       that do not survive serialization.  The object itself is	returned, now
       stripped.

       Note: Operations	that were scheduled to happen "on save()" will also be
       stripped	out by this method.  Examples include the databsae update or
       insertion of any	child objects attached to the parent object using
       "get_set_on_save", "add_on_save", or "delete_on_save" methods.  If such
       operations exist, an exception will be thrown unless the
       "strip_on_save_ok" parameter is true.

       If your object has these	kinds of pending changes, either save()	first
       and then	strip(), or clone() and	then strip() the clone.

       By default, the db object and all sub-objects (foreign keys or
       relationships) are removed.  PARAMS are optional	name/value pairs.
       Valid PARAMS are:

       leave [ NAME  | ARRAYREF	]
	   This	parameter specifies which items	to leave un-stripped.  The
	   value may be	an item	name or	a reference to an array	of item	names.
	   Valid names are:

	   db  Do not remove the db object.  The db object will	have its DBI
	       database	handle (dbh) removed, however.

	   foreign_keys
	       Do not removed sub-objects that have already been loaded	by
	       this object through foreign keys.

	   relationships
	       Do not removed sub-objects that have already been loaded	by
	       this object through relationships.

	   related_objects
	       Do not remove any sub-objects (foreign keys or relationships)
	       that have already been loaded by	this object.  This option is
	       the same	as specifying both the "foreign_keys" and
	       "relationships" names.

       strip_on_save_ok	BOOL
	   If true, do not throw an exception when pending "on-save" changes
	   exist in the	object;	just strip them.  (See description above for
	   details.)

   traverse_depth_first	[ CODEREF | PARAMS ]
       Do a depth-first	traversal of the Rose::DB::Object-derived object that
       this method is called on, descending into related objects. If a
       reference to a subroutine is passed as the sole argument, it is taken
       as the value of the "object" key	to the "handlers" parameter hash (see
       below).	Otherwise, PARAMS name/value pairs are expected.  Valid
       parameters are:

       allow_loops BOOL
	   If true, allow loops	during the traversal (e.g., A -> B -> C	-> A).
	   The default value is	false.

       context SCALAR
	   An arbitrary	context	variable to be passed along to (and possibly
	   modified by)	each handler routine (see "handlers" parameter below).
	   The context may be any scalar value (e.g., an object, a reference
	   to a	hash, etc.)

       exclude CODEREF
	   A reference to a subroutine that is called on each
	   Rose::DB::Object-derived object encountered during the traversal.
	   It is passed	the object, the	parent object (undef, if none),	and
	   the	Rose::DB::Object::Metadata::Relationship-derived object
	   (undef, if none) that led to	this object.  If the subroutine
	   returns true, then this object is not processed.  Example:

	       exclude => sub
	       {
		 my($object, $parent, $rel_meta) = @_;
		 ...
		 return	1  if($should_exclude);
		 return	0;
	       },

       force_load BOOL
	   If true, related sub-objects	will be	loaded from the	database.  If
	   false, then only the	sub-objects that have already been loaded from
	   the database	will be	traversed.  The	default	is false.

       handlers	HASHREF
	   A reference to a hash of handler subroutines.  Valid	keys, calling
	   context, and	the arguments passed to	the referenced subroutines are
	   as follows.

	   object
	       This handler is called whenever a Rose::DB::Object-derived
	       object is encountered.  This includes the object	that
	       traverse_depth_first was	called on as well as any sub-objects.
	       The handler is passed the object, the "context",	the parent
	       object (undef, if none),	the
	       Rose::DB::Object::Metadata::Relationship-derived	object through
	       which this object was arrived at	(undef if none), and the
	       depth.

	       The handler must	return the value to be used as the "context"
	       during the traversal of any related sub-objects.	 The context
	       returned	may be different than the context passed in.  Example:

		   handlers =>
		   {
		     object => sub
		     {
		       my($object, $context, $parent, $rel_meta, $depth) = @_;
		       ...

		       return $context;	# Important!
		     }
		     ...
		   }

	   relationship
	       This handler is called just before a
	       Rose::DB::Object::Metadata::Relationship-derived	object is
	       descended into  (i.e., just before the sub-objectes related
	       through this relationship are processed). The handler is	passed
	       the object that contains	the relationship, the "context", the
	       "context", and the relationship object itself.

	       The handler must	return the value to be used as the "context"
	       during the traversal of the objects related through this
	       relationship.  (If you do not define this handler, then the
	       current context object will be used.)  The context returned may
	       be different than the context passed in.	 Example:

		   handlers =>
		   {
		     relationship => sub
		     {
		       my($object, $context, $rel_meta)	= @_;
		       ...

		       return $context;	# Important!
		     }
		     ...
		   }

	   loop_avoided
	       This handler is called after the	traversal refuses to process a
	       sub-object in order to avoid a loop.  (This only	happens	if the
	       "allow_loops" is	parameter is false, obviously.)	 The handler
	       is passed the object that was not processed, the	"context", the
	       parent object, the previous "context", and the
	       Rose::DB::Object::Metadata::Relationship-derived	object through
	       which the sub-object was	related.  Example:

		   handlers =>
		   {
		     loop_avoided => sub
		     {
		       my($object, $context, $parent, $prev_context, $rel_meta)	= @_;
		       ...
		     }
		     ...
		   }

       max_depth DEPTH
	   Do not descend past DEPTH levels.  Depth is an integer starting
	   from	0 for the object that the traverse_depth_first method was
	   called on and increasing with each level of related objects.	 The
	   default value is 100.

       prune CODEREF
	   A reference to a subroutine that is called on each
	   Rose::DB::Object::Metadata::Relationship-derived object encountered
	   during traversal.  It is passed the relationship object, the	parent
	   object, and the depth.  If the subroutine returns true, then	the
	   entire sub-tree below this relationship will	not be traversed.
	   Example:

	       prune =>	sub
	       {
		 my($rel_meta, $object,	$depth)	= @_;
		 ...
		 return	1  if($should_prune);
		 return	0;
	       },

AUTHOR
       John C. Siracusa	(siracusa@gmail.com)

LICENSE
       Copyright (c) 2010 by John C. Siracusa.	All rights reserved.  This
       program is free software; you can redistribute it and/or	modify it
       under the same terms as Perl itself.

perl v5.24.1			  2015-03-17	  Rose::DB::Object::Helpers(3)

NAME | SYNOPSIS | DESCRIPTION | FUNCTIONS VS. METHODS | OBJECT METHODS | AUTHOR | LICENSE

Want to link to this manual page? Use this URL:
<https://www.freebsd.org/cgi/man.cgi?query=Rose::DB::Object::Helpers&sektion=3&manpath=FreeBSD+12.0-RELEASE+and+Ports>

home | help