Rails force url to be case sensitive wrt to the parameters - ruby-on-rails

I have a rails app with the user model as follows
class User < ActiveRecord::Base
def to_param
"#{username}".parameterize
end
end
In routes.rb I have
resources :users, path: '/u'
To link to the show page of a user, I use
<%= link_to 'Show', #user %>
Now if a user has the username 'UsErNaMe', the above link does not work.
It goes to
http://localhost:3000/u/username
and not
http://localhost:3000/u/UsErNaMe
Any solution to this problem? Thanks in advance!

The usernames in your system should only be case sensitive for display (i.e. someone prefers their username to look a certain way on a page), but never for account lookup. You don't want two accounts, one called "UsErNaMe" and the other called "USERname" to be able to exist at the same time.
I.e. don't worry about the case in the URL. It's not important. What's important is how the username is displayed on the page.

Related

Rails devise registration two ways after sign_up

I want devise to redirect to specific controller index action( or specific page) after user is sign_up.
In detail, i have an app with 2 ways to sign-up : for the client and for the Professor . Actually, the 2 type use the same registration page, it works very nice but when they sign_up they are automatically redirect to the same page ...
So, i want to change the way like this :
- when user click on I want to become Professor i want to register (full name, mail, password) and redirect after sign_up to the Professor dashboard
- and when user click on Client i want to register with the "same way" BUT in the end, i want to redirect to the client's dashboard.
So, i started to change devise.rb to change this
config.allow_unconfirmed_access_for = 2.days (automatically login after sign_up)
And in my RegistrationsController, i override the after_sign_up_path_for to have something like
def after_sign_up_path_for(resource)
if 'user is Prof'
redirect_path_professor
else
redirect_path_client
end
end
but how can i check (in condition) if user click on Prof. or Client ?. Its the same resource (registration) ^^
Thanks
Why not using only one link, then let the user selects his role in the registration view?
If you really want two links for the same view, you should pass the role in a param (something link link_to 'Becoming a Professor', new_registration_path(role: 'professor'), then add an hidden_field in your registration form with the value of the param.
= f.input :role, as: :hidden, input_html: { value: params[:role] }
But don't forget to validate the content of the params to avoid the bad values sent by teasing users
Also, after_sign_in_path_for(resource) should be in application_controller. You'll need a column in users to specify the role, and your method will looks like something like this:
def after_sign_in_path_for(resource)
stored_location_for(resource) || (resource.role.professor? ? professor_dashboard_url : user_dashboard_url(resource))
end

application with multiple "accounts", each containing multiple users

I am trying to build an application with multiple "accounts", each containing multiple users.
I've started with the gem Devise to create user authentication, and I've created Accounts and Preferences MVC's with scaffolding.
The Account model has_one Preferences, and has_many Users
The User model and Preferences model belongs_to my Account model
I've tested these relationships in the console and they seem to work..
What I would like to do, is make sure that when users are logged in, they can only view records associated with their account. From what I've seen, the current_user helper can be used, but I would like to use something like a "current_account".
1. First question is, is there a resource, Gem, method that can help me to create this current_account variable?
2. Second question would be, what do I need to put in my View for this to work? For instance, if a user wants to update his Preferences associated with his account, how would we call this in the _form partial, would if be something like this?
<%= #account.preference.opt_in %>
and if they wanted to see all of the users in the account, would it be something like this?
<% #customer.user.each do |account| %>
<%= user.email %>
<% end %>
Please let me know if I'm overlooking anything major, I've been working on this the last few days.
If I understand correctly, you are looking for a multi-tenancy solution. If so, you don't need to come up with your own solution, as there are well established patterns out there.
You can try the Milia gem, which fits in nicely with devise.

How can I have the user only add their #name instead of entire Twitter link in a url_field?

In my Rails app I have a user model (Devise) with url_field for Twitter.
Right now I have this in my show page:
<%= link_to #deal.user.company_twitter, #deal.user.company_twitter, :class => "comp_twitter" %>
It shows the entire link in the show page (even http://), that's because my url_field makes the user add "http://" or it won't validate the link.
I want the user to only add their "#name" instead of the whole Twitter link when creating their profile. I would also want to show only the #name instead of the Twitter link in the "show" page. How can I do this?
Simply don't use an url_field, but a regular string database field, like twitter_username. When signing up, let the user enter their username, e.g. foo.
For getting the real URL to the Twitter account, create a new method in your user.rb model:
def twitter_url
"http://twitter.com/#{self.twitter_username}"
end
The advantage is that at this point, in your model, you can include a custom validation that would check if this URL really exists after the user has submitted their twitter_username.
Finally, use that in your view instead of just the URL:
<%= link_to "##{#user.twitter_username}", #user.twitter_url %>
This would render:
#foo

Rails and SEF URLs: Changing the key used in link_to to use a different field then the primary key

In my Rails 3 app, I have a model called User with id and username, both are indexed and unique. Somewhere in some views I have following:
<%= link_to 'Show this user', user %>
That creates a link like this:
Show this user
where that horrible number is the id (primary key). Now, for the SEFness of the site, I would like to use the username instead of the id wherever I use link_to "...", user, but only for that User model. Adding parameters to the link_to does not help, because I already have it in many places (and I do not want to have to add another parameter everywhere all the time).
How can I override the behavior of the link_to helper only for one model?
Here is a complete answer to this question, as I deducted from the accepted answer. I added following to my User model:
def to_param # overridden to use username as id, and not the id. More SEF.
username
end
def self.find(id)
#user = User.find_by_id(id)
#user = User.find_by_username(id) if #user == nil
throw ActiveRecord.RecordNotFound.new if #user == nil
#user
end
This now makes all links generated with link_to use the username, while the find will try both the id and the username, making it also backward compatible.
Thought someone as new as me to Rails would find this useful.
Not sure of what I'm saying, but overriding #to_param in your model may be what you're looking for.

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