Rails + jQuery-tokeninput + Draper decorator method

459 views Asked by At

I'm using Rails + jQuery-tokeninput to perform typeahead search and populate a "belongs_to" relationship. Here is the model:

class Performance < ActiveRecord::Base
  attr_accessible  :composition_tokens
  belongs_to :composition
    ...
  attr_reader :composition_tokens

  def composition_tokens=(ids) # comma-separated
      self.composition_tokens = ids.split(',')
  end
end

We're using Draper on this project to provide Decorators for our models.

Our CompositionDecorator has the following method:

class CompositionDecorator < ApplicationDecorator
  decorates :composition

  def full_title
    model.title + ' by ' + model.composer.canonical_name
  end

I've set up the tokeninput support to use the decorator like so:

jQuery ->
  $('#performance_composition_tokens').tokenInput '/admin/compositions.json'
     theme: 'facebook'
     prePopulate:$('#performance_composition_tokens').data('load')
     propertyToSearch: 'full_title'

The controller index method invokes the decorator like so:

class Admin::CompositionsController < Admin::BaseController
def index
    @compositions = Composition.includes(:composer).paginate(:page => params[:page]||1)
    respond_to do |format|
      format.html
      format.json { render :json => 
        CompositionDecorator.decorate(@compositions.where("title like ?",
            "%#{params[:q]}%")) }
    end
end

This all seems to work fine when I'm not using the decorator, but adding the decorator is causing problems. The "full_title" attribute isn't being included in the json generated by the controller, so "undefined" is shown in the selected values, and nothing is displayed in the search results list. The following error is also shown in the javascript console:

TypeError: 'undefined' is not an object (evaluating 'value.replace')

Any help would be greatly appreciated!

1

There are 1 answers

1
TomDavies On

The issue is to_json doesn't know about methods on the object so you have to explicitly tell it via the :methods parameter. I haven't used Draper before but looks like you can add your own custom to_json in your CompositionDecorator. So, something like this may work:

class CompositionDecorator

  def to_json
    composition.to_json(:methods => [:full_title])
  end

end

See also: