Reputation:
Trying to create a profile form in which a user can add information about their hobbies to their user profile. But I get the following error when trying to do so.
NoMethodError in Users#edit_profile
undefined method `hobbies' for #<User:0x007ff1a8a1f198>
Does anyone know what the problem could be, or a potential solution? I'm new to rails but I was under the impression that 'text_field' was a safe bet to make any custom input work. Would installing the strong parameters gem help this out at all?
edit_profile.html.erb
<h2>Tell us about yourself</h2>
<%= form_for @user do |f| %>
<%= f.label :first_name %><br />
<%= f.text_field :first_name, autofocus: true %>
<%= f.label :last_name %><br />
<%= f.text_field :last_name %>
<%= f.label :hobbies %><br />
<%= f.text_field :hobbies %>
<div><%= f.submit "Update" %></div>
<% end %>
user_controller.rb
class UsersController < ApplicationController
before_filter :authenticate_user!
def index
@users = User.all
end
def show
@user = User.find(params[:id])
end
def new
@user = User.new
end
def create
end
def edit
end
def update
@user = User.find(params[:id])
@user.update!(user_params)
redirect_to @user
end
def destroy
end
def edit_profile
@user = User.find(params[:id])
end
def user_params
params.require(:user).permit(:first_name, :last_name, :email, :password, :password_confirmation, :hobbies)
end
end
user.rb
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
attr_accessible :first_name, :last_name, :email, :password, :password_confirmation, :remember_me, :hobbies
#validates :first_name, presence: true, length: { maximum: 50 }
#validates :last_name, presence: true, length: { maximum: 50 }
end
Upvotes: 0
Views: 1361
Reputation: 76774
Does anyone know what the problem could be, or a potential solution?
Sure - the problem is you don't have a hobbies
attribute in your User
model :)
Since you're new, I'll explain a bit about Rails after I answer the question. However, let me explain the value of creating the right attributes:
#app/models/user.rb
class User < ActiveRecord::Base
attr_accessor :hobbies
end
This is what you'll need to create a single attribute for your User
model. The attr_accessor
directive is a Ruby method which sets a getter
and setter
in your User
model
This will give Rails the ability to populate the hobbies
attribute of your Model
. However, the data will not be persistent, as it will only be set on a per-instance basis in the model, meaning it will be lost when you refresh the page etc
Using the code above should get your form working, regardless of whether you're using Rails 3 or 4.
Models
Rails is famously an MVC framework - which means it has 3 core components - models
(builds data from the database), controllers
(configure data for the view) & views
(displays the data from the controller & model).
When you load a Rails application, you're sending a request, which will be routes to a particular controller action. This will then call data from your database, allowing you to manipulate it in your view.
Models
, therefore have to be populated from your database. They do this by taking the various attributes you have in your datatables, and creating a series of getters and setters
for them. These give you the ability to access the data within the attributes, or set new ones.
Your error occurs because you don't have the relevant attribute set in your datatable. You'll need to create a migration to add the hobbies
attribute to your User
model:
> $ rails g migration AddHobbiesToUser hobbies:string
> $ rake db:migrate
The migration should create something like:
class AddPartNumberToProducts < ActiveRecord::Migration
def change
add_column :users, :hobbies, :string
end
end
Upvotes: 0
Reputation: 22296
You don't mention it, but I will assume you're running Rails 4.x.
Rails 4.x introduced strong parameters, so in your controller you need to add a private method to set the allowed parameters and remove the attr_accessible
from your model.
So in you case it will be:
def user_params
params.require(:first_name, :last_name).permit(:email, :password, :password_confirmation, :remember_me, :hobbies)
end
If you still have trouble to understand the concept, or came from a previous Rails version, take a look at this blog post.
Upvotes: 2