Emmanuel Mtali Emmanuel Mtali - 2 months ago 6
Ruby Question

Proper handling of Category model in Rails

My application has Category and App model that i want to associate

Category => has_many :apps ,
App => belong_to :category

I what user to be able to select category when creating and updating app model and it was successful done tutorial i use.

The problem is when user create the app model forgetting to pass any category the application crashed (I dont know how to handle this )


The application crash with error

Again, when user create the app model passing the category then decided to edit it later . . the category field wont point to the last selected category( showing the prompt "select category"), the same error happen when user opt not update the category field!

My form partial

<%= simple_form_for @app do |f| %>
<%= select_tag(:category_id, options_for_select(@categories), {:prompt => "--select category--"}) %>
<%= f.input :title, label: "Application title" %>
<%= f.input :creator %>
<%= f.input :description %>
<%= f.button :submit %>
<% end %>


My apps_controller

def new
@app = current_user.apps.build
@categories = Category.all.map { |c| [c.name, c.id] }
end

def create
@app = current_user.apps.build(app_params)
@app.category_id = params[:category_id]

if @app.save
redirect_to root_path
else
render :new
end
end

def edit
@categories = Category.all.map { |c| [c.name, c.id] }

end

def update
@app.category_id = params[:category_id]
if @app.update(app_params)
redirect_to @app
else
render :edit
end
end


What am I doing wrong? How can I accurately handle this situation?

Answer
  1. Use collection_select
  2. You're using select_tag which is out of the scope of the form object

Fix:

<%= simple_form_for @app do |f| %>
  <%= f.collection_select :category_id, @categories, :id, :name %>
  <%= f.input :title, label: "Application title" %>
  <%= f.input :creator %>
  <%= f.input :description %>
  <%= f.button :submit %>
<% end %>

You will need to remove the map in the controller:

#app/controllers/apps_controller.rb
class AppsController < ApplicationController
  def new
    @app = current_user.apps.new
    @categories = Category.all
  end
end

This assumes you have a category_id column in your apps table