random_user_0891
random_user_0891

Reputation: 2051

only edit certain fields in Rails

I have a user model that has fields for first_name, last_name, email, and password. After a user signs up under their user profile page I would like to allow certain fields and not others to show on a form to update part of the user info.

For example I would like just the first_name to be shown as a field when I render a form for them to edit their name. How do I handle this? Should I make a new route and a controller action that lets me update just this one field? or do I just hide all the other fields and submit them in the background without the user seeing them?

<div class="signup_user">
  <div class="container-fluid">
    <div class="col-md-5 col-sm-12 centered">

      <%= form_for(@user) do |form| %>

      <%= render "shared/errors", object: @user %>
      <%= render "shared/flash" %>

        <div class="card card-default">
          <div class="card-body">

            <h1>Create account</h1>  

            <%= form.label :first_name %>
            <%= form.text_field :first_name, size: 40, autofocus: true, class: "required form-control" %>              

            <%= form.label :last_name %>
            <%= form.text_field :last_name, size: 40, class: "required form-control" %>

            <%= form.label :email %>
            <%= form.email_field :email, size: 40, class: "required form-control" %>

            <%= form.label :password %>
            <%= form.password_field :password, size: 40,  placeholder: "At least 10 characters", class: "required form-control" %>

            <%= form.label :password_confirmation, "Confirm Password" %>
            <%= form.password_field :password_confirmation, size: 40, class: "required form-control" %><br>

            <%= form.submit "Submit", class: 'btn btn-block btn-outline-primary' %>

           <% end %>

           <hr>
           <p>Already have an account? <%= link_to "Sign In", new_session_path %></p>

        </div>
      </div>

    </div>
  </div><!--./container-->
</div><!--./signup_user-->

after the initial signup I would like to just show 1 field like this for editing just the user name.

<div class="signup_user">
      <div class="container-fluid">
        <div class="col-md-5 col-sm-12 centered">

          <%= form_for(@user) do |form| %>

          <%= render "shared/errors", object: @user %>
          <%= render "shared/flash" %>

            <div class="card card-default">
              <div class="card-body">


                <%= form.label :first_name %>
                <%= form.text_field :first_name, size: 40, autofocus: true, class: "required form-control" %>              



        </div>
      </div><!--./container-->
    </div><!--./signup_user-->

Upvotes: 1

Views: 1568

Answers (3)

t56k
t56k

Reputation: 6981

I'd make two definitions of strong parameters on the controller:

def create_params
  params.require(:user).permit(:first_name, :last_name, :email, :password)
end

def update_params
  params.require(:user).permit(:email, :password)
end

Then in your create/update methods just allow each different definition. You don't need a new view or a new model if you just restrict the params based on the action.

def create
  @user.create(create_params)
  redirect_to users_path
end

def update
  @user.update_attributes(update_params)
  redirect_to users_path
end

Makes sense to me, and that way you don't have to create anything superfluous. Then fields will be rejected in a secure way the way they should be. Then you can adjust the view with action_name == 'edit' or similar.

Upvotes: 1

engineerDave
engineerDave

Reputation: 3935

The easiest way is use the action_name helper and create some conditional logic that will conditionally render the fields that you only want to show on the new action, e.g. action_name == "new"

Upvotes: 1

Clyde T
Clyde T

Reputation: 141

You can generate an additional view by creating a new model.

Example :

models/user_edit.rb

class User_Edit < User
end

models/user.rb

class User < ApplicationRecord
...
end

routes

  resources :users
  devise_for :users, path: 'users', controllers: {
        sessions:           "users/sessions",
        passwords:          "users/passwords",
        registrations:      "users/registrations",
        confirmations:      "users/confirmations",
      }
  devise_for :users_edit, path: 'users_edit', controllers: {
        registrations:      "users_edit/registrations",
      }

And so you will have :

views/users/registrations/edit.html

and

views/users_edit/registrations/edit.html

Upvotes: -1

Related Questions