Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

Ruby

Error attempting to input data into PostgreSQL (9.3) array via form (Rails 4.1)

I'm getting the following error when completing my new risk form (I am building a risk management app):

PG::InvalidTextRepresentation: ERROR: array value must start with "{" or dimension information : INSERT INTO "risks" ("action", "area", "created_at", "date_of_action", "description", "impact", "likelihood", "owner", "title", "updated_at", "user_id") VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11) RETURNING "id"

Here is my form, all fields update correctly except for the impact and likelihood fields (both arrays). They are the focus of this question:

<%= simple_form_for(@risk) do |f| %>
  <%= render 'shared/error_messages', object: f.object %>
  <div class="form-group">
    <%= f.input :title, required: false, :error => false, input_html: { class: 'form-control' } %>
  </div>

  <div class="form-group">
    <%= f.input :description, required: false, :error => false,  as: :text, input_html: { class: 'form-control description' } %>
  </div>

  <div class="form-group">
    <%= f.input :area, :collection => ['Operations', 'IT', 'Finance'], required: false, :error => false, input_html: { class: 'form-control' } %>
  </div>

  <div class="form-group">
    <%= f.input :owner, :collection => User.all, required: false, :error => false, input_html: { class: 'form-control' } %>
  </div>

  <div class="form-group">
    <%= f.input :action, required: false, :error => false, input_html: { class: 'form-control' } %>
  </div>

  <div class="form-inline">
    <span class="date-of-action-input">
    <%= f.input :date_of_action, as: :date, :start_year => Date.today.year - 10, :end_year => 2030,
        :order => [ :day, :month, :year], :required => false, :error => false, input_html: { class: 'form-control' } %>
    </span>
    <span class="action-completed-input">
    <%= f.input :action_completed, as: :boolean, required: false, :error => false, input_html: { class: 'form-control' } %>
    </span>

    <span class="impact-input">
    <%= f.input :impact, required: false, :error => false, input_html: { class: 'form-control' } %>
    </span>
    <span class="likelihood-input">
    <%= f.input :likelihood, required: false, :error => false, input_html: { class: 'form-control' } %>
    </span>
    <span class="submit-risk">
    <%= f.button :submit, :error => false, :error => false, input_html: { class: 'form-control' } %>
    </span>
  </div>
<% end %>

Here the associated controller (risks_controller.rb):

class RisksController < ApplicationController
before_action :signed_in_user
before_action :correct_user, only: [:destroy, :update]


def create
    @risk = current_user.risks.build(risk_params)
    if @risk.save
      flash[:success] = "Risk created!"
      redirect_to root_url
    else
      render 'new'
    end
end

def new
  @risk = Risk.new
end

def destroy
  @risk.destroy
  redirect_to root_url
end

def edit
  @risk = Risk.find(params[:id])
end

def update
  @risk = Risk.find(params[:id])
    @risk.assign_attributes(risk_params)
    if @risk.changed? == false
      flash[:info] = "No changes were made"
      redirect_to root_url
    elsif @risk.update_attributes(risk_params)
      flash[:success] = "The risk has been updated."
      redirect_to root_url
    else
        render 'new'
    end
end

private

    def risk_params
        params.require(:risk).permit(:description, :title, :area, :owner, :action, :date_of_action, :action_completed, { :impact => [] }, { :likelihood => [] })
    end

  def correct_user
    if current_user.admin?
      @risk = Risk.find_by(id: params[:id])
      redirect_to root_url if @risk.nil?
    else
      @risk = current_user.risks.find_by(id: params[:id])
      redirect_to root_url if @risk.nil?
    end
  end

end

My db schema file:

# encoding: UTF-8
# This file is auto-generated from the current state of the database. Instead
# of editing this file, please use the migrations feature of Active Record to
# incrementally modify your database, and then regenerate this schema definition.
#
# Note that this schema.rb definition is the authoritative source for your
# database schema. If you need to create the application database on another
# system, you should be using db:schema:load, not running all the migrations
# from scratch. The latter is a flawed and unsustainable approach (the more migrations
# you'll amass, the slower it'll run and the greater likelihood for issues).
#
# It's strongly recommended that you check this file into your version control system.

ActiveRecord::Schema.define(version: 20140617165640) do

  # These are extensions that must be enabled in order to support this database
  enable_extension "plpgsql"

  create_table "risks", force: true do |t|
    t.integer  "user_id"
    t.string   "description"
    t.datetime "created_at"
    t.datetime "updated_at"
    t.string   "title"
    t.string   "area"
    t.string   "owner"
    t.string   "action"
    t.date     "date_of_action"
    t.boolean  "action_completed", default: false
    t.string   "impact",           default: [],    array: true
    t.string   "likelihood",       default: [],    array: true
  end

  add_index "risks", ["user_id", "created_at"], name: "index_risks_on_user_id_and_created_at", using: :btree

  create_table "users", force: true do |t|
    t.string   "name"
    t.string   "email"
    t.boolean  "admin",           default: false
    t.datetime "created_at"
    t.datetime "updated_at"
    t.string   "password_digest"
    t.string   "remember_token"
  end

  add_index "users", ["email"], name: "index_users_on_email", unique: true, using: :btree
  add_index "users", ["remember_token"], name: "index_users_on_remember_token", using: :btree

end

Anyone know why I am seeing this error when trying to update the impact and likelihood (array) fields? Even when trying to update the records in rails console I am getting the same error.

1 Answer

David Moore
David Moore
13,916 Points

I think your issue is due to the Postgres data types support in Rails. Try changing your default on impact and likelihood to {} and see what happens.

Additional reading: https://coderwall.com/p/sud9ja

http://stackoverflow.com/questions/19941428/postgres-insert-error-in-activerecord

https://github.com/dockyard/postgres_ext

Disclaimer: This is all wild speculation. It could just as easily be aliens or zombies.