A piggy bank of commands, fixes, succinct reviews, some mini articles and technical opinions from a (mostly) Perl developer.

Perl Webform CRUD

I have a dream that I can use Perl to build a webpage that allows me to view what's in a database table, and to add new rows to it, *without specifying any of the fields or constraints*!

Okay, maybe I might want to map column names to user-friendly labels, or add additional constraints to the fields (e.g. email address), but that's it.

I particularly don't want to duplicate the constraints which I've already programmed into the database table once. i.e. The form should only validate input data against the database schema, and feed back appropriate errors/warnings.
I don't want to have to duplicate the column list in the database, by defining all the form fields in a configuration file.
And I definitely don't want to have to write any HTML at all.
I must be able to completely integrate the system into my own framework.

UPDATE:
Perhaps if I don't specify pretty names for the columns, or their order, then I end up with a database management tool like phpMyAdmin. This means configuration of the fields is necessary for a real web app.
Probably the same goes for HTML output - its purpose is to lay out the page, so I am required to list the fields there as well.
But I really dislike having to edit all three files (schema, config, and template) when I add a new database column.

Possible modules for DBIx:
  • Catalyst::Manual::Tutorial::09_AdvancedCRUD::09_FormFu - Handles the database part automagically. We define the webform fields, along with any additional constraints and helpful validation features in a configuration file. The fields must also be defined in the template. However, error messages defined in the config file will appear automatically in the right place in the form (with a little help from CSS).
    • HTML::FormFu - This seems to be the best thing.
    • Catalyst::Model::HTML::FormFu (deprecated)
    • Catalyst::Model::FormFu - "Speedier interface to HTML::FormFu for Catalyst"
  • HTML::FormFu::Model::DBIC - "Integrate HTML::FormFu with DBIx::Class". The form fields must be specified in config, and they must match the DBIx class schema.
  • Catalyst::Plugin::FormBuilder - "merges the functionality of CGI::FormBuilder with Catalyst and Template Toolkit" - ?
    • Catalyst::Controller::FormBuilder
  • Catalyst::Example::InstantCRUD - contains DBIx::Class::InstantCRUD. Presumably this is meant to be a database admin tool. See instantcrud.pl
  • Catalyst::Plugin::CRUD::DBIC - "CRUD plugin for DBIx::Class". Looks promising, but the fields also must be listed in an HTML template.
  • DBIx::HTMLinterface
  • DBIx::HTMLView 
  • DBIx::Class::HTMLWidget
  • DBIx::Class::FormTools
  • Catalyst::Helper::Controller::Scaffold
  • Catalyst::Enzyme 
For CGI:
  • CGI::Application::Plugin::BREAD 
  • CGI::Prototype 
  • CGI::FormBuilder - "I hate generating and processing forms" (the author). But do we still have to specify the form fields using Perl code?
See also:
Modules I've actually seen in use:

  • HTML::FormHandler - example
  • Data::FormValidator

Git basics

Have git remember merge conflict resolutions so you never have to do them more than once:
git config --global rerere.enabled 1

Prevent "git push" with no parameters from pushing anything other than your current branch:
git config --global push.default current

Show a graphical summary of the merge tree (looks a bit like gitk).
This gives the answer to "Have I pushed or not"? :
git log --decorate --color --graph  --oneline


Find the point at which you forked (branched):
git merge-base [branch] [trunk or previous branch]


Show all changes made in this branch (if you branched from master):
git log --oneline --name-only --reverse master..HEAD


Ensure only one commit per file; pipe the above through:
| grep -v '^....... ' |sort |uniq -c |sort -nr 
 
Edit all commit messages since a particular commit:
git rebase -i $(git merge-base [branch or HEAD] [trunk or previous branch])


Undo the last commit made locally (e.g. in order to re-do it differently, perhaps in the middle of a rebase): 
git reset HEAD^


To reverse a pushed commit two commits back,
first reverse the second most recent commit, and then commit it back:
git revert -n HEAD~1
git push origin branch
(Do not try to rebase what has been pushed, it will not work. Rebase only changes your local repo)

To revert a merge commit:
git revert SHA -m 1
(Where SHA is the commit ID)

