I'm having trouble viewing other users in my app - ruby-on-rails

In the users controller for my app I have a method for viewing the posts generated by users, but when you go to the index page and click on another user, the page of the currently logged in user shows up but the url is for the user I just clicked onto.
This is the method in my users controller
def feed
#title = "Feed"
#user = User.find(session[:user_id]) # This is the problem
feed = Feed.new(#user)
render 'show_feed'
end
I'm also having trouble understanding the difference between session[:user_id] and params[:id]. If I change session[:user_id] to params[:id] while on the page, of the user I just clicked onto, their posts are then shown, but when I go back to the logged in user's page I get the error "Couldn't find User with 'id'=user_id" in "app/controllers/users_controller.rb:59:in `feed'" So my question is, what do I need to pass into #user = User.find() to get the correctly generated page/s?

Generally if you're clickiing on a link to see some OTHER user, the link has an "id" embedded in it which is passed in the params, so you would do...
#user = User.find(params[:id])
Your link to go back to the logged in user is incorrect, but you haven't shown that link. It should most probably be something like
<%= link_to user_path(session[:user_id]) %>
From the description of your problem you may be doing...
<%= link_to user_path('user_id') %>
... which doesn't make sense... it means literally go to the user record with the id of "user_id"

session is data (usually stored in a cookie) that is persistent from one request to another and that expires at the end of the browser session. A common use is to store the id of the logged in user.
By passing that to User.find you're entirely ignoring the user id that is in the URL. You should be using params[:id] (unless your routes are naming that segment of your url differently)
Your problem when you "go back" is not clear to me (I can't even tell if we're talking about the same controller action) but at a guess either that page doesn't have an id in the URL, or the routing is calling it something else, or (and this is a little messy) you intend to fall back to the current user when there is no id in the URL in which case you need to be using either params[:id] or session[:user_id] depending on what's there.

Related

Routing to profile page by username

I am working on a social media site and I am having a problem with routing.
Every user has a profile page like facebook and this is the root I use:
get 'profile(/:id)' => 'profiles#show'
So, when the URL is like this: www.sitename.com/profile/1 it opens up the page belongs to user with id 1. But, I also want users to be able to use their usernames in url without /profile/. So it is gonna be like facebook.
For example: www.sitename.com/handsomeboy69
How can I do this in routing? Because, rails may think that username passed in URL is a page name.
Thank you
I fixed it. This is the route I used:
get ':username' => 'profiles#show'
In the controller I used this statement:
if params.has_key?(:username)
#profile = User.find_by_username(params[:username])
elsif params.has_key?(:id)
#profile = User.find(params[:id])
else
end
else statement at the end is empty, I am gonna use that area to print out error message saying that profile cannot be found.
and most important part is that this routing should be at the end of the file.

Accessing Params in Rails 3.2

I am working through the RailsApps Stripe tutorial.
When a new subscriber is created through a devise registration controller they are then directed to their content page through a content controller. I want to use their name and email address created upon registration on their content page. But I can't seem to bring the params into the content controller.
I put#user = User.find(params[:id]) into the content_controller but I get the error "Couldn't find User without an ID".
On the error page it lists under Request Info > rack session: "warden.user.user.key"=>["User", [2],
So does that mean that ID of User #2 is being passed to the content_controller but that I can't access it?
I put#user = User.find(params[:id]) into the content_controller but I
get the error "Couldn't find User without an ID".
This error means that params[:id] = nil, i.e., you are not passing id in the params hash when redirecting the user to content page.
Possible Solutions:
With Devise you get a helper method called current_user which returns an instance of currently logged in user. So, you could directly use current_user to access the attributes of currently logged in user. For example:
To access name and email fields of currently logged in user, all you need to do is
current_user.name
current_user.email
In routes.rb, pass the id of the currently logged in user via the route of content page as below:
## Add :id dynamic segment to your content page route
get "content/:id", :to => "contents#action_name", :as => "content_page"
Since, I don't have the route details, you would need to modify the above route as per your requirement.
Next, when redirecting the user to content page after sign up just pass the currently logged in user as below in ApplicationController method named after_sign_up_path_for (You need to override this Devise method if you want to redirect the user to a different route than the default root path):
def after_sign_up_path_for(resource)
content_page_path(resource) ## Provide the path and pass resource to it
end
With Devise, you can access the currently logged in user via the current_user helper in your controller.
See documentation: https://github.com/plataformatec/devise#controller-filters-and-helpers

Rails how to save the requested url?

I have two different ways to access the url "localhost:3000/childrens/new".
I have a drop down in childrens/new page and when the user selects an option through the drop down, it shows the different partials using ajax to call the childrens#new method.
accessing the childrens new page from url "localhost:3000/parents"
accessing the childrens new page from url "localhost:3000/parents1"
After the children have been successfully created, the user should be redirected to the relevant url (either localhost:3000/parents or localhost:3000/parents1)
Store the value in session like session[:last_request] in parent
After create children redirect it to session[:last_request] || session[:return_to] and after that clear the session[:last_request]
There are more than one way of how you can achieve this.
One solution would be to store the referrer inside of the session/cookie when the childrens/new is requested: (inside children_controller)
def new
session['children_new_referrer'] = request.env["HTTP_REFERER"]
#....YOUR CODE....
end
And then using that referrer value stored in session/cookie to redirect appropriately:
def create
#.....YOUR CODE....
if #child.save
format.html {redirect_to (session['children_new_referrer'] || parents_path)}
#.....YOUR CODE....
end
where #child is the object which I assume you are building with the parameters, and parents_path is being defined through your routes. Feel free to adjust these two based on your needs.
An alternative solution would be to not use sessions, but instead save the referrer uri/path inside of the children/new form page itself. This alternative has the benefit of making the solution session/request scope independent with handling the requirement of storing the referral uri/path within the page scope.
Do something like this
def create
redirect_to :back
end
redirect_to :back should come after save.
Pass the referrer as a parameter in the link. I would much prefer this solution to using the session store.
<%= link_to "New child", new_child_path(referrer: #parent.id) %>
.. or whatever you want to call it. Then you can inspect params[:referrer]. You're not wanting to persist data across a 'session', so why use the session store.
request.url
in your controller gives the url you are asking for.
So,
def create
if #child.save
redirect_to request.url
end
end
will do the job perfectly

Rails - how to pass created record from the new form to a redirected page

I think this is a pretty simple question but nothing I've read has answered my question directly:
I have a new products page with a standard form. After successfully submitting the form, I redirect to a custom controller action and view called "thanks".
On the "thanks" page, I want to be able to print the name of the product just created and possibly some other attributes.
How do I pass the object just created into my new action? Right now the controller looks like this:
def create
#product = Product.new(params[:product])
if #product.save
flash[:notice] = "Successfully created Product."
redirect_to thanks_path
else
render :action => 'new'
end
end
def thanks
end
You can't send object through redirect.
There are three ways to solve your problem:
Render the 'thanks' template directly(not action #thanks)
render 'thanks' # thanks template
You can send whatever instance variable to this template directly. #thanks is no longer needed in this case.
Drawback: The url won't be changed.
Convey messages through session
If you want to show certain messages, you can prepare it in #create and send it through session or flash(part of session actually). flash is better as you don't need to clear it manually.
Note: You may want to use ActiveRecord as session storage if the message size is big, otherwise you'll meet CookiesOverflow by default setting.
Send very simple message through session say obj_id
Similar to #2 but I thinks this is better than #2. In #thanks, you can construct complex message according to if obj_id is present, what is the id and then find related data through db.
You have two fairly decent options.
First, you could adjust the thanks_path route to take an id parameter, and call it like redirect_to thanks_path(#product). Then you can call it up in your thank you method like any standard show method. It might be worth mentioning that if you are going to be displaying sensitive information on the thank you screen, you may want to use a random uuid, instead of an id, to look up the product.
A better way might be to not redirect at all, but rather adjust your view from simply drawing the form to something like this:
<% if #product && !#product.new_record %>
THANK YOU MESSAGE GOES HERE
<% else %>
EXISTING FORM GOES HERE
<% end %>

Making sure I got the idea . - Ruby on rails login system

I am currently reading a book, and learning ruby on rails. (Agile Web Development with Rails 4th Edition) .In the book it says how to write a simple product list and display it. I am modifying this idea, to create a user login system.
I am only working on the views now.
So I just need to make sure that my idea is right. My idea is:
The show.html file from the USER model, show data for one user. (given of course its ID)
for example : http://localhost:3000/users/980190974 will give me the html page for the current user right? Now I can allow the user to edit his/her information by using the
<%= link_to 'Edit', edit_user_path(#user) %> link or restrict him from viewing other users by removing the <%= link_to 'Back', users_path %> << that lists all the users from the database. But before the user views his/her details he must login, using his email and password. So by making an html page, that takes 2 strings (username, and password) searches my mySQL database and return the user ID , that I then use to "render" the user's HTML page.
Is my way of thinking correct? Or am I just completely irrelevant on how Ruby on Rails works? O_o
You are heading in the right direction. One thing to point out is that simply removing the link <%= link_to 'Back', users_path %> is not sufficient to avoid other users from accessing the /users path. In the (user) controller you have to use something like:
class UserController < ApplicationController
def index
unless current_user.is_admin
redirect_to user_path(current_user)
return
end
... rest of code here
end
end
where current_user could be a method returning the user object

Resources