0

I'm working on app in Ruby on Rails (5.1.4)- I've recently created scaffold for user with 2 parameters- Username and Name. After some time I changed Username for Index. Now there's a problem with creating new User. Obviously- in every model, controller, etc. I know there's Username- I changed it for Index. The question is- can I do this? Or should I create new scaffold with right parameters? If so- how do I do this? I don't want to lose my work with controllers and views.

So here's how I created scaffold:

rails generate scaffold Student index:string name:string

That's an error I'm getting every time when I try to create new user:

Error

And the changes I made:

app/models/user.rb

class User < ApplicationRecord
    has_and_belongs_to_many :movies, :join_table => :users_movies
    has_many :topics
    has_many :posts

    has_secure_password

    validates :name, presence: true, uniqueness: true, length: { in: 3..50 }
    validates :index, presence: true, length: { is: 6 }, uniqueness: true
    validates :password, presence: true, length: { minimum: 6 }

    def follows?(movie)
        self.movies.include?(movie)
    end
end

app/views/users/_form.html.erb

<%= form_with(model: user, local: true) do |form| %>
  <% if user.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(user.errors.count, "error") %> prohibited this user from being saved:</h2>

      <ul>
      <% user.errors.full_messages.each do |message| %>
        <li><%= message %></li>
      <% end %>
      </ul>
    </div>
  <% end %>

  <div class="field">
    <%= form.label :index %>
    <%= form.text_field :index, id: :user_index %>
  </div>

  <div class="field">
    <%= form.label :name %>
    <%= form.text_field :name, id: :user_name %>
  </div>

  <div class="field">
    <%= form.label :password %>
    <%= form.password_field :password, id: :users_password %>
  </div>

  <div class="field">
    <%= form.label :password_confirmation %>
    <%= form.password_field :password_confirmation, id: :user_password_confirmation %>
  </div>

  <div class="actions">
    <%= form.submit %>
  </div>
<% end %>

app/views/users/_user.json.builder

json.extract! user, :id, :index, :name, :created_at, :updated_at
json.url user_url(user, format: :json)

app/views/users/index.html.erb

<p id="notice"><%= notice %></p>

<h1>Users</h1>

<table>
  <thead>
    <tr>
      <th>Index</th>
      <th>Name</th>
      <th colspan="3"></th>
    </tr>
  </thead>

  <tbody>
    <% @users.each do |user| %>
      <tr>
        <td><%= user.index %></td>
        <td><%= user.name %></td>
        <td><%= link_to 'Show', user %></td>
        <td><%= link_to 'Edit', edit_user_path(user) %></td>
        <td><%= link_to 'Destroy', user, method: :delete, data: { confirm: 'Are you sure?' } %></td>
      </tr>
    <% end %>
  </tbody>
</table>

<br>

<%= link_to 'New User', new_user_path %>

app/views/users/show.html.erb

<p id="notice"><%= notice %></p>

<p>
  <strong>Index:</strong>
  <%= @user.index %>
</p>

<p>
  <strong>Name:</strong>
  <%= @user.name %>
</p>

<%= link_to 'Edit', edit_user_path(@user) %> |
<%= link_to 'Back', users_path %>

app/controllers/user_controller.rb

class UsersController < ApplicationController
  before_action :set_user, only: [:show, :edit, :update, :destroy]

  # GET /users
  # GET /users.json
  def index
    @users = User.all
  end

  # GET /users/1
  # GET /users/1.json
  def show
  end

  # GET /users/new
  def new
    @user = User.new
  end

  # GET /users/1/edit
  def edit
  end

  # POST /users
  # POST /users.json
  def create
    @user = User.new(user_params)

    respond_to do |format|
      if @user.save
        format.html { redirect_to @user, notice: 'User was successfully created.' }
        format.json { render :show, status: :created, location: @user }
      else
        format.html { render :new }
        format.json { render json: @user.errors, status: :unprocessable_entity }
      end
    end
  end

  # PATCH/PUT /users/1
  # PATCH/PUT /users/1.json
  def update
    respond_to do |format|
      if @user.update(user_params)
        format.html { redirect_to @user, notice: 'User was successfully updated.' }
        format.json { render :show, status: :ok, location: @user }
      else
        format.html { render :edit }
        format.json { render json: @user.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /users/1
  # DELETE /users/1.json
  def destroy
    @user.destroy
    respond_to do |format|
      format.html { redirect_to users_url, notice: 'User was successfully destroyed.' }
      format.json { head :no_content }
    end
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_user
      @user = User.find(params[:id])
    end

    # Never trust parameters from the scary internet, only allow the white list through.
    def user_params
      params.require(:user).permit(:index, :name, :password, :password_confirmation)
    end
end

db/schema.rb

# This file is auto-generated from the current state of the database. Instead
# of editing this file, please use the migrations feature of Active Record to
# incrementally modify your database, and then regenerate this schema definition.
#
# Note that this schema.rb definition is the authoritative source for your
# database schema. If you need to create the application database on another
# system, you should be using db:schema:load, not running all the migrations
# from scratch. The latter is a flawed and unsustainable approach (the more migrations
# you'll amass, the slower it'll run and the greater likelihood for issues).
#
# It's strongly recommended that you check this file into your version control system.

ActiveRecord::Schema.define(version: 20180113170026) do

  create_table "movies", force: :cascade do |t|
    t.string "name"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end

  create_table "posts", force: :cascade do |t|
    t.string "body"
    t.integer "user_id"
    t.integer "topic_id"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.index ["topic_id"], name: "index_posts_on_topic_id"
    t.index ["user_id"], name: "index_posts_on_user_id"
  end

  create_table "topics", force: :cascade do |t|
    t.string "title"
    t.integer "user_id"
    t.integer "movie_id"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.index ["movie_id"], name: "index_topics_on_movie_id"
    t.index ["user_id"], name: "index_topics_on_user_id"
  end

  create_table "users", force: :cascade do |t|
    t.string "index"
    t.string "name"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.string "password_digest"
    t.index [nil], name: "index_users_on_index", unique: true
  end

  create_table "users_movies", id: false, force: :cascade do |t|
    t.integer "user_id"
    t.integer "movie_id"
    t.index ["movie_id"], name: "index_users_movies_on_movie_id"
    t.index ["user_id"], name: "index_users_movies_on_user_id"
  end

end

db/migrate/20171125194647_create_users.rb

class CreateUsers < ActiveRecord::Migration[5.1]
  def change
    create_table :users do |t|
      t.string :index
      t.string :name

      t.timestamps
    end
  end
end
1
  • did you try to rebuild your database?
    – Hatik
    Commented Jan 14, 2018 at 13:07

1 Answer 1

0

You can create a migration to rename the attribute in your model, like:

$ rails g migration rename_index_to_username

Inside the migration file, specify the model which to update as the first argument for rename_column, then the old attribute name and the new one:

class RenameIndexToUsername < ActiveRecord::Migration[5.1]
  def change
    rename_column :users, :index, :username
  end
end

Then run rails db:migrate to persis the changes.

After that the error will persist, because there is still some references to index in other files:

  • First edit the user_params created by Rails, replacing index with username.
  • Replace in the show and index page, any reference to the index attribute to username.
  • Replace in the form the text_field helper pointing to index with username.
  • Finally replace also the validation in the model to validates :username ...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.