0

I have a webapp that gives an option to create a new user. However, the problem is that idUser is null I have to generate it automatically.

How do I set :idUser? I have an idea of using User.last.id+1 but I have troubles implementing it.

def user_params
  params.require(:user).permit(:name, :surname, :email, :password, :userName, :idUser)
end
marcospereira
  • 12,045
  • 3
  • 46
  • 52
  • 1
    The `id` should be generated automatically! – Hieu Pham Jan 22 '16 at 03:47
  • 1
    rails (and more generally ruby) doesn't use camelCase, the convention is snake_case, you don't need `idUser`, `id` is a column automatically provided by rails (except you have monkeyed things) and it is by default auto-incrementing – bjhaid Jan 22 '16 at 03:50
  • It unfortently is not since I generated models from db and not the other way around. So I am stuck with idUsers that doesnt automaticly generate. – Domen Lušina Jan 22 '16 at 03:51
  • How is the `users` table defined inside the existing database? How were the `idUser` values assigned to the existing rows? BTW, `User.last.id+1` is not a good approach, that's subject to race conditions and can produce bad values if rows are deleted. – mu is too short Jan 22 '16 at 04:08

3 Answers3

1

Add the primary key in your class definition

class User << ActiveRecord::Base self.primary_key = "idUser" end

and then the params should be handled correctly.

Ray Baxter
  • 3,181
  • 23
  • 27
1

You could try something like:

User.rb

before_create :generate_reference

private

def generate_id
  self.reference = loop do
    token = SecureRandom.urlsafe_base64(nil, false)[0..19]
    break token unless Request.exists?(reference: token)
    self.idUser = token
  end
end
Juan José
  • 39
  • 5
  • this is prone to race conditions, all this work should be done by the DB and not in your code – bjhaid Jan 22 '16 at 19:38
0

Your pattern is pretty lame, but nonetheless you'll want to do one of the following:

  1. Set the "primary key" as idUser
  2. Pull the idUser and "increment" it manually
  3. Use UUID functionality

1 - In your DB, you can set your primary_key to idUser, which should allow you to provide auto-increment functionality:

$ rails g migration AddPrimaryKey

# db/migrate/add_primary_key______.rb
class AddPrimaryKey < ActiveRecord::Migration

   def self.up
      execute "ALTER TABLE users modify `idUser` id int(8) AUTO_INCREMENT"
      execute "ALTER TABLE users ADD PRIMARY KEY (idUser);"
   end

   def self.down
      execute "ALTER TABLE users modify `idUser` id int(8)"
   end

end

$ rake db:migrate

Some wise advice from this answer:

Use the built-in id field as the primary key. If you're going to use Rails, you should build your app the "Rails way" unless you have very good reason not to.

--

2 - You could use this answer:

#app/models/user.rb
class User < ActiveRecord::Base
   before_create :set_id, if: "idUser.blank?"

   private

   def set_id
      self[:idUser] = User.maximum(:idUser).next
   end
end

--

3 - If you wanted to use the inbuilt uuid functionality of Rails, you'd be able to set the idUser as the primary key (above), but instead of making it auto-increment, make it a string and add a UUID generator to it:

# db/migrate/add_primary_key______.rb
class AddPrimaryKey < ActiveRecord::Migration

   def self.up
      execute "ALTER TABLE users ADD PRIMARY KEY (idUser);"
      if Rails.env.staging? #-> Heroku PGSQL
          execute("CREATE EXTENSION IF NOT EXISTS \"uuid-ossp\"")
      else #-> MYSQL
          execute("DROP TRIGGER IF EXISTS before_insert_users;");
          execute("CREATE TRIGGER before_insert_nodes BEFORE INSERT ON users FOR EACH ROW SET new.uuid = uuid();")
      end
   end

end

#app/models/user.rb
class User < ActiveRecord::Base
   set_primary_key "idUser"
end

This will allow you to just use rails as if you were using an id / uuid column, ActiveRecord referencing idUser as required.

Community
  • 1
  • 1
Richard Peck
  • 76,116
  • 9
  • 93
  • 147