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:

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.

Advertisements

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!

Conditional validation with Rails

Let’s say we have a User model that has a unique username, something like this

And let’s say that users can be active or inactive, and we scope our model accordingly.

Now, imagine that we want usernames to be unique, but only among active users.* In other words, active users can have the same usernames of inactive users. If we have a user with the username “Alice”, and this user is inactive, then our validations should not stop us from creating a new, active user with the username “Alice”.

How do we do this? Simply, we make our uniqueness validation conditional.

* We can think of other real-world scenarios where we might want to do this e.g. expired e-mail addresses, archived articles

formtastic and has_one relationship: workaround

I’ve implemented many belongs_to and has_many relationships via ActiveAdmin and formtastic, but never a has_one relationship. I found a quick fix via this git issue.

Let’s take a simple example: we have users and each user “has_one” pet. The ActiveAdmin setup is similar to other relationships.

And this is the setup for our formtastic nested form

The hack in particular is f.object.pet || Pet.new. (With many thanks to simonc!)

Using jQuery Stickem with containers of variable height

I’ve been using jQuery Stickem on a current project to “stick” the sidebar to the top of the page on scroll (see Stickem’s own demo here).

To set up Stickem, we have an outer container, an inner container, and inside this, the element that we want to be sticky. In the Stickem usage example, the outer container is the “.container” div, the inner container is the “.stickem-container” div, and the sticky element is the “.stickem” div.

As the usage example shows, we then use CSS to position the divs, and jQuery to initialise Stickem on the outer container.

The trouble comes when we have a container of variable height. For example, if we have slow loading images on the page, then stickem is initialised before these images are loaded. This means that the container height that stickem calculates will not include the height of the images and the sticky element will “unstick” sooner that we’d like.

The issue #1: Calculating the correct container height for stickem with slow loading elements

The solution #1: Initialise stickem on window.load rather than on DOM ready. This way, the height of the slow loading elements will be included in stickem’s height calculation

This works for slow loading elements such as images, but what about containers with tabs of variable height? Stickem calculates the height of the initially open tab, but if we change to a tab of a larger height, again we have the trouble of the sticky element “unsticking” sooner than desirable.

The issue #2: (Re-)Calculating the correct container height for stickem when using Bootstrap tabs of variable height.

The solution #2: In this case, we want to “destroy” the original stickem instance, and re-initialise stickem once the content of the newly opened tab is shown — that is, when Bootstrap’s ‘shown.bs.tab’ event fires.

A similar approach is recommended for Ajax-loaded content.

Draper CollectionDecorator and pagination with kaminari

I’m working with kaminari today, and I spent a bit of time getting Draper to co-operate with the pagination. This is a fairly well documented issue, but I figured I’d post about this for my own future reference.

The issue: getting kaminari methods (such as current_page, total_pages, etc) to work on a decorated collection.

The solution: We need to delegate the kaminari methods, so that Draper knows to ignore them.

How to do this?

  1. Create a separate PaginatingDecorator that inherits from CollectionDraper, and delegate the kaminari methods.
  1. In your ApplicationDecorator class, make sure that CollectionDecorator knows to look at PaginatingDecorator.
  1. If it’s not already the case, make sure your decorator inherits from ApplicationDecorator

typeahead.js as a search function: multiple datasets

typeahead.js is a js library from Twitterland for building “robust typeaheads”.

What I found a bit confusing is how to get typeahead to act as a search function, so that once we’ve selected our chosen search term from the list of auto-completes, we are taken to a certain URL.

Let’s say we’ve set up typeahead (with the suggestion engine Bloodhound) for two datasets: poets and philosophers..

When we types ‘De’ into the input field, both ‘Descartes’ and ‘Derrida’ will auto-complete. Now, we want to go to ‘[root]/philosophers/descartes’ when we select ‘Descartes’ from this auto-completed list. To do this, we must add

after our existing typeahead code.