Search code examples
ruby-on-railsenumsruby-on-rails-5

Rails Enum '0' is not a valid incomeType


I have a Ruby on Rails app that handles a users income, decides if it is an allowance or an income and applies the appropriate tax rates. I have included some enums to do basic functions as outlined below.

When I go to update from the default I hit the issue '1' is not a valid incomeType.

Below you can see the set up including model, controller and form.

model :

class Income < ApplicationRecord
  enum incomeType: {income: 0, allowance: 1 }
  enum taxed: {yes: 0, no: 1 }

  belongs_to :user
end

controller:

class IncomesController < ApplicationController
  before_action :set_income, only: [:show, :edit, :update, :destroy]

  # GET /incomes
  # GET /incomes.json
  def index
    @incomes = current_user.incomes.all
  end

  # GET /incomes/1
  # GET /incomes/1.json
  def show
  end

  # GET /incomes/new
  def new
    @income = current_user.incomes.build
  end

  # GET /incomes/1/edit
  def edit
  end

  # POST /incomes
  # POST /incomes.json
  def create
    @income = current_user.incomes.new(income_params)

    respond_to do |format|
      if @income.save
        format.html { redirect_to @income, notice: 'Income was successfully created.' }
        format.json { render :show, status: :created, location: @income }
      else
        format.html { render :new }
        format.json { render json: @income.errors, status: :unprocessable_entity }
      end
    end
  end

  # PATCH/PUT /incomes/1
  # PATCH/PUT /incomes/1.json
  def update
    respond_to do |format|
      if @income.update(income_params)
        format.html { redirect_to @income, notice: 'Income was successfully updated.' }
        format.json { render :show, status: :ok, location: @income }
      else
        format.html { render :edit }
        format.json { render json: @income.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /incomes/1
  # DELETE /incomes/1.json
  def destroy
    @income.destroy
    respond_to do |format|
      format.html { redirect_to incomes_url, notice: 'Income was successfully destroyed.' }
      format.json { head :no_content }
    end
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_income
      @income = Income.find(params[:id])
    end

    # Never trust parameters from the scary internet, only allow the white list through.
    def income_params
      params.require(:income).permit(:amount, :frequency, :user_id, :incomeType, :country, :taxed)
    end
end

Form :

<%= form_with(model: income, local: true) do |form| %>
  <% if income.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(income.errors.count, "error") %> prohibited this income from being saved:</h2>

      <ul>
      <% income.errors.full_messages.each do |message| %>
        <li><%= message %></li>
      <% end %>
      </ul>
    </div>
  <% end %>

  <div class="field">
    <%= form.label :amount %>
    <%= form.text_field :amount, id: :income_amount %>
  </div>

  <div class="field">
    <%= form.label :frequency %>
    <%= form.select :frequency, options_for_select([['Weekly', '52'], ['Fortnightly', '26'], ['Monthly', '12'], ['Bi-Monthly', '6'], ['Annually', '1']]), id: :income_frequency %>
  </div>
  <div class="field">
    <%= form.label :incomeType %>
    <%= form.select :incomeType, options_for_select([['Income', '0'], ['Allowance', '1']]), id: :incomeType %>
  </div>
  <div class="field">
    <%= form.label :taxed %>
    <%= form.select :taxed, options_for_select([['Yes', '0'], ['No', '1']]), id: :taxed %>ra
  </div>

  <div class="actions">
    <%= form.submit %>
  </div>
<% end %>

Hopefully you can point me in the right direct.

{"utf8"=>"✓",
 "_method"=>"patch",
 "authenticity_token"=>"HUTd5Bav9eAfWPTFFyqeD69aL4mIgZodIuL1+9eL0zIhN+SjDwAMcD7AzKEuhm6az4iALBSrDUXd/1vVfN77SQ==",
 "income"=>{"amount"=>"102000.0", "frequency"=>"1", "incomeType"=>"0", "taxed"=>"1"},
 "commit"=>"Update Income",
 "id"=>"4f9fc439-4578-487e-bc5d-02cf0cd9aaa3"}

Thanks in advance for your help


Solution

  • Yes it is because enum needs key not the value and you are sending value not the key so in your case enum is trying to find '0' as one key which is not present. So just change your form slightly

    <%= form.select :incomeType, options_for_select([['Income', 'income'], ['Allowance', 'allowance']]), id: :incomeType %>
    

    PS : change form for taxed as well. Hope this will help