Rake task, który ustawi nazwe użytkownika z adresu email

Witam,
chcialbym ustawic dla wszystkich uzytkownikow nazwe, ktora bedzie pobierana z adresu email.

desc "Set username of all users wihout a username" task set_username_of_all_users: :environment do users_without_username = User.select{ |u| !u.username? } users_without_username.each do |user| username = user.email.split('@').first if User.find_by_username(username).blank? user.username = username user.save else User.find_by_username(username).each_with_index do |u, index| u.username = username.insert(0, index) u.save end end end end
Powyższy kod nie dziala po drugiej pętli.
Mam ustawione oczywiscie

  validates :username, :uniqueness => { :case_sensitive => false }

Zastanawiam się jak do tego podejść: https://gist.github.com/3067635#comments

Co znaczy „nie działa” w tym przypadku?

hmm, przy trzecim emailu o tym samym user.email.split(’@’).first nazwa uzytkownika pozostaje pusta.

ale zmienilem go na taki i dziala :), moze macie jakies uwagi:

desc "Set username of all users wihout a username" task set_username_of_all_users: :environment do users_without_username = User.where(:username => ["", nil]) users_without_username.each do |user| email_part = user.email.split('@').first user.username = email_part prefix = 1 while user.invalid? # add and increment prefix until a valid name is found user.username = email_part.insert(0, prefix.to_s) prefix += 1 end user.save end end

Czy masz walidację emaila? Czy jestes pewien, że email zawsze będzie miał małpkę?

Ryzykujesz też, że będziesz się kręcił w nieskończonej pętli zwiększając prefix, jeżeli z jakiegoś INNEGO powodu model będzie invalid.

mam walidacje emaila(devise)

w takim razie chyba spróbuje dodać jakoś sprawdzenie dlaczego user.invalid? => true

desc "Set username of all users wihout a username" task set_username_of_all_users: :environment do users_without_username = User.where(:username => ["", nil]) users_without_username.each do |user| user.username = user.email.split('@').first #solves the username error while user.invalid? && user.errors[:username].any? # add and increment prefix until a valid name is found user.username += rand(10)#0..9 end user.save! #shoults if there are any other errors end end

Mam jeszcze jeden problem z rosnacym prefixem, chcialbym jednak aby kazda kolejna nazwa uzytkownika jezeli sie powtaza byla z rosnacym prefixem: “test”, “1test”, “2test”

Toż już miałeś chyba podobny kod.

base_username = .... user.username = base_username prefix = 0 while user.invalid? && user.errors[:username].any? prefix += 1 user.username = "#{prefix}_#{base_username}" end
No i ja bym jednak dorzucił do środka jakiś warunek - strasznie nie cierpię nieskończonych pętli, nawet teoretycznych :slight_smile:

  raise "I give up - #{prefix} tries, and still no unique name." if prefix > 10000

No i jeszcze ja bym sprawdzał, czy błąd związany z username to na pewno ten dotyczący uniqueness, a nie czegoś innego. Bo tu znów zakładasz, że jeśli jest jakiś błąd, to na pewno jest to ten błąd, o którym myslisz. A czasami świat lubi zaskakiwać :wink:

Tu już nie wiem jak ustawiasz komunikaty błędów, ale ja zazwyczaj wrzucam tam symbole, a tłumaczenie tego na ludzki robię dopiero w widokach, więc miałbym coś w tym stylu:

 if user.errors[:username].include?( "not_unique" )