Reputation: 16023
I'm trying to do in a rails console
>> user = User.new(:name => "", :email => "[email protected]")
=> #<User not initialized>
My User class looks like
class User < ActiveRecord::Base
attr_accessor :name, :email
has_many :microposts
def initialize(attributes = {})
@name = attributes[:name]
@email = attributes[:email]
end
def formatted_email
"#{@name} <#{@email}>"
end
end
I am following along from the rails tutorial. Why am I not able to initialize the object ?
Upvotes: 3
Views: 4758
Reputation: 1931
tl;dr: Copy exactly from the book and you should be fine. (Note: I am the author.)
The example in question is from Chapter 4 of the Ruby on Rails Tutorial book and is not an Active Record model. In particular, the User class shown in the question is based on Listing 4.9:
class User
attr_accessor :name, :email
def initialize(attributes = {})
@name = attributes[:name]
@email = attributes[:email]
end
def formatted_email
"#{@name} <#{@email}>"
end
end
This class does not inherit from ActiveRecord::Base
, but rather must be included explicitly in the console using require './example_user.rb'
, as described in Section 4.4.5. The behavior you're seeing is the result of including < ActiveRecord::Base
in the first line, but if you copy the code in Listing 4.9 exactly you should see the expected behavior.
Upvotes: 4
Reputation: 13014
First, I assume that User
model persists in your Rails app. That means, that you already have a migrated User
model before running rails console
.
If that table doesn't exist, you will be instanly prompted with:
=> User(Table doesn't exist)
Now, let's have some fun in rails console
:
First things first, don't override initialize
method in Rails model; While creating an object initialize method from ActiveRecord takes precedence (I think), so it may create conflicts. Instead use after_initialize
callback. In console:
class User < ActiveRecord::Base
attr_accessible :name, :email
def after_initialize(attributes = {})
self[:name] = attributes[:name]
self[:email] = attributes[:email]
end
def formatted_email
"#{self.name} <#{self.email}>"
end
end
Now,
u = User.new({name: "Foo", email: "[email protected]"})
#<User name: "Foo", email: "[email protected]", created_at:nil updated_at: nil>
u.formatted_email
#=> "Foo <[email protected]>"
All done! Sweet.
UPDATE:
As per your recent gist; I see no point of having after_initialize
at all. Rails does that on it's own.
First thing first, replace attr_accessor
with attr_accessbile
.
attr_accessor
is ruby method(courtesy, metaprogramming) which creates getter and setter for provided instance variable. Rails uses attr_accessible
for that; for security concerns, only instance variables allowed in attr_accessible
allowed for mass-assignment (by sending params hash).
user.rb
class User < ActiveRecord::Base
attr_accessible :name, :email
#def after_initialize(attributes = {})
# self[:name] = attributes[:name]
# self[:email] = attributes[:email]
#end
def formatted_email
"#{self.name} <#{self.email}>"
end
end
Upvotes: 2
Reputation: 835
Are you running console using the rails c
command to load your environment from the root directory of your project? Typing irb
to start a console session does not load the Rails application environment by itself.
Here are some more troubleshooting tips
config/database.yml
is running rake db:migrate
varchar
(or text
) for fields :name and :emailUpvotes: 0
Reputation: 829
are you running your console in the same file directory as your project? I'd also try switching up the notation to the example used in the book and see if that gets you anywhere.
you can also try calling User.new with no attributes and see if it generates an object as listed in 6.1.3 of the tutorial , and then fill in the attributes and see if it works.
also make sure you dont have a validation on your user name in your model.
and a last check you can run user.error to see why it might not be saving
Upvotes: 2