ruby on rails myprofile page - ruby-on-rails

I want to create a profile page for users that signing up
so let's say a user already registered, his profile link should be
website.com/profile/username
and on the
views/profile/index.html.erb
each user should see his own profile and edit it with the form_for I guess
so far I have profiles_controller.rb, profile.rb model and resources :profilesfor my routes.rb
What is the best way to do that?

If you wanna get by username then you need to use slug. The example below is for id version.
Profile controller
def show
#profile = Profile.find(params[:id])
end
routes:
get 'profile/:id' => 'profile#show'
for :slug version, url will be like this: http://localhost:3000/profiles/**username**
routes:
resources :profiles, param: :slug
profiles_controller
def show
end
private
def set_profile
#profile = Profile.find_by_username(params[:slug])
end
Or you can use gem for this https://github.com/norman/friendly_id

Related

How to update a profile attribute by link_to

I want to update a Profile model attribute by using link_to. The Profile model have a lang column, and I want to change to :en.
I could find out that I should use method: :put.
<%= link_to t('english'), profile_path(profile: {lang: :en}), method: :put %>
But it's ends up with error:
ActionController::UrlGenerationError in StaticPages#home
Showing /Users/ironsand/dev/phrasebook/app/views/layouts/_header.html.erb where line #21 raised:
No route matches {:action=>"update", :controller=>"profiles", :profile=>{:lang=>:en}} missing required keys: [:id]
I have this line in routes.rb to use the path:
resources :profiles, only: :update
How can I enable the function like this?
I found a similar question, but the case is a bit difference.
Edit
class ProfilesController < ApplicationController
def update
return redirect_to root_path unless current_user # If user is not logged in, redirect to /
if current_user.profile.update(profile_params) # Don't forget about validation for lang in Profile model
redirect_to root_path
else
redirect_to root_path
end
end
private
def profile_params
params.require(:profile).permit(:lang)
end
end
You need to identify the profile somehow, that's why it asks for id. But you can update profile without id, you just need to improve update method:
def update
return redirect_to root_path unless current_user # If user is not logged in, redirect to /
if current_user.profile.update(profile_params) # Don't forget about validation for lang in Profile model
redirect_to success_path
else
redirect_to error_path
end
end
private
def profile_params
params.require(:profile).permit(:lang)
end
For route, try this:
resources :profiles, only: [] do
collection do
put :update
end
end
or just:
put '/profiles' => 'profiles#update'
Since you're updating a specific profile, you need to supply something that lets your controller know what profile you're updating.
As you can see from the error message generated, your controller can't identify which profile it is that you're asking to be updated. You need to supply the id of the profile in order to update it.
One way this could be achieved with link_to is as follows:
link_to t('english'), profile_path(id: #profile.id, lang: :en), method: :put
lang would then be available in your update action in params[:lang].

Rails: How do I create links like "mysite.com/fFD2Zad" instead of "mysite.com/?var=fFD2Zad"

I want users to have codes to invite other users to the website. I know how I could generate random strings but how can I make it so that each user has a link such as "mysite.com/fFD2Zad" that uses the code instead of having a bulky link like "mysite.com/?var=fFD2Zad"?
Rails.application.routes.draw do
get '/:invitation_code', to: 'users#welcome'
end
class UsersController < ApplicationController
def welcome
p params
end
end
Check yourserver.com/fFD2Zad
#=> {"controller"=>"users", "action"=>"welcome", "invitation_code"=>"fFD2Zad"}
You can add the lowest priority route in the end of routes.rb:
get '/:user_code', to: 'users#profile', user_code: /[a-zA-Z0-9]{7}/
And process it in your controller:
def profile
# => params[:user_code]
...
end

Rails 4 - routing actions for contact form

I have two actions in the controller:
def report
#user = User.find_by_slug(params[:slug])
end
def reportForm
#user = User.find_by_slug(params[:slug])
Thread.new do
mail = ...
end
#message = 'Thanks!'
end
and in routes:
# User report form
get "/user/:slug/report", to: "users#report"
# Catch report form and action
post "/user/:slug/report", to: 'users#reportForm'
And the view:
<form method="POST" action="/user/<%= #user.slug %>/reportForm">
...
But the problem is, that when I send the form, the action reportForm is not called and instead of that is only refresh the current page with the form.
What's wrong here?
Thank you guys.
Form Helpers
The first thing that's wrong is you're not using the form helpers that Rails provides - this is a problem because you'll end up with niggly little problems like the one you're receiving:
#config/routes.rb
resources :users do
get :report #-> domain.com/users/:id/report
post :reportForm #-> domain.com/users/:id/reportForm
end
#view
<%= form_tag user_reportForm_path(#user) do %>
...
<% end %>
Routes
The second issue you have is to do with your routes
You've set the following routes:
get "/user/:slug/report", to: "users#report"
post "/user/:slug/report", to: 'users#reportForm'
This means you've got to send the request to domain.com/user/user_slug/report. Your form sends the URL to reportForm...
You should see my routes above for the solution to this problem
But more importantly, you should read up on nested resources:
#config/routes.rb
resources :users do
match :report, action: "reportForm", via: [:get, :post] #-> domain.com/users/:id/report
end
Slug
Finally, you're trying to use params[:slug] in your controller
With the resourceful routes you should be using in Rails, you'll be passing params[:id] most of the time. This should not be an issue (what is contained in params[:id] can be anything).
I would highly recommend looking at a gem called friendly_id, which makes including slugs in your application a lot simpler:
#app/models/user.rb
Class User < ActiveRecord::Base
extend FriendlyId
friendly_id :name, use: [:slugged, :finders]
end
This will allow you to call:
#app/controllers/users_controller.rb
Class UsersController < ApplicationController
def reportForm
User.find params[:id] #-> will use either `id` or `slug`
end
end

Customizing Friendly_id URL

First I am sorry for my English
I am using Friendly_id gem to create Clean URL and it work just fine but instead of having a URL like this http://localhost:3000/profile/jack-sparo I want a URL like this http://localhost:3000/profile/1/jack-sparowhere 1 is the user_id, so how can I do it?
this is my config/routes
get "profiles/show"
get '/profile/:id' => 'profiles#show', :as => :profile
get 'profiles' => 'profiles#index'
and this is my Profile controller
def show
#user= User.find_by_slug(params[:id])
if #user
#posts= Post.all
render action: :show
else
render file: 'public/404', status: 404, formats: [:html]
end
end
If you have an id of the record in URL anyway, you don't need
Friendly_id gem. You need to tune routes.
But maybe you would be happy with something like this instead?
http://localhost:3000/profiles/1-john-smith
If so, you need to override to_param method in User model like
this:
class User < ActiveRecord::Base
def to_param
"#{id}-#{name}".parameterize
end
end
Now the profile_path(profile) helper will generate URL like
http://localhost:3000/profiles/1-john-smith
And, with this request, the User.find(params[:id]) in controller
will find profile with id 1 and cut all other stuff which was in URL.
So
http://localhost:3000/profiles/1-mojombo-smith
will link to the same profile as
http://localhost:3000/profiles/1-john-smith

Rails route dependent on current user

I'd like to create a rails route for editing a user's profile.
Instead of having to use /users/:id/edit, I'd like to have a url like /edit_profile
Is it possible to create a dynamic route that turns /edit_profile into /users/{user's id}/edit, or should I do thing in a controller or?
You might want to create a separate controller for this task but you could also continue using users_controller and just check whether there is a params[:id] set:
def edit
if params[:id]
#user = User.find(params[:id])
else
#user = current_user
end
end
But you should note that /users normally routes to the index action and not show if you still have the map.resources :users route. But you could set up a differently called singular route for that:
map.resources :users
map.resource :profile, :controller => "users"
This way /users would list all the users, /users/:id would show any user and /profile would show the show the currently logged in users page. To edit you own profile you would call '/profile/edit'.
Since a route and controller serve two different purposes, you will need both.
For the controller, assuming you're storing the user id in a session, you could just have your edit method do something like:
def edit
#user = User.find(session[:user_id])
end
Then have a route that looks something like:
map.edit_profile "edit_profile", :controller => "users", :action => "edit"
This route would give you a named route called edit_profile_path
Tomas Markauskas's answer could work, but here's the answer to your question from the Rails Guide:
get 'edit_profile', to: 'users#edit'
So, when someone goes to www.yoursite.com/edit_profile, it will route to www.yoursite.com/users/edit.
Then, in your controller you can access the user with
#user = User.find(session[:current_user_id])
Assuming you set that session variable when someone logs in. Also, don't forget to check if they're logged in. This will work if your using Resourceful Routing (the Rails default) or not.
Source: http://guides.rubyonrails.org/routing.html
make the route as
get '/users/:id/edit', to: 'users#edit', as: 'edit_profile'
As explained in this link section 'The hard way' :
http://augustl.com/blog/2009/styling_rails_urls/
The url will be
/users/edit_profile
Because the ID is no longer in the URL, we have to change the code a bit.
class User < ActiveRecord::Base
before_create :create_slug
def to_param
slug
end
def create_slug
self.slug = self.title.parameterize
end
end
When a user is created, the URL friendly version of the title is stored in the database, in the slug column.
For better understanding read the link below
http://blog.teamtreehouse.com/creating-vanity-urls-in-rails
write it in any home controler.
def set_roots
if current_user
redirect_to dashboard_home_index_path
else
redirect_to home_index_path
end
end
in routes.rb file
root :to => 'home#set_roots'
match "/find_roots" => "home#set_roots"

Resources