Multiple feature creation

Hi all I wondering how I would go about generating multiple features on
user creation. I want every user who signs up to have a wishlist
automatically which is a separate to the actual users (different
model/view/controller etc.)

On user create I want it to create a user as well as create a wishlist.
The wishlist will be blank but I just want the feature to show on their
profile so that they can edit. Currently the user has to click on a
button to set it up.

Here is my current user create method. I want to add a line to create
the wishlist alongside. Any help will be appreciated.

def create
@user = User.new(params[:user])
respond_to do |format|
if @user.save
UserMailer.registration_confirmation(@user).deliver
session[:user_id] = @user.id
format.html { redirect_to root_url, :notice => “User was
successfully created.” }

else
  format.html { render :action => "new" }
  format.xml  { render :xml => @user.errors, :status =>

:unprocessable_entity }
end
end
end

Hi Chris,

Use an after_create callback in the User model to create the associated
Wishlist record.

HTH,
Bill

Use an after_create callback in the User model to create the associated
Wishlist record.

So in the user model would I define first like this:

after_create :set_wishlist

then the following:

def set_wishlist
@wishlist = Wishlist.new(params[:wishlist])
end

I hope I am on the correct track.

Any feedback would be great. Thanks.

Hi,

I tried the method that I stated in the model:

def set_wishlist
@wishlist = Wishlist.new(params[:wishlist])
end

But once I created the user it returned an error screen stating:

NameError in UsersController#create

undefined local variable or method `params’ for #User:0x4a51a78
Rails.root: C:/finalproject

Application Trace | Framework Trace | Full Trace

app/models/user.rb:21:in set_wishlist' app/controllers/users_controller.rb:35:inblock in create’
app/controllers/users_controller.rb:34:in `create’

My usersController create methods looks like the following:

def create
@user = User.new(params[:user])
respond_to do |format|
if @user.save
UserMailer.registration_confirmation(@user).deliver
session[:user_id] = @user.id
format.html { redirect_to root_url, :notice => “User was
successfully created.” }

else
  format.html { render :action => "new" }
  format.xml  { render :xml => @user.errors, :status => 

:unprocessable_entity }
end
end
end

On Thu, Feb 9, 2012 at 5:43 AM, Christopher J. [email protected]
wrote:

@wishlist = Wishlist.new(params[:wishlist])
end

I hope I am on the correct track.

Any feedback would be great. Thanks.

That’s the general idea though, from what you’ve said, the only thing
you’ll know about the Wishlist object at the point of creation is the
User to whom it belongs. If you need to return it to the user in the
response, as indicated by your creation of a separate instance
variable, you’ll want to do that in the User controller prior to
rendering.

Best regards,
Bill

On Feb 9, 2012, at 10:43 AM, Christopher J. wrote:

NameError in UsersController#create

