I’m working on a Rails app to allow users to post information on places they want to go to and then add the places to their personal bucket lists. While the strong parameters for the create and update actions can commonly be shared, I wanted to set different permitted parameters for the create and update actions of my controller. I wanted a user to be able to create a place and add a name, address and description when they create a post, but only be able to update the description field if they decide to edit it later, so as not to interfere with the other users’ bucket lists. I also wanted to give the admin the ability to edit all three fields at any time, just in case a place really did change its name or address. My mentor helped me to come up with a solution that customized the strong parameters for different users and actions.

places_controller.rb

  def update
    @place = Place.find(params[:id])
    return render text: 'Not Allowed', status: :forbidden unless @place.user == current_user || current_user.admin?
    @place.update_attributes(place_params)
    if @place.valid?
      redirect_to root_path
    else
      render :edit, status: :unprocessable_entity
    end
  end
  
  private
  
  def place_params
    if current_user.admin? || @place.nil?
      params.require(:place).permit(:name, :address, :description)
    else
      params.require(:place).permit(:description)
    end
  end

Now the user can update the description field but not the name field, as demonstrated by the tests.

places_controller_spec.rb

describe 'PUT update' do
    before do
      @user = Fabricate(:user)
      allow(controller).to receive(:authenticate_user!).and_return(true)
      allow(controller).to receive(:current_user).and_return(@user)
    end
    
    context 'with the current user' do
      it 'updates the attribute' do
        place = Fabricate(:place, description: 'old description', user_id: @user.id)
        put :update, {id: place.id, place: { description: 'new description' }}
        expect(place.reload.description).to eq('new description')
      end
    end

   context 'with invalid input' do    
      it 'does not update a locked attribute' do
        place = Fabricate(:place, name: 'old name', user_id: @user.id)
        put :update, {id: place.id, place: { name: 'new name' }}
        expect(place.reload.name).to eq('old name')
      end
    end
  end

The github link is https://github.com/ashlynnpai/dream/blob/master/app/controllers/places_controller.rb.

Tags: , , ,

In categories: Rails, web development

COMMENTS

LEAVE A REPLY

Only the name field is required. Your email will not be published.