Rails 4.0 with Devise. Nested attributes Unpermited parameters

前端 未结 3 1389
日久生厌
日久生厌 2020-11-29 03:07

I am working on a web-app using Devise and Rails 4. I have a User model which I have extended with 2 extra form fields such that when a user signs up he can

相关标签:
3条回答
  • 2020-11-29 03:31

    You must create your own registration controller to do so, here is how:

    routes.rb

    devise_for :users, controllers: {registrations: 'registrations'}
    

    Controller

    You must replace :your_fields by the fields you want to allow (sorry if I leave that to you, but that makes my answer more general, therefore usable for anyone that would pass by)

    class RegistrationsController < Devise::RegistrationsController
    
      private
    
        def sign_up_params
          allow = [:email, :your_fields, :password, :password_confirmation]
          params.require(resource_name).permit(allow)
        end
    
    end
    

    Additional info (nested attributes + some testing)

    Also note that if you are using association and accepts_nested_attributes_for you will have params structured like this

    model: {field, field, field, associated_model: {field, field}}

    And off course you must use the same structure in your sign_up_params method. If you need to understand this, you can change the content of sign_up_params method like this:

        def sign_up_params
          params.require(resource_name).permit!
        end
    

    That will allow any param, then post your form (it should pass this time) and look into your rails console to see the structure of params, finally you can set-up sign_up_params method correctly

    Check this for more info http://www.railsexperiments.com/using-strong-parameters-with-nested-forms/

    In your case you should use:

    params.require(resource_name).permit( :email, :first_name, :last_name, institutions: [:name], :password, :password_confirmation )

    0 讨论(0)
  • 2020-11-29 03:49

    config/routes.rb

    Create your own registration controller like so ... (see Devise documentation for the details of overriding controllers here ...) ... which is more elegant way as opposed to doing it via the ApplicationController

    devise_for :users, controllers: {registrations: 'users/registrations'}
    

    app/controllers/users/registrations_controller.rb

    Override the new method to create a Profile associated with the User model as below ... run the configure_permitted_parameters method before to sanitize the parameters (note how to add nested parameters)

    class Users::RegistrationsController < Devise::RegistrationsController
    
      before_filter :configure_permitted_parameters
    
      # GET /users/sign_up
      def new
    
        # Override Devise default behaviour and create a profile as well
        build_resource({})
        resource.build_profile
        respond_with self.resource
      end
    
      protected
    
      def configure_permitted_parameters
        devise_parameter_sanitizer.for(:sign_up) { |u|
          u.permit(:email, :password, :password_confirmation, :profile_attributes => :fullname)
        }
      end
    end
    

    db/migrate/xxxxxxxxxxxxxx_create_profiles.rb

    This is the migration that generates the Profile model (note the reference to User) ... this example profile only keeps fullname as an extension of the User but feel free to add as you wish!

    class CreateProfiles < ActiveRecord::Migration
      def change
        create_table :profiles do |t|
           t.references :user
           t.string :fullname
           t.timestamps
        end
      end
    end
    

    app/models/user.rb

    class User < ActiveRecord::Base
    
      # Associations
      has_one :profile, dependent: :destroy, autosave: true
    
      # Allow saving of attributes on associated records through the parent,
      # :autosave option is automatically enabled on every association
      accepts_nested_attributes_for :profile
    
      # Devise
      # Include default devise modules. Others available are:
      # :confirmable, :lockable, :timeoutable and :omniauthable
      devise :database_authenticatable, :registerable,
             :recoverable, :rememberable, :trackable, :validatable
    end
    

    app/models/profile.rb

    class Profile < ActiveRecord::Base
    
      # Associations
      belongs_to :user
    
      # Validations
      validates :fullname, presence: true
    end
    

    app/views/devise/registrations/new.html

    <% resource.build_profile if resource.profile.nil? %>
    <%= form_for(resource, :as => resource_name,
                           :url => registration_path(resource_name)) do |f| %>
      <ul>
    
        <%= devise_error_messages! %>
    
        <li class="fullname">
          <%= f.fields_for :profile do |profile_fields| %>
            <%= profile_fields.label :fullname %>
            <%= profile_fields.text_field :fullname %>
          <% end %>
        </li>
        <li class="email">
          <%= f.label :email %>
          <%= f.email_field :email, :autofocus => true %>
        </li>
        <li class="password">
          <%= f.label :password %>
          <%= f.password_field :password %>
        </li>
        <li class="password">
          <%= f.label :password_confirmation %>
          <%= f.password_field :password_confirmation %>
        </li>
        <li>
          <%= f.submit %>
        </li>
        <li>
          <p><%= render "devise/shared/links" %></p>
        </li>
      </ul>
    <% end %>
    
    0 讨论(0)
  • 2020-11-29 03:54

    Using rails 5.1 and devise 4.4.1 following is the shortest and works pretty good:

    app/models/user.rb

    after_initialize do
      build_profile if new_record? && profile.blank?
    end
    

    app/controllers/application_controller.rb

    before_action :configure_permitted_parameters, if: :devise_controller?
    
    def configure_permitted_parameters
      devise_parameter_sanitizer.permit(:sign_up, keys: [{ profile_attributes: :name }])
    end
    

    The key here is that you can do following without making separate controller:

    • permit nested attributes
    • build relation for form builder
    0 讨论(0)
提交回复
热议问题