undefined local variable or method `params’ for #User:0x4a51a78
Rails.root: C:/finalproject

If you tried this in the controller, you would find the params hash
available. But in the model, there’s no such animal. That’s what the
error message is telling you. You could pass that variable back to the
model, like this:

def set_wishlist(params)

end

and then include the params hash in your method call. But if you want to
rely on that hash just being there, you could probably put this method
in your controller and call it from there in your after_create callback.

Walter

By stating params in the model as

def set_wishlist(params)

It returns the error of: wrong number of arguments (0 of 1).

If I was to try and call the create method from wishlistController
through the user model, how would I go about calling it?

I have not had he experience of doing such thing before.

Thanks
Chris.

Hey Walter,

I have the following in my userController

after_filter :set_wishlist, :only => :create

def set_wishlist
@wishlist = Wishlist.new(params[:wishlist])
@wishlist.user = current_user
end

It goes ahead but doesn’t actually create a wishlist for the user. I
checked in the server log and it seems to just be searching for any
wishlist matching this user which it obviously wont find because it
hasn’t been created.

Any suggestions?

Thanks.

On Feb 9, 2012, at 11:06 AM, Christopher J. wrote:

By stating params in the model as

def set_wishlist(params)

It returns the error of: wrong number of arguments (0 of 1).

If I was to try and call the create method from wishlistController
through the user model, how would I go about calling it?

I have not had he experience of doing such thing before.

I don’t think you can, but you can do an after_filter on create, in the
controller:

after_filter :foo, :only => :create

private
def foo
@word.update_attributes(:notes => ‘FOO!’)
end

I just did this and it worked. You would have access to the variables
you set in your create method. Apparently these after_filter beasties
fire before any redirect is called.

Walter

That one-liner ought to Just Work.

Walter

I have my code like this but I just doesn’t seem to generate a wishlist
:frowning:

before_filter :set_wishlist, :only => :create

def set_wishlist
@wishlist = Wishlist.create(params[:wishlist])
@wishlist.user = current_user
@wishlist.save
end

On Feb 9, 2012, at 2:34 PM, Christopher J. wrote:

It goes ahead but doesn’t actually create a wishlist for the user. I
checked in the server log and it seems to just be searching for any
wishlist matching this user which it obviously wont find because it
hasn’t been created.

Any suggestions?

Try adding @wishlist.save to the end.

Actually, maybe structure it so you are adding a member to the
current_user.wishlists collection. If you do that, and you do this in a
before_save filter, then the wishlist will be saved along with the user.
Read the Rails guides about associations and auto-save. I know there’s
something in there that covers this.

def set_wishlist
@wishlist = current_user.wishlists.create(params[:wishlist])
end

That one-liner ought to Just Work.

Walter

And just to confirm, you are doing this in the user controller, right?

Yes this is all happening in the user model

What do your models look like for wishlist and user then? If you have
defined the has_many belongs_to relationship, then the one-liner I
showed you:

My user model has a: has_one: wishlist
My wishlist model: belongs_to: user

@wishlist = current_user.wishlists.create(params[:wishlist])

should create the relationship and build and save the wishlist.

I have put as you said:

before_filter :set_wishlist, :only => :create

def set_wishlist
current_user.wishlists.create(params[:wishlist])
end

But now I have errors return back stating:

undefined method `wishlists’ for nil:NilClass

If I change it to wishlist I get the same error as well as Wishlist. If
I state params in the def set_wishlist(params) it returns aargument (0
of 1) error.

On Feb 9, 2012, at 8:56 PM, Christopher J. wrote:

@wishlist = Wishlist.create(params[:wishlist])
@wishlist.user = current_user
@wishlist.save
end

And just to confirm, you are doing this in the user controller, right?
What do your models look like for wishlist and user then? If you have
defined the has_many belongs_to relationship, then the one-liner I
showed you:

@wishlist = current_user.wishlists.create(params[:wishlist])

should create the relationship and build and save the wishlist.

Walter

I know that the correct user is being signed in because certain elements
such as adding a product etc. get created based on who is signed in and
therefore associates the id of the product with them so that they get
displayed under the profile.

The wishlist should be created when I create the user account but at the
moment it doesn’t do that, I have to click on a button to create the
wishlist but my problem with doing that is that the button can be
clicked multiple times which I don’t want, I just want the user to be
able to create one wishlist so my options are to either have it create
on user creation or limit the button to one use per user but that is
beyond me.

On Feb 10, 2012, at 5:23 AM, Christopher J. wrote:

end

But now I have errors return back stating:

