'How to remove a field from params[:something]

My registration form, which is a form for the Users model, takes a string value for company. However, I have just made a change such that users belongs_to companies. Therefore, I need to pass an object of Company to the Users model.

I want to use the string value from the form to obtain the an object of Company:

@user.company = Company.find_by_name(params[:company])

I believe the above works, however the form is passing the :company (which is string) into the model when I call:

@user = User.new(params[:user])

Therefore, I want to know (and cannot find how) to remove the :company param before passing it to the User model.



Solution 1:[1]

Rails 4/5 - edited answer (see comments)

Since this question was written newer versions of Rails have added the extract! and except eg:

new_params = params.except[the one I wish to remove]

This is a safer way to 'grab' all the params you need into a copy WITHOUT destroying the original passed in params (which is NOT a good thing to do as it will make debugging and maintenance of your code very hard over time).

Or you could just pass directly without copying eg:

@person.update(params[:person].except(:admin))

The extract! (has the ! bang operator) will modify the original so use with more care!

Original Answer

You can remove a key/value pair from a Hash using Hash#delete:

params.delete :company

If it's contained in params[:user], then you'd use this:

params[:user].delete :company

Solution 2:[2]

You should probably be using hash.except

class MyController < ApplicationController
  def explore_session_params
    params[:explore_session].except(:account_id, :creator)
  end
end

It accomplishes 2 things: allows you to exclude more than 1 key at a time, and doesn't modify the original hash.

Solution 3:[3]

The correct way to achieve this is using strong_params

class UsersController < ApplicationController
  def create
    @user = User.new(user_params)
  end

  private

  def user_params
    params.require(:user).permit(:name, :age)
  end
end

This way you have more control over which params should be passed to model

Solution 4:[4]

respond_to do |format|
  if params[:company].present?
    format.html { redirect_to(:controller => :shopping, :action => :index) }
  else
    format.html
  end
end

this will remove params from the url

Solution 5:[5]

To be possible to delete you can do a memo:

def parameters
  @parameters ||= params.require(:root).permit(:foo, :bar)
end

Now you can do:

parameteres.delete(:bar)
parameters
=> <ActionController::Parameters {"foo" => "foo"} permitted: true>

Solution 6:[6]

Rails 5+: Use the handy extract! method with strong params!

The extract! method removes the desired variable from the Parameters object (docs) and returns a new ActionController::Parameters object. This allows you to handle params properly (i.e. with strong params) and deal with the extracted variable separately.

Example:

# Request { user: { company: 'a', name: 'b', age: 100 } }

# this line removes company from params
company = params.require(:user).extract!(:company)

# note: the value of the new variable `company` is { company: 'a' }
# since extract! returns an instance of ActionController::Parameters

# we permit :name and :age, and receive no errors or warnings since 
# company has been removed from params
params.require(:user).permit(:name, :age)

# if desired, we could use the extracted variable as the question indicates
@company = Company.find_by_name(company.require(:company))

Full example in controller

Of course, we could wrap this up in a handy method in our controller:

class UsersController < ApplicationController
  before_action :set_user, only: [:create]

  def create
    # ...
    @user.save
  end

  def set_user
    company = params.require(:user).extract!(:company)
    @user = User.new(params.require(:user).permit(:name, :age))
    @user.company = Company.find_by_name(company.require(:company))
  end
end

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 rmcsharry
Solution 2 samuraisam
Solution 3 Deepak Mahakale
Solution 4 Jan Klimo
Solution 5 Washington Botelho
Solution 6 Matt