Search code examples
ruby-on-railsmass-assignment

How to change protected attribute in rails after form


I think this question is so simple, that I am at a loss for how to google it.

In RoR, if I have a protected attribute like :premium or :admin, and I only want to change it if a User does something specific (signs up for premium account or something as simple as provides a phone number), how would I do that? It should only change if certain conditions are met, but I don't want someone to be able to fake those conditions.

I understand that things like "premimum" or "admin", I want to avoid through mass assignment. So how do you change it if a user fills out a certain form?

Feel free to direct me to any useful links, I just cannot figure out how to word this, but I think it's a simple solution.


Solution

  • Read about Mass Assignment

    You can create roles

    attr_accessible :first_name, :last_name                            # default role
    attr_accessible :first_name, :last_name, :premium, :as => :special # 'special' role
    

    When calling .update_attributes(params) on this model, it will use the default role; if :premium is found in params, it will throw an error.

    In the POST method for your special form, you'd specify the :special role for the update_attributes like .update_attributes(params, :special), directing the update_attributes to use the :special role which allows the mass assignment of the :premium attribute.

    You can conditionally pass the role name based on some property in params, like the phone number having a value like you mentioned

    @the_model.update_attributes(params, params[:phone_no].present? ? :special : :default)
    

    If these conditions are more complex, you might consider adding them as a class method to the model

    def self.special_role?(params)
      # fancy conditions here, returning true/false
    end
    

    and then the update_attributes might look like

    @the_model.update_attributes(params, TheModel.special_role?(params) ? :special : :default)