'Can't return array elements from array of string using instance variables

I have this model with an array of strings as one of the columns

  create_table "shows", force: :cascade do |t|
    t.time "st"
    t.time "ed"
    t.integer "money"
    t.string "av_seats", default: "--- []\n"
    t.string "oc_seats", default: "--- []\n"
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false
    t.integer "theatre_id"
    t.integer "screen_id"
    t.integer "movie_id"
    t.index ["movie_id"], name: "index_shows_on_movie_id"
    t.index ["screen_id"], name: "index_shows_on_screen_id"
    t.index ["theatre_id"], name: "index_shows_on_theatre_id"
  end

I'm trying to reference av_seats and oc_seats in another model's controller via this logic

def create
    @booking = Booking.new(booking_params)
    @av_seats = Show.find(params[:show_id]).pluck(:av_seats)
    @oc_seats = Show.find(params[:show_id]).pluck(:oc_seats)

    if @booking.save
      if @av_seats.include? @booking.seat
        @oc_seats << @booking.seat
        @av_seats.delete @booking.seat
      end
      render json: @booking, status: :created, location: @booking

Essentially, it's supposed to move an element from one array to another and delete the same element from the previous array all based on input.

"status": 404,
    "error": "Not Found",
    "exception": "#<ActiveRecord::RecordNotFound: Couldn't find Show without an ID>",

I've tried using the pluck method beforehand and then attempt to use find for the element but I may not be doing it right either.

    @av = Show.pluck(:show_id, :av_seats)
    @oc = Show.pluck(:show_id, :oc_seats)

    @av_seats = Show.find(@av)
    @oc_seats = Show.find(@oc)
# routes.rb

Rails.application.routes.draw do
  resources :movies
  resources :bookings
  resources :shows
  resources :screens
  resources :theatres
  resources :users
end

This is what the form typically looks like. It's an API so no views, just pure JSON.

{
    "booking": {
        "user_id": 1,
        "show_id": 2,
        "screen_id": 2,
        "seat": "A5"
    }
}


Solution 1:[1]

You create a Booking resource. The information (:show_id) is nested under the :bookings key in your params

I assume you got the following method on the BookingsController

def booking_params
  params.require(:booking).permit(:show_id, :user_id, :seat, :screen_id)
end

?

If your Booking has the association setup properly

class Booking < ApplicationRecord
  belongs_to :show
end

Then you can access the show like this:

booking = Booking.new(booking_params)
show = booking.show

If no association is setup, then you can use

show = Show.find(params[:booking][:show_id])
# or
show = Show.find(booking_params[:show_id]) # not _params_

Since the show object is loaded anyhow, you can just access av_seats and oc_seats directly

show.av_seats
show.oc_seats

pluck is an optimization where only the columns you pluck are fetched from the DB.

You probably want to change the xx_seats columns to be of type string[] (with array: true in your migration).

Once you change the contents of the seats array(s) you need to save the show record.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Pascal