Dmitri Mityugov Dmitri Mityugov - 2 months ago 6
AngularJS Question

How i can create Guests in another controller (for me it is Events)

I am stuck on creating Guests in my Events controller.

An error from rails:


undefined method `permit' for [{"name"=>"John"},
{"name"=>"Mike"}]:Array


How can I save Guests from Events controller, please help.

This is my EventsController:

class EventsController < ApplicationController

def create
@event = Event.create(event_params)
@guest = Guest.create(guest_params)

respond_with [@event, @guest]

end

private
def event_params
params.require(:event).permit(:name, :description, :date)
end

def guest_params
params.require(:guests).permit(:name)
end
end


So, this is JSON from the view:

date:"25.07.2016"
description:"Biggest Show"
guests:[{name: "John"}, {name: "Mike"}]
name:"Night Show"


My class Event.rb:

class Event < ActiveRecord::Base
has_many :guests
def as_json(options = {})
super(options.merge(include: :guests))
end
end


My class Guest.rb:

class Guest < ActiveRecord::Base
belongs_to :event
def as_json(options = {})
super
end
end


And Guest controller (if it more helpful):

class GuestsController < ApplicationController
respond_to :json
def index
respond_with Guest.all
end

def show
respond_with Guest.find(params[:id])
end

def create
respond_with Guest.create(guest_params)
end


private
def guest_params
params.require(:guest).permit(:name)
end
end

Answer

Since guests in your view is an array of hashes [{name: "John"}, {name: "Mike"}], you should do something like this in your controller:

# app/controllers/events_controller.rb
class EventsController < ApplicationController
  def create
    @event = Event.create(event_params)
    @guests = guests_params[:guests].map { |guest|
      Guest.create(name: guest[:name], event: @event)
    }

    respond_with [@event, @guests]
  end

  private
    def event_params
      params.require(:event).permit(:name, :description, :date)
    end

    def guests_params
      params.require(:event).permit(:guests)
    end
end

Alternatively you could change your view to return guests: { name_1: "John", name_2: "Mike", name_3: ... ] and then use a permit method, that expects the index of the guest:

# app/controllers/events_controller.rb
class EventsController < ApplicationController
  def create
    ...
    @guests = (1..max_index).map { |index|
      Guest.create(guest_params(index).merge({ event: @event }))
    }
    ...
  end

  private
    ...
    def guest_params index
      params.require(:guests).permit("name_#{index}")
    end
end

I have not checked the code against the interpreter, but I think you get the idea :)

EDIT: changed event_params.guests to params[:event][:guests], since guests is not a method or field of the event_params hash. Also removed guests from the permit method, because it could give an error when creating the event. But I am not sure if this is a good practice solution or if it even works exactly that way. It's still just to give the idea :)

EDIT2: added guests_params method

Comments