Skip to content

Instantly share code, notes, and snippets.

@danielpuglisi
Last active August 9, 2021 12:33
Show Gist options
  • Star 11 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save danielpuglisi/3c679531672a76cb9a91 to your computer and use it in GitHub Desktop.
Save danielpuglisi/3c679531672a76cb9a91 to your computer and use it in GitHub Desktop.
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

Where are you getting type from?

@danielpuglisi
Copy link
Author

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

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

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

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