How To Save Nested Attribute Checkboxes With Formtastic and Cocoon and Avoid the TypeError

Avoiding the TypeError: can’t cast Array to string

Recently, I was inserting nested attribute checkboxes using
Formtastic and Cocoon and was cruising along with all my other nested forms partials until I got a dreaded TypeError: can’t cast Array to string.

Below is the pertinent code pattern I used that worked for other parts of my nested form:

Code for the form view using Formtastic

1
2
= semantic_form_for @person, url: {action: "update_something_action" } do |f|
3
  %h4 Papers
4
    #papers
5
      = f.semantic_fields_for :papers do |paper|
6
        = render 'paper_fields', :f => paper
7
      .links
8
        = link_to_add_association 'Add paper', f, :papers
9

Code for the form partial _paper_fields.html.haml using Formtastic and Cocoon

1
2
.nested-fields
3
  = f.inputs :name => "Paper" do
4
    = f.input :paper_title
5
    = f.input :paper_year
6
    = f.input :good_paper, as: :check_boxes, collection: ["Yes", "No"]
7
    = link_to_remove_association "Remove paper", f
8

The code for the form view and form partial above worked except for the
check boxes which kept giving the TypeError: can’t cast Array to string.
Below is how I fixed this.

Step 1: Setup the parent model, Person, correctly

1
2
class Person < ActiveRecord::Base
3
 
4
  has_many :papers, dependent: :destroy
5
 
6
  accepts_nested_attributes_for :papers, allow_destroy: true
7
 
8
end
9

Step 2: Serialize good_paper in Paper.rb

You serialize the attribute you want checkboxes for as follows:

1
2
class Paper < ActiveRecord::Base
3
 
4
  belongs_to :person
5
 
6
  serialize :citation_status, Array
7
 
8
end
9

Step 3: Setup FactoryGirl correctly

In spec/factories/paper.rb, we have:

01
02
FactoryGirl.define do
03
  factory :paper do
04
    paper_title "MyText"
05
    paper_year "MyString"
06
    citation_status ["",""]
07
    association :person
08
  end
09
end
10

And that’s it, your Rails 4 application nested attribute checkboxes should now be working correctly with Cocoon and Formtastic.

How To Setup jQuery Autcomplete With Elasticsearch In Your Rails Application

What is jQuery autocomplete?

The jQuery autocomplete plugin enables your users to receive suggestions while they type keywords in an input field.

How do you use it with elasticsearch?

If you haven’t setup elasticsearch with your Rails application, you can read about how to do it in these articles:

Step 1 – Install rails gem

Add the jquery-ui-rails to your Gemfile and run bundle install.

1
2
gem 'jquery-ui-rails'
3

At the command line type:

1
2
bundle install
3

Step 2 – Require the correct assets in your asset pipeline

Here I will show how I have my assets setup, but you can see the jquery-ui-rails README on github if you want to pick and choose what parts of jquery-ui you want to include.

In your application.css file, include the following assets:

1
2
 *= require jquery-ui/core
3
 *= require jquery-ui/theme
4
 
5
 *= require_self
6

In your application.js file, include the following:

1
2
//= require jquery
3
//= require jquery_ujs
4
 
5
//= require jquery-ui
6
//= require_tree .
7

Step 3 – Write a controller method

01
02
class AjaxController < ApplicationController
03
 
04
  respond_to :json
05
 
06
  def autocomplete
07
    # ...
08
    @response = HTTParty.get("http://scctsi-ctds-staging.herokuapp.com/1/clinical_trials/layman_terms")
09
    @tag_counts = @response["response"]
10
    if params[:term]
