= Sequel::Model Mass Assignment
Most Model methods that take a hash of attribute keys and values, including Model.new, Model.create, Model#set and Model#update are subject to Sequel's mass assignment rules.
When you pass a hash to these methods, each key has an = appended to it (the setter method), and if the setter method exists and access to it is not restricted, Sequel will call the setter method with the hash value.
By default, there are two types of setter methods that are restricted.
The first is methods like typecast_on_assignment= and ==, which don't affect columns.
These methods cannot be enabled for mass assignment.
The second is primary key setters.
To enable use of primary key setters, you need to call +unrestrict_primary_key+ for that model:
Post.unrestrict_primary_key
Since mass assignment by default allows modification of all column values except for primary key columns, it can be a security risk in some cases.
Sequel has multiple ways of securing mass assignment.
The first way is using +set_allowed_columns+:
Post.set_allowed_columns :title, :body, :category
This explicitly sets which methods are allowed (title=, body=, and category=), all other methods will not be allowed.
This method is useful in simple applications where the same columns are allowed in all cases, but not appropriate when different columns are allowed in different scenarios (e.g. admin access vs. user access).
To handle cases where different columns are allowed in different cases, you can use +set_only+ or +update_only+:
# user case
post.set_only(params[:post], :title, :body)
# admin case
post.set_only(params[:post], :title, :body, :deleted)
In this case, only the title= and body= methods will be allowed in the mass assignment in the user case, and only title=, body=, and deleted= will be allowed for mass assignment in the admin case.
By default, if an invalid setter method call is attempted, Sequel raises a Sequel::Error exception. You can have Sequel silently ignore invalid calls by doing:
# Global default
Sequel::Model.strict_param_setting = false
# Class level
Post.strict_param_setting = false
# Instance level
post.strict_param_setting = false
These mass assignment methods have been around a long time, but starting in Sequel 3.12.0, the +set_fields+ and +update_fields+ methods were added, and these may be a better mass assignment choice for most users.
These methods take two arguments, the attributes hash as the first argument, and a single array of valid field names as the second argument:
post.set_fields(params[:post], [:title, :body])
+set_fields+ and +update_fields+ differ in implementation from +set_only+ and +update_only+.
With +set_only+ and +update_only+, the hash is iterated over and it checks each method call attempt to see if it is valid.
With +set_fields+ and +update_fields+, the array is iterated over, and it just looks up the value in the hash and calls the appropriate setter method.
+set_fields+ and +update_fields+ are designed for the case where you are expecting specific fields in the input, and want to ignore the other fields.
They work great for things like HTML forms where the form fields are static.
+set_only+ and +update_only+ are designed for cases where you are not sure what fields are going to be present in the input, but still want to make sure only certain setter methods can be called.
They work great for flexible APIs.
Starting in Sequel 3.34.0, +set_fields+ and +update_fields+ take an optional argument hash, and currently handles the :missing option. With :missing=>:skip, +set_fields+ and +update_fields+ will just skip missing entries in the hash, allowing them to be used in flexible APIs. With :missing=>:raise, +set_fields+ and +update_fields+ will raise an error if one of the entries in the hash is missing, instead of just assigning the value to nil or whatever the hash's default value is. That allows stricter checks, similar to the :strict_param_checking setting for the default mass assignment methods.
In all of the mass assignment cases, methods starting with +set+ will set the attributes without saving the object, while methods starting with +update+ will set the attributes and then save the changes to the object.