One-to-Many Associations in Netzke
Let’s say we have a grid listing clerks, and we want to be able to assign a boss to a clerk (yes, my favorite setup). A traditional way to do this is by using a combobox listing available bosses as options. Netzke does it for you automatically when it detects a foreign key between the model’s attributes. However, sometimes we want to be in more control over how one-to-many associations are handled in Netzke grids and panels. This tutorial will show you how to configure the following:
- How each boss should be represented in the drop-down list. Will it be her first name or last name? Or maybe an arbitrary string that combines them both and eventually includes some extra info (such as the boss’ salary)?
- Scoping out bosses in the drop-down list. We may not want to list all the bosses in the drop-down list. How could we limit those to a specific department, for instance?
Specifying association method for combobox options
By default, when Netzke detects a foreign key among the columns to be displayed in a grid or a form, it turns that column/field into a combobox column/field, and, as its options, lists the records by the first valid association attribute from the following list: name, title, and label. If association records do not respond to any of these methods, Netzke will fall back to the association’s primary key.
If the defaults is not what you want, then specify a different association attribute, by using Netzke’s double-underscore convention (when configuring the columns):
netzke :some_clerks, :class_name => "GridPanel", :model => "Clerk", :columns => [:id, :first_name, :boss__last_name]
Note the last column we’re specifying: Netzke grid will recognize it as an association column and make it a combobox column, listing bosses by first_name in the drop-down list. You may choose for any other attribute from the Boss model, e.g.: boss__first_name, boss__salary, etc. There are 2 things to keep in mind here:
- Uniqueness of the attribute. If the attribute you choose is not meant to have unique values in the table, there’ll be no way to exactly choose a specific boss when there’s more than 1 boss with the same value. If there are 2 bosses with the same last name in the given example, there’ll be no way to distinguish between them in the list. So, make sure that the attribute validates as unique.
- Virtual attribute. You may also use virtual attributes here. E.g. you may define the name instance method in the Boss class, which will return a string made of the first and the last name, and then use boss__name among the columns in the clerks grid. However, in this case you need to provide Netzke with a method called find_by_<association_method> (returning one record) in the associated model – that’s what is used by Netzke to decide which record should get associated. So, if you define an association column as boss__full_name_with_salary, then Netzke will assume that the Boss class responds to find_by_full_name_with_salary.
Scoping out association options
Sometimes we don’t want to list all the bosses in the drop-down list. In this case you may specify one or more scopes for the association column:
netzke :some_clerks, :class_name => "GridPanel", :model => "Clerk", :columns => [ :id, :first_name, { :name => :boss__last_name, :editor => { :xtype => :combobox, :scopes => [:recently_hired, ["salary_greater_than", 95000]] } } ]
The :scopes option for the “combobox” column editor accepts an array of named scopes. In the example above we assume that the Boss model has a scope recently_hired (taking no arguments), and a scope salary_greater_than (which accepts an argument). If a scope accepts no arguments, it can be specified as a symbol. If it requires one or more arguments, us an array, where the first element is the scope name, and the rest – the arguments.
Note that “salary_greater_than” is a named scope magically provided to us by the wonderful Searchlogic.
To conclude this brief tutorial, I’d like you to note that you may as well apply this technique to configure attributes on the model level, as explained in one of the previous tutorials, and the grid’s demo page shows, between other grid-related things, a little example of doing just that.
While this blog is the first source of Netzke-related tutorials, you may also consider following me on Twitter for all kinds of news around Netzke.
