Reputation: 43
I have a new question.
What I want to do?
I've created the profile for each player, now I want to allow users to edit their profile.
Part of this profile takes the devise
table, with a second table called profiles
.
Devise: Captures username, password and email
Profiles: Captures Personal Information
Schema of Profiles
create_table "profiles", force: :cascade do |t|
t.text "about"
t.string "fb"
t.string "skype"
t.string "birthday"
t.string "twitter"
t.string "steam"
t.string "gender"
t.string "occupation"
t.string "location"
t.string "interest"
end
My profile_controller.rb (Updated)
class ProfileController < ApplicationController
def index
@profile = Player.all
end
def show
@profile = Player.find_by(nick: params[:nick])
end
def edit
# use this to populate a form in your view
@profile = Player.find_by(nick: params[:nick])
end
def update
@profile = Player.find_by(nick: params[:nick])
if @profile.update_attributes(profiles_params)
redirect_to(:action => "show", :profile => @profile.nick)
else
render("index")
end
end
private
def profiles_params
params.require(:profiles).permit(:about, :skype)
end
end
Rake routes
profiles GET /profiles(.:format) profiles#index
GET /profiles/:nick/edit(.:format) profiles#edit
GET /profiles/:nick(.:format) profiles#show
PATCH /profiles/:nick(.:format) profiles#update
PUT /profiles/:nick(.:format) profiles#update
Routes.rb
devise_for :players
resources :profile, param: :nick
resources :profiles, only: [:index, :show, :edit, :update], param: :nick
Notes:
show.html.erb
index.html.erb
*How should I make the edit page for each users profile, considering that each user edits their own profile?
Once a user edits a field, I want this to be reflected on the page show.html.erb
. How can I achieve this?*
** show.html.erb **
<div id="myTabContent" class="tab-content">
<div class="tab-pane fade active in" id="info">
<p><div class="form-group">
<label for="textArea" class="col-lg-2 control-label">About <%= @profile.nick %></label>
<div class="col-lg-10">
<pre style="padding-bottom: 200px;"><%= @profiles.about %>(THIS IS THE ERROR)</pre>
<span class="help-block">In Progress</span>
</div>
</div></p>
</div>
** edit.html.erb (Not _edit, because missing template)**
<strong>Testing About</strong>
<%= form_for :profiles do |f| %>
<%= f.label :about %>
<%= f.text_field :about %>
<div class="btn btn-primary">
<a href="http://localhost:3000/profile/<%= @profile.nick %>">
<%= f.submit "Update Profile", :class => 'btn btn-primary' %></a>
</div>
<% end %>
<% end %>
<p>I am editing for</p>
<%= @profile.nick %>
Thanks in advance
Upvotes: 0
Views: 2237
Reputation: 756
Show should be used to display a users profile, not edit it - this is the rails way.
I suggest you jump over and have a read on rails resourceful routing: http://guides.rubyonrails.org/routing.html - this covers routes and CRUD.
Consider you have your resource, :profiles - in your routes this can be declared as:
resources :profiles
This route will automatically create the desired routes for you - in this case we only seem to want index, show, edit and update therefore this can be declared:
resources :profiles, only: [:index, :show, :edit, :update]
We now have the following routes, i've commented what their purpose should be:
GET /profiles #show all profiles
GET /profiles/:id #show specific user profile
GET /profiles/:id/edit #edit specific user profile
PATCH /profiles/:id #update a specific profile
Now that we have our routes lets look at this from a controller perspective - i'm jsut going to focus on edit/update as this is your question:
class ProfileController < ApplicationController
def index
#do something
end
def show
# do something
end
def edit
# use this to populate a form in your view
@profile = get_profile
end
def update
@profile = get_profile
if @profile.update_attributes(profile_params)
#do something on success
else
# do something on fail
end
end
private
def profile_params
params.require(:profile).permit(:about, :skype, etc)
end
def get_profile
nick = params[:nick]
if Player.where(username: nick).present?
if Player.where(username: nick).count == 1
Player.includes(:profile).find_by(username: nick).profile
else
raise "Error: Multiple profiles found"
end
else
raise "Error: Profile cannot be found"
end
end
end
You'll notice the 'profile_params' method, this is apart of rails strong paramaters and whitelists the attributes we can use for mass assignment. Read more: http://edgeapi.rubyonrails.org/classes/ActionController/StrongParameters.html
Because our routes are set up as expected for our profile, our forms are super simple as rails can infer everything.
edit.html.erb
<%= form_for @profile do |f| %>
<%= f.text_field :about %>
... etc
<% f.submit %> # this will submit to profile#update
<% end %>
Further reading on form_for: http://apidock.com/rails/ActionView/Helpers/FormHelper/form_for
Ofcourse you should also be adding authorisation to the controller methods but hopefully i've covered the basic premise for you.
EDIT1: In regards to your comment I've added a private method for locating your user profile by either username or id (tweak to suit). But like I said, go through the linked readings so you can get an understanding of routing.
EDIT2: SO taking into consideration your further comments and the routes you added to the question i've updated your get_profile method.
Upvotes: 4