fREWdiculous!
29 Jul
I am proud to announce a new release of DBIx::Class::Helpers. There are five major changes in this release.
First off, the latest release adds DBIx::Class::Candy exports. So if you are using DBIx::Class::Candy to define a result, certain methods will be imported into your namespace. For example, DBIx::Class::Helper::Row::SubClass will export a subclass subroutine into your module. Not huge but nice nonetheless.
Next up, we have four shiny new components. Two are ResultSet components and two are Result components. One of the two ResultSet components was originally going to be in the core of DBIx::Class, but I decided to make a helper first to ensure that we iron out the details before we release it in core. That component is DBIx::Class::Helper::ResultSet::RemoveColumns. It does exactly what it sounds like. With it you can do
1 2 3 |
and the id column will no longer be selected in your ResultSet. I am sure that it has some quirks, but I am not sure what they would be till people use this. So have at it!
The next component, DBIx::Class::Helper::ResultSet::AutoRemoveColumns, is based upon RemoveColumns. Again, the name should make it clear what it does. Currently it removes typically large columns by default, like text, blob, and the like. See the docs for exactly what it removes. (Note: later on I hope to add a component that adds lazy columns as detailed in ovid’s post here. Ovid if you are reading this I can’t comment on your blog.)
Next up is a fairly simple component, DBIx::Class::Helper::Row::StorageValues. It gives you access to the last known stored value of a column. For example:
1 2 3 4 5 | my $foo = $resultset->search({ name => 'frew'}) ->next; $foo->name('frioux'); # prints "frew" say $foo->get_storage_value('name'); |
Building upon that we have my favorite new component: DBIx::Class::Helper::Row::OnColumnChange. This module adds powerful hooks for calling methods when a column has been modified. If you enable StorageValues for the column you hook into you get to look at the old value and the new value, which is pretty cool. There are three hooks: before_column_change, around_column_change, and after_column_change. It automatically takes into account values changing because of accessors as well as by the arguments passed to update. Also note that it allows you to tell it to wrap the call to update and the column change method in a transaction so that you can safely do things to other tables in the method. Anyway, enough talk, here’s a small example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | __PACKAGE__->add_column(relationship_status => { data_type => 'varchar', length => 30, keep_storage_value => 1, }); __PACKAGE->before_column_change(relationship_status => { method => 'happy_times', txn_wrap => 1, }); sub happy_times { my ($self, $old, $new) = @_; $self->significant_other->update({ feelings => 'happy' }) if $new eq 'together' && $old eq 'apart' } |
So basically if relationship status changes from apart to togehter the significant other gets marked as happy, and all of this is done in a transaction, which is pretty awesome.
Anyway, hopefully this makes your job easier. Have a good Friday!
7 Feb
A new release of the resplendent Perl ORM DBIx::Class means new release of DBIx::Class::Helpers
The ResultSet::Random helper had the wrong function used for MySQL. That was fixed thanks to an RT from pldoh.
get_namespace_parts from the util package was unnecessarily strict. Thanks to melo for the prodding to do that.
I refactored some of the code in core DBIx::Class so that I can more easily detect is_numeric with Row::NumifyGet, instead of requiring the user to specify it. Normally DBIx::Class autodetects it based on column type, but that code wasn’t quite generic enough until now. Nice!
And then the most exciting bit is a new helper entirely for the suite: Row::ToJSON. Basically I was sick of doing this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
Of course that can be shortened to:
But I still have to make that stupid columns list! This shiny new helper makes a TO_JSON method that will simply include all of your columns except for the “heavy” ones like TEXT, NTEXT, or BLOB. Of course you can have finer-grained control than that by explicitly saying to include (or not) a column in it’s configuration. See the docs for all the nitty gritty details.
14 Jan
Yesterday I added a basic but really nice helper to DBIx::Class::Helpers. Say hello to DBIx::Class::Helper::Row::NumifyGet. The reasoning is that often we have bit fields in our database and when we serialize them with JSON we get something like the following:
1 | { 'bit_field':'0'} |
JavaScript has the whole truthy concept like Perl except that in JavaScript “0″ is true, while 0 is false. So NumifyGet will automatically “numify” columns with the is_numeric field set to true. After doing that the json above would become:
1 | { 'bit_field':0} |
Much nicer. Also I added some good docs to DBIx::Class::Helper::ResultSet::Union as well as fixing some latent bugs that were in it.
Enjoy!
28 Dec
If I were to pick one of the modules that I’ve written so far to be my legacy DBIx::Class::Helpers would be it. Maybe later it will be DBIx::Exceptions, but as of now that’s technically vaporware.
So over the Christmas break I’ve been working on updating it a bit. First and foremost I added the exciting DBIx::Class::Helper::ResultSet::Union helper. The best use case (I can think of) for a union is when you want to get data from multiple tables as if they were one table. Here is how one might do something like that with the new module (example ripped from wikipedia):
1 2 3 4 5 6 7 8 9 10 | my $sales_2006 = $schema->resultset('Sales2006')->search(undef, { columns => [qw{sales_person_id amount}] }); my $sales_2007 = $schema->resultset('Sales2007')->search(undef, { columns => [qw{sales_person_id amount}] }); $sales_2006->result_class('DBIx::Class::ResultClass::HashRefInflator'); $sales_2007->result_class('DBIx::Class::ResultClass::HashRefInflator'); my @sales = $sales_2006->union($sales_2007)->all; |
I’d argue that if you have tables like the above you are Doin it Rong, but there are other times when it might make more sense, like if you wanted to maybe have some kind of autocompleter that works for more than one table (Artist, Album, Track) where all of the things have names and ids.
As you should be able to see from the name of the Component I have gone from naming things DBIx::Class::Helper::* to DBIx::Class::Helper::$namespace::*. Mostly that was because my esteemed DBIx::Class janitor, ribasushi, suggested it. I almost had done it before, but his asking for it was enough to get me to do it. The old names will be available for all of the 2.* series and the 3.* series with a warning. After that they will be removed.
Speaking of version numbers, I have also switched from using RJBS versions to using a more normal versioning scheme. Again, I wouldn’t take the credit for this one as it is mostly due to mst and ribasushi’s prodding. Basically the deal is that although RJBS versions make it dead easy for me to release code, they make it hard for the user to see what’s going on. How much has changed between releases? All a user knows is if a release breaks backcompat or not. So I’ll be using the more normal x.yyyzzw where x breaks backcompat, y means major new features, z means bugfixes, and w means minor fixes like pod or dist fixes. I imagine that even that could be automated by looking at current and previous release… Maybe next time
Next up is a much more complete DBIx::Class::Helper::ResultSet::Random which allows the selection of an arbitrary amount of rows, instead of just one. As mentioned in the POD I’ve only tested it on a large table with SQL Server (2005.) To be more explicit, if you are using mysql and it is as slow as people always say, show me a benchmark and we can work together to make it fast. The only thing I can think of to make it fast is to use RowNumberOver and do an IN for a list of shuffled numbers generated with perl. We’ll see though. It works fine for me right now so I don’t care
While I was updating all these little bits I went ahead and pregenerated the DDL for the schema, so I no longer depend on SQLT, which is actually surprisingly heavy. So that’s pretty sweet.
Lastly, String::CamelCase had a new release that no longer fails tests! So I’ve added it as a dep and removed the conditional load code. This isn’t as big a deal as most of the other stuff, but it is certainly a nice change.
Because of all of the major changes I’ve released the new version to cpan as a developer version, so please check it out. At the very least if someone finds a missing dep or something that would be good. If I somehow messed up the doc or something that would be good to find out as well. I plan on releasing for realz before (or on?) New years.