17

I want to specifically set a field when a user is created. I have

class RegistrationsController < Devise::RegistrationsController
  def create
    super
    @user.tag_list = params[:tags]
  end
end

I have check boxes that pass the tags parameter and I have verified in the server logs that the tags parameter is being passed. However, when I call @user.tag_list in the console I just get a blank response [] .

I feel that the problem lies in my manipulating of the create method of devise. I have not explicitly set @user anywhere but am not sure how to set it using Devise. Does anyone know how to set a specific field when using devise?

Vasseurth
  • 6,354
  • 12
  • 53
  • 81
  • 2
    Planetpluto, you should add your own answer for using `resource` and mark that as the answer, as you alluded to in your comment Puneeth. That is a far better and simpler solution. – Jeff Sep 26 '13 at 19:54

3 Answers3

52

For future reference for anyone who finds this while searching for how to override devise methods, most of the Devise methods accept a block, so something like this should work as well:

class RegistrationsController < Devise::RegistrationsController
  def create
    super do
        resource.tag_list = params[:tags]
        resource.save
    end
  end
end
streetlogics
  • 4,640
  • 33
  • 33
  • 1
    it didn't work for me (Rails 3.2), i've switched to old one super then my instructions – OWZY Jun 04 '15 at 18:02
  • Worked on Rails 5.1. – haris Jul 17 '17 at 13:38
  • Beware that this might be dangerous as already existing users will be loaded into resource when there is a duplicate registration! Use `resource.persisted?` to check if the user was successfully created. – clst Feb 08 '21 at 14:53
12

Instead of using super to invoke the Devise::RegistrationsController's create action, replace it with the actual code of Devise::RegistrationsController's create method

build_resource
resource.tag_list = params[:tags]   #******** here resource is user 
if resource.save
  if resource.active_for_authentication?
    set_flash_message :notice, :signed_up if is_navigational_format?
    sign_in(resource_name, resource)
    respond_with resource, :location => after_sign_up_path_for(resource)
  else
    set_flash_message :notice, :"signed_up_but_#{resource.inactive_message}" if is_navigational_format?
    expire_session_data_after_sign_in!
    respond_with resource, :location => after_inactive_sign_up_path_for(resource)
  end
else
  clean_up_passwords resource
  respond_with resource
end
Puneeth
  • 519
  • 4
  • 9
  • 1
    Thanks, this works perfectly. I'm going to try using super and under it, instead of @user.tag_list resource.tag_list to see if that works too. – Vasseurth Apr 15 '12 at 20:22
  • Sorry for revisiting such an old thread, but Puneeth, can you explain why it would be better to put in the actual code from Devise's create method, as opposed to using `super`? – jeffdill2 Feb 11 '15 at 21:25
  • 1
    @streetlogics answer better addresses this question. The devise create super has this line "yield resource if block_given?" that will evaluate the block added in his example. – blnc Mar 11 '15 at 16:42
9

If you don't want to rewrite the entire code of the create method, you can simply set the resource variable inside the protected method :build_resource of Devise::RegistrationsController, which is called before the resource is saved.

protected 

# Called before resource.save
def build_resource(hash=nil)
  super(hash)
  resource.tag_list = params[:tags]
end
Pedro Augusto
  • 303
  • 3
  • 5
  • 1
    Had an issue with the accepted answer triggering my validation twice and this approach brought a new approach to my implementation, thanks. – ollaollu Apr 09 '17 at 19:35