Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Rails examples: Single Table Inheritance (STI), strong parameters, single controller.
# Variant 1
def user_params(type)
params.require(type.to_sym).permit(attributes)
end
# Variant 2
def user_params(type)
case type
when "user"
params.require(:user).permit(user_attributes)
when "apprentice"
params.require(:apprentice).permit(apprentice_attributes)
end
end
# Variant 3
def update
...
if @user.update(send("#{@user.type.underscore.to_sym}_params"))
...
end
def user_params
params.require(:user).permit(attributes)
end
def apprentice_params
params.require(:apprentice).permit(attributes)
end
# Variant 4
https://github.com/T-Dnzt/sti-with-rails4/blob/master/app/controllers/animals_controller.rb
@bswinnerton
Copy link

bswinnerton commented Oct 27, 2014

Where are you getting type from?

@danielpuglisi
Copy link
Author

danielpuglisi commented Nov 11, 2014

type is a keyword reserved by Active Record. If you're using STI on your models it gets automatically set with the class name of the object.

For more check out the section Single Table Inheritance here: http://api.rubyonrails.org/classes/ActiveRecord/Base.html#label-Single+table+inheritance

@wizzor
Copy link

wizzor commented Feb 26, 2015

For multipart product names (like in my case CoreProduct, AddonProduct...) adding an underscore
call is needed to get the model name to the right format.

# Variant 1
def user_params(type)
params.require(type.underscore.to_sym).permit(attributes)
end 

@vinagrito
Copy link

vinagrito commented Oct 25, 2015

If the list gets too long I took an approach where I defined the permitted attributes in every model

# products_controller.rb
def product_class
 @product_class ||= params[:product][:type].camelcase.constantize
end
def create
  product_class.new product_params
end

def product_params
  @product_params ||= product_class.permitted_attributes_from_params(params[:product])
end
# product/product_a.rb 
class ProductA < Product
 def self.permitted_attributes_from_params(params)
  parameters = ActionController::Parameters.new(params)

  parameters.permit(:name, :price).tap do |whitelisted|
    whitelisted[:hash_attribute] = params[:hash_attribute] # this is in case the hash keys are dynamic
  end
 end
end

Again, this approach is for when the possible amount of permitted gets crazy big cause of STI.

@aalvrz
Copy link

aalvrz commented Nov 17, 2015

Thank you this worked wonderfully!

@dinkengraven
Copy link

dinkengraven commented Jan 13, 2017

Just stumbled upon this and found a handy solution for my problem, thank you :)

@flavio-b
Copy link

flavio-b commented Jun 8, 2018

Thanks! To get the name of the model used in the parameters, you can also use:
@model_instance.model_name.param_key

@jonatassalgado
Copy link

jonatassalgado commented Sep 29, 2018

And what about that?

def user_params
    type = @user.type.underscore.to_sym
    params.require(type).permit(:name, :age)
end

@adriancb
Copy link

adriancb commented Aug 9, 2021

Thanks! To get the name of the model used in the parameters, you can also use:
@model_instance.model_name.param_key

👍 - cleanest IMO. Thanks @flavio-b!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment