Search code examples
ruby-on-railsparametersupdate-attributes

Update attributes separately in Rails


Trying to update 2 attributes to a User model, this is my current code in the Users controller:

def update
@user = User.find(params[:id])
if @user.update_attributes(songkickID: params[:user][:songkickID], jamID: params[:user][:jamID])

  redirect_to @user
else
  redirect_to @user
end
end

The Songkick ID and the Jam ID are entered into 2 different fields. However, with the current code, if I attempt to update the Jam ID on its own, it updates that attribute, but then redirects to the user page (as expected), where the Songkick ID is now nil. Upon entering the Songkick ID again, the Jam ID becomes nil. I suppose this is because they are both part of the same if statement in the controller?

I attempted to use an elsif for the jamID params, but it does not seem to recognise at all (i.e. won't update that attribute for the user). Also attempted || conditional operator.

EDIT: Here's the 2 different forms:

<%= form_for(@user) do |f| %>

  <%= f.text_field :jamID, :id=>"jamURL" %>


    <%= f.submit "Jam ID", :onclick => "changeImg()", id: "saveJam" %>

<% end %>

and

<%= form_for(@user) do |f| %>

  <%= f.text_field :songkickID %>

  <%= f.submit "Songkick ID", :type => :image, :src => image_path("songkicklogo.png"), id: "skLogo" %>
<% end %>


And I tried modifiying the code to update_column, but I get wrong number of arguments (1 for 2).

EDIT 2: Following layout from Hartl's Rails Tutorial, I attempted this to define strong parameters:

private

def user_params
  params.require(:user).permit(:songkickID, :jamID)
end

But I still get the Forbidden Attributes Error?

EDIT 3: The following code passes, but I worry it doesn't adhere to Rails 4 strong parameters:

Controller:

class UsersController < ApplicationController
def show
    @user = User.find(params[:id])
end

def edit
    @user = User.find(params[:id])
end



def user_params
  params.require(:user).permit(:songkickID, :jamID)
end

def update
@user = User.find(params[:id])
if @user.update_attributes(user_params)

  redirect_to @user
else
  redirect_to @user
end


end
end

If I move update to below the update method, I get an undefined variable/method error for user_params, and I cannot make it private.


Solution

  • So - why are you explicitly naming the attributes in your update_attributes?

    You should be able to use the following:

    @user.update_attributes(params[:user])
    

    Remember that if you've named your form fields correctly, params[:user] is a hash that will already have the keys you want (:songkickID etc)

    Now - you will get one of two things coming through to your action, which you then pass through to update_attributes as:

    {:songkickID => someID}
    {:jamID => someOtherID}
    

    which will correctly update your user and only change the one that is passed.

    The problem with your earlier code was that what you passed to update attribute was:

    {:songkickID => someID, :jamID => nil}
    {:songkickID => nil, :jamID => someOtherID}
    

    which was deliberately overwriting the other id with the nil you passed.

    EDIT from OP: Thanks for this, and here's my final controller code:

    class UsersController < ApplicationController
    def show
        @user = User.find(params[:id])
    end
    
    def edit
        @user = User.find(params[:id])
    end
    
    
    def update
    @user = User.find(params[:id])
    if @user.update_attributes(user_params)
    
      redirect_to @user
    else
      redirect_to @user
    end   
    end
    
    
    private
    
    
    def user_params
      params.require(:user).permit(:songkickID, :jamID)
    end
    end