Question

Currently I have an edit form as follows:

<li>
    <%= form_for @ingredient do |f| %>
        <span class="span2"><%= f.text_field :name, placeholder: "#{@ingredient.name}" %></span>
        <span class="span1"><%= f.text_field :quantity, placeholder: "#{@ingredient.quantity}" %></span>
        <span class="span1"><%= f.text_field :unit, placeholder: "#{@ingredient.unit}" %></span>
        <span class="span3">Added: <%= @ingredient.updated_at.strftime("%d %b. at %H:%M") %></span>
        <span class="span2"><%= f.text_field :expiration, placeholder: "#{@ingredient.expiration}" %></span>
        <span class="span2"><%= f.submit "Submit", class: "btn btn-small" %></span>
    <% end %>
</li>

When I click submit my log file shows the follow:

Started PATCH "/pantries/112" for 127.0.0.1 at 2014-04-29 18:03:35 -0400
Processing by PantriesController#update as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"NUSmadjWCVVLHOZmncKD5D48L+7ZMa3DEbZ9Y+Y+Pnc=", "pantry"=>{"name"=>"test1", "quantity"=>"1", "unit"=>"cup", "expiration"=>"2015-05-05"}, "commit"=>"Submit", "id"=>"112"}
  [1m[35mUser Load (0.5ms)[0m  SELECT "users".* FROM "users" WHERE "users"."remember_token" = '27ecdc04fc67375fd3567c89fbe831e4d4919d09' LIMIT 1
  [1m[36mPantry Load (0.3ms)[0m  [1mSELECT "pantries".* FROM "pantries" WHERE "pantries"."id" = $1 LIMIT 1[0m  [["id", "112"]]
  [1m[35m (0.2ms)[0m  BEGIN
  [1m[36m (0.1ms)[0m  [1mCOMMIT[0m
Redirected to http://localhost:3000/users/1/pantry
Completed 302 Found in 6ms (ActiveRecord: 1.1ms)

It doesn't raise an error it just does not update at all, but says that the update completed successfully.

pantry.rb

class Pantry < ActiveRecord::Base
    before_save { self.name = name.downcase }
    belongs_to :user

    validates :name, presence: true
    validates :user_id, presence: true
end

pantries_controller

def update
        @ingredient = Pantry.find(params[:id])
        if @ingredient.update_attributes(params[ingredient_params])
            redirect_to pantry_user_path(current_user), :flash => {info: "Ingredient Updated"}
        else
            redirect_to pantry_user_path(current_user), :flash => {info: "Failed"}
        end
end
private
        def ingredient_params
            params.require(:pantry).permit(:name, :quantity, :unit, :expiration, :created_at, :updated_at)
        end

schema:

create_table "pantries", force: true do |t|
    t.string   "name"
    t.string   "quantity"
    t.string   "unit"
    t.integer  "user_id"
    t.datetime "created_at"
    t.datetime "updated_at"
    t.date     "expiration"
  end

  add_index "pantries", ["expiration"], name: "index_pantries_on_expiration", using: :btree
  add_index "pantries", ["quantity"], name: "index_pantries_on_quantity", using: :btree
  add_index "pantries", ["unit"], name: "index_pantries_on_unit", using: :btree

If I replace @ingredients.update_attributes with @ingredient.update_column(:expiration, params[:pantry][:expiration]) the update takes place on that column. Falling back to update_column is not ideal. I understand update_attributes and update_attributes! call callbacks while update_column does not. I don't see any issue with the callbacks and no error messages are given. Anyone have an idea on what the issue might be?

Was it helpful?

Solution

Change your update action as below:

def update
        @ingredient = Pantry.find(params[:id])
        if @ingredient.update_attributes(ingredient_params) ## Call ingredient_params
            redirect_to pantry_user_path(current_user), :flash => {info: "Ingredient Updated"}
        else
            redirect_to pantry_user_path(current_user), :flash => {info: "Failed"}
        end
end

With Rails 4 strong parameters concept, you need to whitelist the attributes that you would like to be saved in database.

Currently, you are using params[ingredient_params] instead of calling ingredient_params which is causing this issue

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top