This time no story giving insight in to my life as a superhero developer; instead straight to the facts. When you write a .gitignore file, precede each entry with a forward slash. So instead of writing:
*.zip
You should write:
/*.zip
It means zip files only get ignored in the same directory as the .gitignore file, and not in each subdirectory. Do this on principle, and optimize later if you find it is an extension you really want ignoring project-wide. (In other words wait for the noise to appear before using .gitignore to suppress noise.)
Especially important for websites: I may have a temporary zip file in the root of the website from a designer, but deeper in the site I may have zip files that users are supposed to download.
Friday, October 28, 2011
Saturday, October 22, 2011
Frapi (PHP web service API system)
I read about Frapi in PHP Architect (May 2011), and spent a couple of
hours trying it out. It is quite interesting, but I
don't think I will be using it. It is a full web-interface for
making the API. This is what makes it cool, but also its biggest
disadvantage. There is a lot of code involved, meaning there is a lot to
learn if you need to change it and lots of places for bugs and security exploits to crop up.
It comes with a documentation generator, which could be really useful. This feature is still incomplete (for instance there are no links to it yet, see here, PDF generation didn't work properly), but it looks okay.
There is one specific limitation: I could not create an action with an optional parameter, at least not using the router. E.g. if my action is called "ddd", then I can call /ddd (no parameter). But I cannot call "/ddd/77". (I can give an optional parameter with /ddd?id=77). Or I can define a router as "/ddd/:id" so that I can call "/ddd/77". But in that case id is now required and I cannot use "/ddd".
Another disadvantage is no built-in support for oAuth. (I did find an oauth extension for Frapi but did not try it as the integration seems quite rough still.)
Incidentally if you were looking for a full application built on Zend Framework this may make the perfect study case. Apparently only the admin interface uses ZF, and the actual web services do not; but as far as I can tell they are closely tied and you need to keep both together even on your production servers.
Overall, because making a web service in PHP is not that hard, the advantages are slight and not enough to outweigh the disadvantages (large codebase, inflexible structure, etc.).
It comes with a documentation generator, which could be really useful. This feature is still incomplete (for instance there are no links to it yet, see here, PDF generation didn't work properly), but it looks okay.
There is one specific limitation: I could not create an action with an optional parameter, at least not using the router. E.g. if my action is called "ddd", then I can call /ddd (no parameter). But I cannot call "/ddd/77". (I can give an optional parameter with /ddd?id=77). Or I can define a router as "/ddd/:id" so that I can call "/ddd/77". But in that case id is now required and I cannot use "/ddd".
Another disadvantage is no built-in support for oAuth. (I did find an oauth extension for Frapi but did not try it as the integration seems quite rough still.)
Incidentally if you were looking for a full application built on Zend Framework this may make the perfect study case. Apparently only the admin interface uses ZF, and the actual web services do not; but as far as I can tell they are closely tied and you need to keep both together even on your production servers.
Overall, because making a web service in PHP is not that hard, the advantages are slight and not enough to outweigh the disadvantages (large codebase, inflexible structure, etc.).
Labels:
php,
php|a,
web services
Thursday, October 20, 2011
R: what to do when the jitter gets too much
The subject sounds like this will be a discussion of an over-full bladder... instead, brace yourself for some serious functional programming.
So, I had this little bit of R to generate a "rough" exponent curve (as test data):
The problem was it was sometimes giving NA values - too much jitter!
I started off with this fix:
I.e. wherever it was an NA use the un-jittered value.
Unfortunately it was often complaining with "number of items to replace is not a multiple of replacement length". In this case this was not a warning to ignore, because it revealed I was doing something very wrong. exp(x) is a vector of 40 items. y[is.na(y)] is a vector of however many entries in y are NA. The dangerous thing is if there is just one NA in y, but it is the 5th element, it will be set to exp(1)^0.5, instead of exp(5)^0.5.
Let's cut straight to the solution:
y[is.na(y)]=exp(x[is.na(y)]^0.5)
x[is.na(y)] means the values out of x where the same-sized y-vector has a NA in that position. So, for the above example where just the 5th element in y is NA, then x[is.na(y)] will be "5".
Simple when you know how. (?!)
So, I had this little bit of R to generate a "rough" exponent curve (as test data):
x=1:40
y=exp( jitter( x, factor=30 ) ^ 0.5 )
The problem was it was sometimes giving NA values - too much jitter!
I started off with this fix:
y[is.na(y)]=exp( x^0.5 )
I.e. wherever it was an NA use the un-jittered value.
Unfortunately it was often complaining with "number of items to replace is not a multiple of replacement length". In this case this was not a warning to ignore, because it revealed I was doing something very wrong. exp(x) is a vector of 40 items. y[is.na(y)] is a vector of however many entries in y are NA. The dangerous thing is if there is just one NA in y, but it is the 5th element, it will be set to exp(1)^0.5, instead of exp(5)^0.5.
Let's cut straight to the solution:
y[is.na(y)]=exp(x[is.na(y)]^0.5)
x[is.na(y)] means the values out of x where the same-sized y-vector has a NA in that position. So, for the above example where just the 5th element in y is NA, then x[is.na(y)] will be "5".
Simple when you know how. (?!)
Labels:
R
Tuesday, October 11, 2011
Renaming files is easy!
What do you mean? Of course renaming is easy! From the GUI just click it and type the new name. From the linux commandline just type
But what about when you have 200 *.JPEG files and you need to rename them to be *.jpg? In the past I've written throwaway PHP scripts to do just this. Well, it turns out linux has a command called
What about a few thousand log files, and I want to remove the datestamp portion from the filename (because I'm going to keep each day's logs in their own subdirectory)? How about this:
(See here for how to then use a bash loop to loop through all the datestamps you have to deal with.)
mv oldname newname
.But what about when you have 200 *.JPEG files and you need to rename them to be *.jpg? In the past I've written throwaway PHP scripts to do just this. Well, it turns out linux has a command called
rename
, that can use regexes. To rename those jpegs:rename 's/JPEG/jpg/' *.JPEG
What about a few thousand log files, and I want to remove the datestamp portion from the filename (because I'm going to keep each day's logs in their own subdirectory)? How about this:
mkdir 20110203 mv *.20110203.log 20110203/ rename 's/.20110203//' 20110203/*
(See here for how to then use a bash loop to loop through all the datestamps you have to deal with.)
Labels:
commandline,
linux
Subscribe to:
Posts (Atom)