undefined method `wishlists’ for nil:NilClass

If I change it to wishlist I get the same error as well as Wishlist. If
I state params in the def set_wishlist(params) it returns aargument (0
of 1) error.

Okay, then you have another issue. For some reason, current_user isn’t
in the world when the method is being called, or maybe it’s not in scope
within that method. Can you put a breakpoint inside the method and see
what current_user equals at that point? Are you using Devise or
Authologic or similar, and are you sure the user is assigned (logged in)
at the moment that this method runs?

I didn’t try assigning a variable from outside of the method when I did
my little test (quoted earlier), just did a static assignment, and it
worked. We need to figure out how to get current_user into scope where
you need it, and then you can have the same success.

Walter

Okay, one last time, and I tested something similar to your application
this time. It’s much much simpler than we’ve been trending.

class User < ActiveRecord::Base

Include default devise modules. Others available are:

:token_authenticatable, :encryptable, :confirmable, :lockable,

:timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable

Setup accessible (or protected) attributes for your model

attr_accessible :name, :email, :password, :password_confirmation,
:remember_me
has_one :wishlist
after_create :assign_wishlist

private
def assign_wishlist
self.update_attributes :wishlist => Wishlist.create(:user_id =>
self.id)
end

end

class Wishlist < ActiveRecord::Base
belongs_to :user
has_many :wishlist_items
end

Please give that a try, or at least delete my other helpful suggestions,
which didn’t seem to work with a has_one relationship.

Walter

before_create :assign_wishlist

private
def assign_wishlist
self.wishlist = Wishlist.create
end

I placed the above in the user.rb (Is that correct or should it be
wishlist.rb?) and It created the account but after looking at the log
there was nothing about creating the wishlist like it said in yours, I
am truly stumped about what has gone wrong.

And even simpler:

before_create :assign_wishlist

private
def assign_wishlist
self.wishlist = Wishlist.create
end

1.8.7-p352 :003 > User.create! :name => ‘Bill’, :email =>
[email protected]’, :password => ‘helpermethod’, :password_confirmation =>
‘helpermethod’
=> #<User id: 5, name: “Bill”, created_at: “2012-02-10 19:51:15”,
updated_at: “2012-02-10 19:51:15”, email: “[email protected]”,
encrypted_password:
“$2a$10$rq0MdN9T7ErRj3Iqlt/eNOA8t22BbXM1xGNTz5w6LxhY…”,
reset_password_token: nil, reset_password_sent_at: nil,
remember_created_at: nil, sign_in_count: 0, current_sign_in_at: nil,
last_sign_in_at: nil, current_sign_in_ip: nil, last_sign_in_ip: nil>
1.8.7-p352 :004 > _.wishlist
=> #<Wishlist id: 4, created_at: “2012-02-10 19:51:15”, updated_at:
“2012-02-10 19:51:15”, user_id: 5>
1.8.7-p352 :005 >

Walter

This is my user model:

class User < ActiveRecord::Base
has_one :profile
has_many :games
has_one :wishlist

attr_accessor :password
before_save :encrypt_password

validates_presence_of :username
validates_length_of :username, :within => 6…20, :message => “must
contain between 6 to 20 characters”
validates_uniqueness_of :username
validates_presence_of :email
validates_uniqueness_of :email
validates_format_of :email, :with =>
/\A([^@\s]+)@((?:[-a-z0-9]+.)+[a-z]{2,})\Z/i, :on => :create
validates_confirmation_of :password
validates_length_of :password, :within => 8…20, :message => “must
contain between 8 to 20 characters”
validates_presence_of :password, :on => :create
validates_presence_of :password_confirmation

before_create :assign_wishlist

private
def assign_wishlist
self.wishlist = Wishlist.create
end

def encrypt_password
if password.present?
  self.password_salt = BCrypt::Engine.generate_salt
  self.password_hash = BCrypt::Engine.hash_secret(password, 

password_salt)
end
end

def self.authenticate(email, password)
user = find_by_email(email)
if user && user.password_hash ==
BCrypt::Engine.hash_secret(password, user.password_salt)
user
else
nil
end
end
end

and the following is my wishlist model:

class Wishlist < ActiveRecord::Base
belongs_to :user
validates_presence_of :number_1
validates_presence_of :number_2
validates_presence_of :number_3
validates_presence_of :number_4
validates_presence_of :number_5

end

On 10 February 2012 20:57, Christopher J. [email protected]
wrote:

contain between 8 to 20 characters"
def encrypt_password
BCrypt::Engine.hash_secret(password, user.password_salt)
class Wishlist < ActiveRecord::Base
belongs_to :user
validates_presence_of :number_1
validates_presence_of :number_2
validates_presence_of :number_3
validates_presence_of :number_4
validates_presence_of :number_5

I have come into this late so apologies if already discussed or not
relevant but any time one sees a model like this it sets alarm bells
going. Generally something like this is better dealt with by user
has_many wishes with one wish per record. Or maybe using something
like awsome_nested_set to get the ordering.

Colin