If you steal from one author, it's plagarism; if you steal from many, it's research
The first Drive-in movie theatre was built in Camden, New Jersey
I hate comment spam. As if a mailbox full of solicitations to buy cialis soft tabs is not enough, now I have to deal with my blog posts being barraged with comment spam. What's the solution? I obviously can't go on accepting all of these spam posts, so what's a guy to do? Here are some options:
The solution I chose? No anchors. I know - that last bit about pillars and faltering is quite dramatic, but I just have to beleive that this is the best solution for me right now. A regular expression based implementation was put into place and seems to be working well so far. Leave me a comment if you disagree with my position here - just be sure not to leave me a link :)
Saturday, December 02, 2006 12:09 AM ESTThis has to be the funniest Jersey joke I've heard in a while (From the movie 'Just Friends')
Are you kidding? You're Chris Brander. You're Hollywood; you date models. He's Jersey; he skis in his jeans.Wednesday, December 06, 2006 08:55 AM EST
I guess I should have learned this a long time ago - but when a tiny piece of code kicks my ass this bad, I like to share it with the world :) How many times do you expect the following Javascript to alert 'hi'?
function x() {
for(i=0; i<8; i++) {
y();
}
}
function y() {
for(i=0; i<2; i++) {
alert('hi');
}
}
x();
The answer - An infinite number of times! Believe it or not, when the Javascript interpreter comes across a variable without the var keyword in front of it, it automatically creates a global variable with the given variable name. Fun stuff.
Monday, December 18, 2006 10:23 PM ESTIf given a choice between simple and complex, Rails will always lean towards the simple (actually, it crashes into the simple side of things.) Most of the time this is a nice, refreshing change from the J2EE world, whose committee seems to get off on adding complexity into every nook and cranny of the J2EE spec. However, sometimes there are real complexities in the problems we are trying to solve. Consider the following domain model:
Now, let's suppose you would like to display the rendered html version of this entire object graph to the user on a single page with only one form. If you've done any rails development in the past, you're probably thinking "It can't be that bad". After all, Rails almost enforces that you follow domain-driven design, so how hard can it be to satisfy this requirement? update_attributes to the rescue! Take a look at the RDoc:
Sounds great right? But wait - what if the method fails? Can we still access the error messages as if i called the save or valid? method directly on each object? Will the framework know which properties have errors associated with them to insert the proper 'fieldWithError' class names while rendering the response? Unfortunately, the answer is No. The update_attributes method is therefore worthless to me, and exists as nothing more than an absolute tease. However, I'm sure the Rails core developers will argue that they were just 'keeping it simple'. I applaude that. But I still have to satisfy this requirement that goes against the seemingly conventional Rails wisdom of a single object per page.
So what options are we left with here? I could refactor my interface to break the object graph into multiple screens, but that would add lots of complexity to my user interface, which I believe should remain simple at all costs (even if it means adding complexity to the back-end.) So refactoring the interface is out. I suppose I could just walk the object graph and populate and save each object directly, collecting any error messages that arise as we make our way to the bottom of the graph. Populate and save you say? That's what update_attributes is for. So maybe we can validate each object on our way down, and then use the update_attributes on each object. Sounds good right? Wrong again. update_attributes maintains its own transaction, which means that once an object is updated, it cannot be rolled back if another object's validation or save fails. The entire group of saves needs to be wrapped in a transaction. It looks like the optimal solution in this case is to use the attributes= method to populate the attributes from the parameters hash and the save method to do the persisting, all within one transaction.
This solution will work (and does work for a couple apps I have written.) However, the complexity of the save operation increases for each entity you add to your domain model (luckily, this seems to be only a linear increase.) But seriously, I can't help but to think there's a better way to do this...
Friday, December 29, 2006 01:12 PM ESTAs I said in my last post, I can't help but to think there is a better way to persist object graphs in Rails applications. The solution I outlined last time seems to stray from the DRY principle (Don't Repeat Yourself,) and just seems to leave a bad taste in my mouth. Don't you wish there was some way to leverage the meta-programming capabilities of Ruby and Rails to solve this problem in a generic way? Me too. Consider the following sketch of a solution:
def update_object_graph(root_entity, entities_seen = [])
# return if we've processed this entity already
return if entities_seen.include?(root_entity)
entities_seen << root_entity
errors = []
parameter_name = root_entity.class.name.underscore
# if paramaters are given for the root entity, then we update it
if params[parameter_name]
keys = params[parameter_name].keys
index = keys.index(root_entity.id.to_s)
root_entity.attributes = params[parameter_name].values[index]
errors += root_entity.errors.full_messages unless root_entity.save
end
forward_associations =
root_entity.class.reflect_on_all_associations -
root_entity.class.reflect_on_all_associations(:belongs_to)
forward_associations.each do |association|
# ignore acts_as_versioned association tables
next if(/::Version$/ =~ association.class_name)
raise unless root_entity.respond_to?(association.name)
# Deal with has_one associations
if(association.macro == :has_one)
assoc_entity = root_entity.send(association.name)
new_errors = update_object_graph(assoc_entity, entities_seen)
errors = errors + new_errors if new_errors
# Deal with has_many and habtm associations
else
association_entities = root_entity.send(association.name)
association_entities.each do |assoc_entity|
new_errors = update_object_graph(assoc_entity, entities_seen)
errors = errors + new_errors if new_errors
end
end
end
errors
end
The idea here is that we first update the current entity with any corresponding values in the parameters hash. Then we attempt to
save the entity and collect any errors. Remember, since the save method is called on the actual instance of
the entity in question, it's erorrs collection will be populated and used when rendering the page. Now things get interesting - we discover the
associations of the entity, and then use reflection to obtain references to the actual objects that represent those associations. Now we recursively call persist_object_graph on each of these objects.
Makes perfect sense right? Let me first say that this code doesn't actually work: it is just a sketch of a solution and has lots of oversights (no support for composed_of aggregations, it makes assumptions about the names of things, etc.) However, I was hopeful that I could take this idea and run with it. Unfortunately, this solution hits a brick wall when we back up and take a real close look at the Active Record design pattern. Can anyone spot the subtle but major flaw here?
Saturday, December 30, 2006 04:20 PM EST