Inherited Resources and Manipulating the Parameter Hash

The Inherited Resources gem is very useful at de-cluttering our controller code. And the documentation is pretty great at telling us how we can manipulate this clutter within the conventions of the gem itself. For example, if we want to, we can easily change the redirect of a controller action.

Recently I wanted to manipulate the model parameters of the params hash in a controller that uses Inherited Resources. Changing the params hash is probably (that is, almost certainly) a bad idea, but what the heck. I couldn’t think of a better work around at the time. Here’s how I did it.

The issue: We want to manipulate the params hash of a controller that uses Inherited Resources

The solution: We overwrite the build_resource_params method. We first permit the parameter keys that we expect. Then we manipulate the model parameters to our whim, before returning it.

Despite being fairly familiar with Inherited Resources and its various overwrite options, I was stuck on this for quite a while. I kept getting an ActiveModel::ForbiddenAttributesError which means (surprise) that the attributes in our params hash have not been permitted.

Let’s say we have an Animal model and a corresponding AnimalsController. We want to modify the Animal parameters in the params hash. We’d need something like this as our build_resource_params:

class AnimalsController < ApplicationController
inherit_resources
..
protected
def build_resource_params
animal_params = params.fetch(:animal, {}).permit(:name, :age, :family)
[prepare_animal_params(animal_params)]
end
def prepare_animal_params animal_params
# here we manipulate the model parameters however we want
# e.g. animal_params[:age] = 1 if animal_params[:age] < 0
...
# importantly this method must return the model params
animal_params
end

And that’s it!

Note: if we had overwritten the permitted_params to allow our Animal parameters, this overwrite wouldn’t be needed any more as the permission step now happens in the build_resource_params.

Learning a new paradigm is refreshing

Wednesday evening is my new happy place. Why? Because it’s Clojure study group time! After Berlin’s first ClojureBridge, two off-shoot project groups were formed: an art group, focusing on libraries like Quil and Overtone, and a web development group. I am part of the latter.

While we do have an over-arching web project in mind, we have for the last two weeks been working through simple programming exercises and katas in Clojure.

Usually when faced with programming tasks like these, I have some idea how or where to start. It might not be the right or best solution, but it is something. And in my experience, having worked with or at some point studied Python, Java, C++, PHP, and Ruby, this something can carry across the different languages in some form or another: a for-loop here, inheritance there, whatever.

Of course, with Clojure, it’s different. If I’m thinking about objects or for-loops, I’m not thinking in a useful way. Rather I have to think about things like data structures and — surprise — functions. This conscious shift that I make in my thinking is similar to the shift my mind makes when I switch from speaking one natural language to another. If I try to speak French while thinking in English, I may use French words, but my expression remains awkwardly English.

Importantly, though, persevering so that we become able to make this shift — whether in relation to programming or natural language — will give us new ways of thinking about things. When faced with a programming task, we will be able to think about a functional solution in addition to a procedural or Object-Oriented one.

But I’d say that the best part about learning a new programming language, particularly one from an unfamiliar paradigm, is the novelty of it all. It’s like starting over, learning to code for the first time. When I wrote my first few lines of Python, it was like magic. Everything was new and exciting. A for-loop, wow! How does it work? Nested for-loops?! Amazing! It’s the same now with Clojure: (map) what now?! Wizardry!