Reset a branch to be same as the repo:
git reset --hard origin/branch_name

Delete a branch:

git branch -D branch_name # delete it locally
git push origin :branch_name # delete it on remote


Use a branch in a different repo for the same project:
git remote add repo_shortname user@server:/repo_name
Use different branch names in each repo.
Push to your repo_shortname instead of origin.

Create a new, tracked branch:
Tracked means that 'git status' will show you how many commits behind the parent branch you are, and if the parent branch has diverged (which means you might want to rebase onto it)
git checkout master # or wherever you want to branch from 
git checkout -t -b my_new_branch

Easily make an alteration to a previous commit:
git commit -m'fixup! same title as another commit' filename
git rebase -i --autosquash [commit id]

(the commit will be put in the correct place and marked as 'fixup' automatically)

A git workflow:
(dca-73 is the name of a branch)
git fetch
git checkout dca-73
git pull origin dca-73
# run tests
# make changes
# run tests
git fetch
git push origin dca-73
git checkout master
git pull origin master
git merge --no-ff dca-73

# run tests

# check it looks right
git log --decorate --graph --oneline

git push origin master




How to merge conflicts without editing the file:

git checkout --ours path/to/filename
git checkout --theirs path/to/filename


Automatically run checks on your code before committing with git hooks:
e.g. Just edit the file .git/hooks/pre-commit in your working directory, and make it executable.
It will not be committed along with your code because it's in the special .git directory.

PostgreSQL basics (for MySQL users)

Installing

  • sudo apt update
  • sudo apt install postgresql postgresql-contrib
  • sudo service postgresql start
  • sudo passwd postgres # then close and re-open the terminal(?)
  • sudo -u postgres psql
    • create user foo;
    • alter user foo with superuser;
    • alter user foo with password 'new_password';
  • psql -Ufoo -d postgres

Reconfigure authentication if necessary to either require or disable passwords.


Using


MySQL and Postgres command equivalents (mysql vs psql)

connect: psql -U [username, e.g. postgres] -d [database]
  • \c dbname = connect to dbname
  • \l = list databases:
  • \dt = describe tables, views and sequences
  • \dt+ = describe tables with comments and sizes 
  • \dT = describe Types
  • \di = describe indexes
  • \q = quit
  • \x = toggle equivalent of adding MySQL's \G at the end of queries to display columns as rows 
  • \connect database = change to a different database
  • CREATE DATABASE yourdbname;
  • CREATE USER youruser WITH ENCRYPTED PASSWORD 'yourpass';
  • GRANT ALL PRIVILEGES ON DATABASE yourdbname TO youruser;
  • Use auto_increment in a column definition:
    • create sequence foo__id__seq increment by 1 no maxvalue no minvalue start with 1 cache 1; 
    • create table foo ( id integer primary key default nextval('foo__id__seq') );
  • Reset an auto_increment counter (sequence):
    • SELECT setval('sequence_name', 1, false); -- this works
    • ALTER SEQUENCE sequence_name RESTART WITH 1; -- this also works
  • See what's in an ENUM
    • SELECT enumlabel  FROM pg_enum WHERE enumtypid = 'myenum'::regtype ORDER BY id;
  • Closest equivalent of MySQL's "show create table"
    • pg_dump -U postgres --schema-only [database] >> dump.sql
  • See current activity
    • SELECT * FROM pg_stat_activity (equivalent to MySQL's "show processlist")
  • Drop all current connections
    • SELECT pg_terminate_backend(procpid) FROM pg_stat_activity WHERE datname='foo'; # foo = database name
Other stuff
  • pg_dump -Upostgres -hHOSTNAME DBNAME -fOUTPUTFILE.sql --no-password
  • psql -Upostgres -hHOSTNAME -dDBNAME -fINPUTFILE.sql
  • psql -Upostgres -hHOSTNAME -dDBNAME -c "Some SQL command"
      See also

      Audio in Ubuntu

      Don't do this:
      sudo apt-get remove pulseaudio gstreamer0.10-pulseaudio
      
      
      Something:
      $ sudo dpkg-reconfigure linux-sound-base

      Volume control:
      $ alsamixer