1

I have a postgres column called content which is an array.

But when trying to use it in a form I'm getting:

can't cast ActionController::Parameters to text

Despite the fact that the output looks pretty good:

{"utf8"=>"✓",
 "_method"=>"patch",
 "authenticity_token"=>"NkK4BggxknfEn0A8shTs06xmesERaZdYtZdl9oEEUTk=",
 "notification_template"=>{"content"=>{"0"=>"Join us {{event_time}} {{{twitter_name}}} to win Big! hint: {{{question}}} #quiz {{location_tags}} {{url}} sdfsdfsdf"}},
 "commit"=>"Update Notification template",
 "id"=>"25"}

strong params

params.require(:notification_template).permit(:name, :content => {})

routes

resources :notification_templates do
  get 'edit/:id', to: 'notification_templates#edit_content', as: 'edit_content'
end

controller

  def edit_content
    @notification_template = NotificationTemplate.find(params[:notification_template_id])
  end

  def update
    if @notification_template.update(notification_template_params)
      redirect_to admin_notification_template_path(@notification_template), notice: 'Social message was successfully updated.'
    else
      render action: 'edit'
    end
  end

my form

the url looks like: /notification_templates/25/edit_content/7 # custom action, but uses normal update

<%= simple_form_for([:admin, @notification_template]) do |f| %>
  <%= f.error_notification %>

  <div class="form-inputs">
    <%= f.simple_fields_for :content do |fields| %>
        <%= fields.input params[:id], input_html: { value: @notification_template.content[params[:id].to_i] } %>
    <% end %>
  </div>

  <div class="form-actions">
    <%= f.button :submit %>
  </div>

<% end %>

the DB column

add_column :notification_templates, :content, :text, array: true, default: []

Lastly, I was unsure about the conventions for adding it. The above worked fine, but I also noticed other possibilities such as

add_column :notification_templates, :content, :text, array: true, default: []
add_column :notification_templates, :content, :sting, array: true, default: []
add_column :notification_templates, :content, :text, array: true, default: {}

I choose the first one on the basis that a string wouldn't allow for as many characters as I might eventually need and text is more convenient. Also the default of [] vs {} or '{}'

But in postgres is see content text[] DEFAULT '{}'::text[]

log

Started PATCH "/admin/notification_templates/25" for 127.0.0.1 at 2014-11-28 14:25:43 +0100
Processing by Admin::NotificationTemplatesController#update as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"NkK4BggxknfEn0A8shTs06xmesERaZdYtZdl9oEEUTk=", "notification_template"=>{"content"=>{"4"=>"{{{question}}} Study up and stop by {{{twitter_name}}} {{event_time}} for a #quiz {{location_tags}} {{url}} sdfsdfsdf"}}, "commit"=>"Update Notification template", "id"=>"25"}
  User Load (0.9ms)  SELECT  "users".* FROM "users"  WHERE "users"."id" = 1  ORDER BY "users"."id" ASC LIMIT 1
  NotificationTemplate Load (0.5ms)  SELECT  "notification_templates".* FROM "notification_templates"  WHERE "notification_templates"."id" = $1 LIMIT 1  [["id", 25]]
   (0.3ms)  BEGIN
   (0.3ms)  ROLLBACK
Completed 500 Internal Server Error in 54ms
Reporting exception: can't cast ActionController::Parameters to text

TypeError (can't cast ActionController::Parameters to text):
  app/controllers/admin/notification_templates_controller.rb:40:in `update'


  Rendered /Users/holden/.rvm/gems/[email protected]/gems/actionpack-4.1.7/lib/action_dispatch/middleware/templates/rescues/_source.erb (1.1ms)
  Rendered /Users/holden/.rvm/gems/[email protected]/gems/actionpack-4.1.7/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb (2.0ms)
  Rendered /Users/holden/.rvm/gems/[email protected]/gems/actionpack-4.1.7/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb (1.4ms)
  Rendered /Users/holden/.rvm/gems/[email protected]/gems/actionpack-4.1.7/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (27.5ms)

UPDATE

I also observed that update array type field doesn't work as expected in the console.

eg. if I attempt to update a member of the array, something = record.content[2] = 'blah' it appears to work. But when I save the record it doesn't update it.

6
  • params.require(:notification_template).permit(:name, :content => {})? Commented Nov 28, 2014 at 13:16
  • hey, that seems to work! Got that part working, Thanks. Commented Nov 28, 2014 at 13:19
  • please specify full trace log, with line of exception Commented Nov 28, 2014 at 13:21
  • show the code around the line: ` app/controllers/admin/notification_templates_controller.rb` Commented Nov 28, 2014 at 13:46
  • please try @notification_template.update(notification_template_params.to_h) Commented Nov 28, 2014 at 18:17

1 Answer 1

1

Yeah, Rails postgres Arrays are still a bit wonky. Hstore is a bit easier.

You may be better served going thru a virtual attribute and doing what you want expressly rather than relying on standard rails behavior through a form.

eg.

def content_member=(member)
    unless member.blank?
        self.content_will_change!
        self.content[member.keys.first.to_i] = member.values.first
    end
end

You also need to let rails know if you're going to update a member of an array, that's why it doesn't work in the console.

There's a full explanation here:

Rails 4 Postgresql array data-type: updating values

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.