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!
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:
See also: