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!
26 Jul
I have been using git more and more. I use it in all of my CPAN modules. I’m using git to the point where I expect everything else (that is, svn) to be just as powerful and fast. Unfortunately that just is not the case, and I’m still stuck with it for all but one project at work.. For example, the other day I wanted to find the last commit that my coworker made. With git it would just be git log –author wes -1. I couldn’t seem to figure out a way to do it with svn. Maybe I’m just dumb? Add on to that the fact that git log is mega fast but if you do svn log You Have Made a Mistake. Also the colors! Who doesn’t like the fact that git has colors out of the box?
To sum up the previous paragraph: I need to learn to use git-svn. Lets get started:
First off, you need to make a users file. At my company that’s pretty easy since there are like, 12 people who have commit access to svn. This is what it looks like:
1 2 3 | david = David B. <elduderino@hotmail.com> fred = Fred K Beckhusin <gnarlbot@hotmail.com> frew = Arthur Axel "fREW" Schmidt <frioux@gmail.com> |
Put it in a file named “users” in the current directory. All this does is substitute the svn names (on the left) for the git names (on the right.) Next up, check out your repository:
1 | git svn clone --stdlayout --authors-file=users svn://reposerver/foo/bar |
This assumes that /foo/bar has subdirs /trunk, /branches, and /tags. If yours is different you’ll want to do something like the following:
1 | git svn clone --trunk='/Developer' --tags='/Releases' --authors-file=users svn://reposerver/foo/bar |
Of course you might need to do some tweaking there.
Now, we have three other svn:externals repositories in our repo. This is the most ghetto part of all of this, and it’s probably just because I haven’t done the appropriate research. Again, if you know better, just tell me. (Normally with git you’d do this with a submodule, but we aren’t going to do that because we want to directly check the “submodule” out from svn so we can commit back easily. If you don’t know what a submodule is, ignore this
)
1 | git svn clone --stdlayout --authors-file=users svn://reposerver/svnexternal1 $to_name |
This will check out the svnexternal1 repo to a folder called $to_name. If you need to check it out to a separate subdir either cd into that dir or change $to_name.
You don’t want to check that into svn because your coworkers already have an svn:externals for that. Normally this would be done with .gitignore, but we won’t use that because your coworkers don’t want a .gitignore file in their repository. Instead you’ll use .git/info/exclude, which is the same thing but not inside of the repo. Just put $to_name on a single line in that file and it won’t show up in your available changes when you need to commit.
Speaking of commiting, how do you commit? Normally your workflow should be the way it is with git. You commit often and when you are ready for a feature to go to the team you push it out. I usually rebase and clean up commits before I push, but that’s up to you. The main difference is that you don’t do git push … Instead you’ll do
1 | git svn rebase && git svn dcommit |
git svn rebase actually checks out the new changes from svn and puts them in your repository before the changes you’ve already committed. If there are conflicts you’ll have to deal with those of course, but otherwise it will just pull in the changes and then use dcommit to submit new changes. You should not have any uncheckedin changes when you do this (it will complain if you do) because dcommit actually does a different kind of rebase after checking in changes. It changes your commits to include the svn id so that the git commits match up with the svn commits.
In general that’s all there is to it. At some point I’d like to do a post about how I use git rebase fairly often in my workflow, but this I think is a lot more important. Oh and here are some cool new git features I learned today. Enjoy
22 Jul
Yesterday I released a new (major version of) Devel::Dwarn, or what is technically Data::Dumper::Concise. But those in the know call it Devel::Dwarn.
If you did not already know, Devel::Dwarn is sugar + good defaults for Data::Dumper. Check it out. Drool. Use it.
Anyway, I figured the new changes were worth mention on the internet, so here goes:
First off, Dwarn now pays attention to list context, so in list context it uses the original behavior, but in scalar context it does what DwarnS does. One of my coworkers got bit by the Dwarn vs DwarnS distinction so much that he only uses DwarnS now. Hopefully this will remedy that issue.
Next up is that Dumper (and also Dwarn because it uses Dumper) no longer returns an object when passed zero arguments. If you used that I’m sorry; but it just bit most of us when we tried Dwarn(@foo) and @foo was an empty list. Sorry, it’s gone!
Last, is the brand new DwarnN. DwarnN is a neat debugging tool which will label your output by the variables passed in. So if you do DwarnN $foo it will print ‘$foo => ‘ . Dumper($foo). Not world changing, but still very helpful!
Hopefully this will ease your job that much more!
20 Jul
Over a year ago I read this blog post. To be honest at the time I thought it was mostly silly and I still feel that way. The things that are important to me in an ORM are capabilities, not subjective prettiness of code. But, I also get tired of typing repetitive things, especially __PACKAGE__->. That’s just too many shift keys! So after working on a few different modules and accruing various bits of knowledge here and there I learned what I needed to to create a sugar layer for DBIx::Class that doesn’t throw the baby out with the bath-water.
I am proud to announce the initial, development version of DBIx::Class::Candy, which should be coming to a CPAN mirror near you very soon. If you just can’t wait, use cpanf to get it right now. The basic gist of it is that you can use:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | package MyApp::Schema::Result::Artist; use DBIx::Class::Candy; table 'artists'; column id => { data_type => 'int', is_auto_increment => 1, }; column name => { data_type => 'varchar', size => 25, is_nullable => 1, }; primary_key 'id'; has_many albums => 'A::Schema::Result::Album', 'artist_id'; 1; |
instead of
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | package MyApp::Schema::Result::Artist; use strict; use warnings; use base 'DBIx::Class::Core'; __PACKAGE__->table('artists'); __PACKAGE__->add_columns( id => { data_type => 'int', is_auto_increment => 1, }, name => { data_type => 'varchar', size => 25, is_nullable => 1, } ); __PACKAGE__->set_primary_key('id'); __PACKAGE__->has_many( albums => 'A::Schema::Result::Album', 'artist_id' ); 1; |
There are a few other features, like having it turn on 5.10 or 5.12 features, use a non standard base, and more. Check it out now!