11
      @tag_counts = @tag_counts.select { |term, value| term=~/#{params[:term]}.*/}
12
    end
13
    respond_with(@tag_counts)
14
  end
15
end
16

In the controller above, I am calling out to an API (basically another Rails application) that returns a JSON response with a disease name and a count like the following:

01
02
 
03
{"response":{"Kidney (Renal Cell) Cancer":6,"Advanced or
04
 
05
Metastatic":4,"Localized or Resected":4,"Heart Attack":17,"Rheumatic
06
 
07
Diseases":16,"Alzheimer's Disease":8,"Dementia":6,"HIV":2,"AIDS":2,"Hepatitis c":2,"HIV and
08
 
09
aging":2,"HIV/hepatitis c co-infection":2,"Bladder (Urothelial,
10
 
11
Transitional Cell) Cancer":4,"Aneurysm":2,"Stroke":2,"Cerebrovascular
12
 
13
Disease":1,"Cerebrovascular Stroke":1,"Cerebrovascular Accident":1,"Skin
14
 
15
(Cutaneous) Cancer":3,"Squamous Cell":3,"Head and Neck
16
 
17
Cancers":1,"Hypopharynx":1,"Larynx":1,"Lip Nasopharynx":1,"Oral
18
 
19
Cavity":1,"Oropharynx":1,"Trachea":1,"Aortic Disease":3,"Aortic
20
 
21
Stenosis":5,"Heart Failure":7,"Heart Valve
22
 
23
Diseases":5,"Uterine/Endometrial Cancer":5,"Metastatic or
24
 
25
Unresectable":2,"Resectable (Pre-Cystectomy)":2,"Superficial
26
 
27
(Non-Invasive)":2,"Bone Cancer":5,"Ewing's
28
 
29
Sarcoma":5,"Osteosarcoma":5,"Non-Small Cell Cancer (NSCLC)":6,"Small
30
 
31
Cell Lung Cancer (SCLC)":6,"Pancreatic
32
 
33
Cancer":2,"Narcolepsy":1,"Leukemia":5,"Acute Lymphoid leukemia
34
 
35
(ALL)":5,"Acute Myeloid Leukemia (AML)":5,"Acute Promyelocytic Leukemia
36
 
37
(APL)":5,"Chronic Lymphocytic Leukemia (CLL)":5,"Chronic Myelogenous
38
 
39
Leukemia (CML)":5,"Other Leukemia":5,"Lymphoma: Hodgkin":4,"Lymphomas:
40
 
41
Non-Hodgkin":4,"Cutaneous Lymphoma":4,"Diffuse Large B-Cell
42
 
43
Lymphoma":4,"Low Grade Lymphoma":4,"Mantle Cell Lymphoma":4,"Other
44
 
45
Histologies":4,"T-Cell Lymphoma":4,"Waldenstrom
46
 
47
Macroglobulinemia":4,"Gynecologic Cancers":2,"Eye Cancer":1,"High Blood
48
 
49
Pressure / Hypertension":2,"Pulmonary Hypertension":1,"Basal Cell
50
 
51
Carcinoma":1,"Melanoma":1,"Other Skin Cancers":1,"Multiple
52
 
53
Sclerosis":2,"Glaucoma":1,"Arrhythmias":1,"Atherosclerosis":2,"Thrombosis":1,"Arthritis":2,"Liver":3,"Ovarian/Peritoneal/Fallopian
54
 
55
Cancer":1,"Neuroendocrine Tumors":5,"Diabetes":2,"Huntington's
56
 
57
Disease":16,"Parkinson's Disease":16,"Tourette's Disorder":13,"Brain
58
 
59
(Central Nervous System) Cancers":15,"Gliomas":16,"Metastatic
60
 
61
CNS":13,"Pediatric Brain Tumors":13,"Central Nervous System
62
 
63
Cancer":15,"Liver Tumors":7,"Chronic Liver Disease / Cirrhosis":7,"Any
64
 
65
Cancer Condition or Solid Tumor":57,"Breast Cancer":19,"Lung
66
 
67
Cancer":18,"Stomach Cancer":19,"Gastric (Stomach)
68
 
69
Cancer":7,"Gastrointestinal Stromal Tumor (GIST)":7,"Colon/Rectal
70
 
71
Cancer":6,"Anal Cancer":6,"Colon Cancer":6,"Rectal Cancer":6,"Prostate
72
 
73
Cancer":4,"Localized Disease":4,"Metastatic Disease":4}}
74
 
75

The params[:term] tells the controller what term(s) (or disease name(s)) to display to the end user in the autocomplete search box. It works in real-time.

Step 4 – Include a route to the controller in routes.rb

1
2
 
3
get 'autocomplete', to: 'ajax#autocomplete'
4
 
5

Step 5 – Write a coffeescript method to call the search method

In my case, I wanted to display the count along with the disease name asthe user typed their search term. I also wanted the user to be able to mouse click on the terms as they were dropping down via autocomplete and have the Rails application respond to that event by bringing the user to a page with more information about that term. Hence, I tell the autocomplete widget to submit the form with the selected term value via the select api method of jQuery autcomplete.

01
02
jQuery ->
03
  $('#search_terms').autocomplete
04
    source: (request, response) ->
05
      $.ajax
06
        url: '/autocomplete.json'
07
        dataType: "json"
08
        data: { term: request.term }
09
        success: (data) ->
10
          objects = $.map(data, (v, i) ->
11
            label: i+" ("+v.toString()+")"
12
            value: i
13
          )
14
          response objects
15
    select: (event, ui) ->
16
      $("#search_terms").val(ui.item.value)
17
      $("#search-form").submit()
18

Step 6 – Setup the search form in your Rails view

You also have to setup the search form with the appropriate CSS id names that you reference in your coffeescript code. Below is what I used.

1
2
= form_tag(search_path, :method => "get", id: "search-form", class: "navbar-form navbar-left") do
3
  = text_field_tag :search_terms, params[:search_terms], placeholder: "Search by Keyword", class: "form-control"
4
  = submit_tag "Search", :name => nil, class: "btn btn-default"
5

How to Setup Elasticsearch in your Rails App in Production

Step 1 - Install elasticsearch in your Rails Application in Production If you haven’t setup elasticsearch in your Rails application in development, this article tells you how to do so in Linux Step 2 - Create the search indices on your Heroku

Continue Reading …

How To Setup Elasticsearch In Your Rails Application In Development

Step 1 - Install elasticsearch If you haven’t installed elasticsearch on your local development machine, this article tells you how to do so in Linux Step 2 - Add the right ruby gems for the Ruby elasticsearch client in your Gemfile and bundle

Continue Reading …

How To Install Elasticsearch On Linux for Rails Development

What is elasticsearch? Elasticsearch is an open-source real-time search and analytics engine that runs on top of Lucene, a Java-based indexing and search library. How to install it on Linux Mint 16 and Ubuntu 14.04 Step 1 - Download

Continue Reading …

How To Squash Your Last 2 Git Commits

Why Squash Commits? If you’ve been working with Git for a while you might start to wonder why you can’t combine that last trivial “hello world” type commit with your previously more meaningful commit. Fortunately, you don’t have to wonder as Git

Continue Reading …

Installing Phantomjs on Linux Mint 16

Just wrote a protip on Coderwall about how to install Phantomjs on Linux Mint 16...

Continue Reading …

Setting Up Spring + RSpec For Testing Your Rails 4 Application

What is spring? Spring is an application preloader. That means it boots up your rails application and keeps it running in the background. Why is this good? It means you don’t have to boot it up every time you need to run a test

Continue Reading …

Avoiding the ‘oCol is undefined’ Error with jQuery-datatables-rails

The ‘oCol is undefined’ Error Recently I installed jQuery-datatables-rails in a Rails 4 project. With the Firebug plugin in Firefox, I received an error ‘oCol is undefined’. With Google Chrome via the console, I received an error ‘Cannot

Continue Reading …

Integrating Fat Free CRM Into Your Rails Application

What is Fat FREE CRM? Fat Free CRM is an open-source customer relationship management piece of software that lets you perform the basic marketing activities integral to the sales cycle. Tracking leads, managing campaigns, and contact lists are

Continue Reading …