title: ActiveModel::ForbiddenAttributesError using update_attributes having created params hash myself
body: <p>I’m trying to edit/update a model record using simple_form, but the form is not going to directly change a model field.  Instead, I offer a couple of check_box_tag fields that tell update what fields need changed.  As a result, update is not receiving a params[:device] hash that I can use to update the attributes.  I am attempting to create this hash, but am getting ForbiddenAttributesError when I issue the @device.update_attributes(params[:device]).  </p>
  
  <p>I believe my strong parameters list is correct.  If I allow one model field (name) to be processed in the edit view, I receive the expected params[:device] hash and everything works.  If I disable that field, because I don’t want it to be changed, then I need to create that hash myself and I receive the error.  When I look at the hash I created, it looks to me as equivalent to the one passed by the view.  I don’t understand why it is failing.  </p>
  
  <p>Environment is Ruby 2.0.0, Rails 4.1 on Windows 8.1 with RubyMine 6.3.  </p>
  
  <p>The form is:  &lt;... needs correct formatting once working ...></p>
  
  <pre><code>&lt;%= simple_form_for @device do |f| %&gt;
        &lt;legend&gt;&lt;%= controller.action_name.capitalize %&gt; Device:&lt;/legend&gt;
        &lt;%= f.input :name, disabled: true %&gt;
        &lt;%= check_box_tag(:is_admin, 0, @device.admin?) %&gt;
        &lt;%= label_tag(:is_admin, "Make admin?") %&gt;
        &lt;%= check_box_tag(:chg_pwd) %&gt;
        &lt;%= label_tag(:chg_pwd, "Change password?") %&gt;
        &lt;%= f.button :submit %&gt;
  &lt;% end %&gt;
  </code></pre>
  
  <p>The params[:device] that I receive when I sent f.input :name, disabled: false and allow the view to generate params[:device] is:</p>
  
  <pre><code>ActionController::Parameters (3 element(s))
  "{"name"=&gt;"D105", "password"=&gt;"D105Dvgr", "password_confirmation"=&gt;"D105Dvgr"}"
  </code></pre>
  
  <p>And, everything works.</p>
  
  <p>The params[:device] that I create is:</p>
  
  <pre><code>ActionController::Parameters (3 element(s))
  "{"name"=&gt;"D106", "password"=&gt;"D106VdAd", "password_confirmation"=&gt;"D106VdAd"}"
  </code></pre>
  
  <p>And, I receive Forbidden Attribute Error, even though I see no difference between the two.</p>
  
  <p>The update is:  &lt;... Code needs refactored, once it is working...></p>
  
  <pre><code>class DevicesController &lt; ApplicationController
    before_filter :authenticate_device!
  
  ... other methods removed here ...
  
    def edit
      @device = Device.find(params[:id])
      # my_page = render_to_string controller: 'devices', action: 'edit', layout: "application"
    end
  
    def update
      authorize! :update, @device, :message =&gt; 'Not authorized as an administrator.'
      @device = Device.find(params[:id])
      pwd_msg = ""
      if params[:chg_pwd]
        pwd_gen = @device.device + SecureRandom.urlsafe_base64(15).tr('lIO0=_\-', 'sxyzEUM').first(4)
        params[:device] = {name: @device.name} if params[:device].nil?
        params[:device][:password] = pwd_gen
        params[:device][:password_confirmation] = pwd_gen
        pwd_msg = ", new password is #{pwd_gen}"
      end
      if @device.update_attributes(params[:device])
        params[:is_admin] ? @device.add_role(:admin) : @device.remove_role(:admin)
        flash[:notice] = ["Device updated" + pwd_msg]
        redirect_to devices_path
      else
        @device.errors.messages.each do |key, value|
          flash[:alert] = ["Unable to update device"]
          @device.errors.messages.each do |key, value|
            flash[:alert] &lt;&lt; key.to_s.capitalize + " " + value[0]
          end
        end
        redirect_to devices_path
      end
    end
  
    private
  
    def device_params
      params.require(:device).permit(:device, :name, :email, :password, :password_confirmation, :encrypted_password, :salt, :role_ids, :is_admin, :chg_pwd)  # TODO minimize when update is working
    end
  
  end
  </code></pre>
  
  <p>The model is:</p>
  
  <pre><code>class Device &lt; ActiveRecord::Base
  
    rolify
    devise :database_authenticatable, :rememberable, :trackable, :validatable
  
    validates :device,
              presence: true,
              length: {minimum: 4 },
              uniqueness: {case_sensitive: false }
    validates :name,
              presence: true
  
    def remember_me
      true unless self.admin?
    end
  
    def admin
      self.add_role :admin
    end
  
    def not_admin
      self.remove_role :admin
    end
  
    def admin?
      self.has_role? :admin
    end
    def device?
      self.has_role? :device
    end
    def vip?
      self.has_role? :vip
    end
  
    def login=(login)
      @login = login
    end
    def login
      @login || self.device || self.email
    end
  
    def self.find_first_by_auth_conditions(warden_conditions)
      conditions = warden_conditions.dup
      if login = conditions.delete(:login)  # Note one equal sign.  Strange but true.
        where(conditions).where(["lower(device) = :value OR lower(email) = :value", { :value =&gt; login.downcase }]).first
      else
        where(conditions).first
      end
    end
  
  end
  </code></pre>
  
  <p>NEW INFORMATION:  I neglected to provide information I have in the ApplicationController.  This fix from Anton Trapp handles strong parameters for gems that aren't yet fully Rails 4 compatible:</p>
  
  <pre><code>  before_filter do
      resource = controller_name.singularize.to_sym
      method = "#{resource}_params"
      params[resource] &amp;&amp;= send(method) if respond_to?(method, true)
    end
  </code></pre>
  
  <p>I have found that using the proposed solution of:</p>
  
  <pre><code>@device.update_attributes(device_params)
  </code></pre>
  
  <p>does not work if a model field is updated.  The result is "param not found: device".  It does work if no model field is update.  So, the whole issue begs the question of what is truly wrong.</p>