Archive | Tech
The JavaScript Identity Operators
I’ve heard rumors of this before, but didn’t quite grok it. And now that I do, it’s very cool yet very strange. To demonstrate:
js>var n = "1" js>1==n true js>1===n false
Yep, n is both equal and unequal to 1. But what’s up with that === operator? As many of you know, JavaScript is dynamically typed. If you check to see if two objects are equal using ===, JavaScript will try to figure out if they are the same type and, if not, try to get them to that same type. So, in the example above, n is a string with value of 1 and when you compare that to the Number value 1, they are the same.
But === doesn’t do the conversion. Instead, if it sees two objects aren’t of the same type, it says they aren’t equal automatically. This is more in line with how Python and Java work — i.e. statically typed languages. They call this an “identity operator”. Naturally there is a !== operator as well that returns true if the objects are not equal.
In Douglas Crockford’s awesome JavaScript presentations, he recommends always using the identity operators instead of the equality, unless you are purposely comparing to different objects. I tend to agree — not having automatic type casting should reduce bugs as well as improved performance.
YUI TreeView
As usual, it’s quiet around here because my life hasn’t been so quiet lately. Lots happening at work and lots happening at home. And I still don’t have my lawn mowed.
And one of my things I seem to be lacking on blogging is JavaScript. But that doesn’t mean I haven’t been using it! No, I devote many hours a day with it. I’ve been using the YUI components heavily and they are oh-so-pleasant to use. They really take over the low-level work and let you concentrate on the important stuff.
Example: today I was playing with a TreeView object and making the leaves of the tree appear in a table when clicked. This is easier than I ever thought it would be.
First, I saved the leaf node with an ID and a label, because I wanted them both in the same row but different cells. I also wanted the row to be able to match to the ID so I could get to that row easily if need be. This is how I saved the node:
var nodeData = {label: mylabel id: myId}
var txtNode = new YAHOO.widget.TextNode(nodeData, node ,false);
And this is how I took that data from the tree node and put it in the table:
tree.subscribe("labelClick",function(node) {
// if it doesn't have children, then it must be the text
// of a rule
if ( ! node.hasChildren() ) {
// we are only going to add it once
if (document.getElementById(node.data.id)!=null) {
return ;
}
var myTable = document.getElementById("tableID");
var numRows = ruleTable.rows.length;
var row = ruleTable.insertRow(numRows)
row.id=node.data.id;
var idCell = row.insertCell(0);
idCell.innerHTML=node.data.id;
var txtCell = row.insertCell(1);
txtCell.innerHTML=node.data.label;
}
})
And that was that.
Powered by ScribeFire.
Microsoft is losing it’s edge
In VBA for Macintosh goes away Joel Spolsky says:
When Microsoft lost the backwards-compatibility religion that had served them so well in the past, they threatened three of their most important businesses (Office, Windows, and Basic), businesses which are highly dependent on upgrade revenues.
Interestingly enough, Apple threw out their backwards-compatibility religion and make OSX, which has served them very well — their market share is increasing. But MS already has the vast majority of users — meaning, they can’t grow anymore. It’s either upgrade, stay the course, or move to something completely different. Microsoft has removed on the only thing that will make them money. At least in their current model. I can and do say all sorts of negative things about Microsoft, but I will be the first to admit that they learn from their mistakes and are highly adaptable. But how will they adapt to this?
Powered by ScribeFire.
Putting Object Ownership in Django
I’m working on a Top Secret web project that I will talk more about in the near to medium future. Because I’m a Python nut and need to make simple web application that has complex business rules (i.e. the technology isn’t complex, but the business logic can be ) I chose [Django](http://www.djangoproject.com/) as my engine of choice.
One of the issues I ran into is Django’s security model. By default, if a user or a group has permission to that object, the users have permissions on **all** those objects. This isn’t what I wanted — I wanted to give the idea of “ownership” to the object, so only the owner and/or the superusers can change that object.
This isn’t as easy as it appears. Django does have a branch called [per-object-permissions](http://code.djangoproject.com/wiki/RowLevelPermissions) that would do it, but it hasn’t been merged with the trunk for a while and I found it too late — I was already writing stuff for Django 0.96! So I had to come up with my own method. But, when that branch is merged, I would like to use it. I would do the merge myself, but it wouldn’t be an easy process and I have other things to do now.
I took some good, hard looks at the admin views and decided that I needed to either rewrite these views or intercept them before going to those functions. The first one that I wrote, the one that displays all the objects a user has permissions to change. This came from `change_list` view in `admin/views/main`
from django.contrib.admin.views.main import ChangeList,IncorrectLookupParameters
def my_objects(request):
app_label = ‘myapp’
model_name = ‘myobject’
model = models.get_model(app_label, model_name)
if model is None:
raise Http404(“App %r, model %r, not found” % (app_label, model_name))
if not request.user.has_perm(app_label + ‘.’ + model._meta.get_change_permission()):
raise PermissionDenied
try:
cl = ChangeList(request, model)
if not request.user.is_superuser:
owner_objs=list(MyObject.objects.filter(owner=request.user))
these_objs = cl.result_list
new_objs = []
for f in owner_objs:
if f in these_objs:
new_objs.append(f)
cl.result_list=new_objs
cl.result_count = len(cl.result_list)
except IncorrectLookupParameters:
if ERROR_FLAG in request.GET.keys():
return render_to_response(‘admin/invalid_setup.html’, {‘title’: _(‘Database error’)})
return HttpResponseRedirect(request.path + ‘?’ + ERROR_FLAG + ‘=1′)
c = template.RequestContext(request, {
‘title’: cl.title,
‘is_popup’: cl.is_popup,
‘cl’: cl,
})
c.update({‘has_add_permission’: c['perms'][app_label][cl.opts.get_add_permission()]}),
return render_to_response(['admin/%s/%s/change_list.html' % (app_label, cl.opts.object_name.lower()),
'admin/%s/change_list.html' % app_label,
'admin/change_list.html'],
context_instance=c)
I’m sure that this could be better — in fact, I’m not sure I had to rewrite the whole thing. I could have just intercepted the objects before making the list, somehow. And I know that the queries could have been better. But this works well.
The view that displays the individual object for editing is much easier. In this function, I simply intercepted the call, checked the permissions, and if they were okay, the view sends them to the proper view, which is `admin.views.main.change_stage`. I like how this one turned out over the view above:
from django.contrib.admin.views.main import change_stage
def edit_object(request,object_id):
if not request.user.is_superuser:
objects=list(MyObject.objects.filter(owner=request.user))
this_obj = MyObject.objects.get(id=object_id)
if not this_obj in objects:
raise PermissionDenied
return change_stage(request,’myapp’,'myobject’,object_id)
After doing all this, you have to change your `urls.py` to go to your new views instead of the standard admin views. So I added these in my `urlpatterns` object there:
(r’^admin/myapp/myobject/$’, ‘myapp.views.my_objects’),
(r’^admin/myapp/myobject/(?P
So that’s it — this is what my app will be using until the Per-Object-Permissions gets merged (or a recent trunk gets merged to that branch). I think that solution is better.
The Joy of Z-Shell
Late last week, I finally got the opportunity to upgrade my Cygwin to something modern. Like, you know, within the past month instead of three years old. But after the upgrade, bash was really giving me fits. Horrid fits. Like not understanding blank lines in my scripts; completion was way off. And other nasty bits.
I’ve had looking at Z Shell for a while now and, since my bash was broken, I decided there was no better time like the present. Among others, Ted Leung likes zsh and I think Ted is smart. It was worth a try.
Converting my all-important bash aliases was easy — because zsh uses the same syntax. Just a <code>source ~/.aliases</code> loaded my alias file. Wonderful stuff.
You can do a ton of customization with zsh and you probably will want to. Luckily, on Cygwin, zsh notes if you have a <code>~/.zshrc</code> file and, if not, asks you to configure one. It steps you through a few different commands (like tab completion, etc.) and then saves it. Zsh uses “smart completion” similar to the bash-completion project. Only it’s not a separate download. In other words, if you have have new files you want to add to your svn project, type <code> svn add [tab]</code> and Zsh will display the files that aren’t in your project yet. Neato.
Another neat completion trick — <code>./*.py[tab]</code> will display all the .py files in your directory. Even if you have 100%. You can also configure a menu of candidates during completion
There are other tricks besides completion:
- hitting a ” and then a newline will give you a prompt that says “quote>”, so you know where you left off. Something similar happens with a for statement, etc.
- It has a bunch of built-in prompts. Once you initialize <code>promptinit</code> type <code>prompt -l</code> to see a list, and the <code>prompt [name]</code> to choose that prompt. I’m currently using “bart”.
- Putting an = before a word does a which on that and then runs the command. For example, <code> ls -l =python</code> is the same as <code>ls -l `which python`</code>.
So I’m sold for now. Z Shell is very cool indeed.
Powered by ScribeFire.
