How to remove a field from params[:something]

Ruby on-Rails

Ruby on-Rails Problem Overview


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.

Ruby on-Rails Solutions


Solution 1 - Ruby on-Rails

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 - Ruby on-Rails

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 - Ruby on-Rails

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 - Ruby on-Rails

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 - Ruby on-Rails

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 - Ruby on-Rails

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionprovidenceView Question on Stackoverflow
Solution 1 - Ruby on-RailsPaige RutenView Answer on Stackoverflow
Solution 2 - Ruby on-RailssamuraisamView Answer on Stackoverflow
Solution 3 - Ruby on-RailsDeepak MahakaleView Answer on Stackoverflow
Solution 4 - Ruby on-RailsTaimoor ChangaizView Answer on Stackoverflow
Solution 5 - Ruby on-RailsWashington BotelhoView Answer on Stackoverflow
Solution 6 - Ruby on-RailsMattView Answer on Stackoverflow