access
There are cases where you don't want Mongoid to allow attributes to be set through mass assignment, like passwords. This is a common event when submitting forms, and fields can be protected by using Mongoid's attr_protected or attr_accessible thanks to the wonders of Active Model.
protected
When defining a list of fields as protected, all other fields in the document will NOT be able to be set through mass assignment.
class User include Mongoid::Document field :first_name, type: String field :password, type: String attr_protected :password end # Set attributes on a person properly. Person.new(first_name: "Corbin") person.attributes = { first_name: "Corbin" } person.write_attributes(first_name: "Corbin") # Attempt to set attributes a person, raising an error. Person.new(first_name: "Corbin", password: "password") person.attributes = { first_name: "Corbin", password: "password" } person.write_attributes(first_name: "Corbin", password: "password")
accessible
Providing a list of fields as accessible is simply the inverse of protecting them. Anything not defined as accessible will cause the error.
class User include Mongoid::Document field :first_name, type: String field :password, type: String attr_accessible :first_name end # Set attributes on a user properly. User.new(first_name: "Corbin") user.attributes = { first_name: "Corbin" } user.write_attributes(first_name: "Corbin") # Attempt to set attributes on a user, will silently ignore protected ones. User.new(first_name: "Corbin", password: "password") user.attributes = { first_name: "Corbin", password: "password" } user.write_attributes(first_name: "Corbin", password: "password")
You can scope the mass assignment by role by providing the role as an option to the constructor or create methods.
class User include Mongoid::Document field :first_name, type: String field :password, type: String attr_accessible :first_name, as: [ :default, :admin ] end # Set attributes on a person for the admin role Person.new({ first_name: "Corbin" }, as: :admin) Person.create({ first_name: "Corbin" }, as: :default) Person.create!({ first_name: "Corbin" }, as: :admin)
overriding
In the case you want to override the security in a single call, you can pass a block to the document constructor to set fields manually.
Person.new(first_name: "Corbin") do |person| person.password = "password" end