Redirect_to with variable fir destination link - ruby-on-rails

I have a site where you can enter the name of a business after the domain and if it exists it is displayed. E.g. www.mysite.com/BUSINESS_NAME. I do this through a route:
match ':id' => 'businesses#show', :via => [:get]
It essentially means that a new custom URL is created for each new business that signs up. At the moment each time a new business is created (create form submitted) I am redirected to something like
http://localhost:3000/businesses/42
This is expected as I use:
redirect_to #business
How am I able to redirect to the newly created business and make the URL look like
www.mysite.com/BUSINESS_NAME instead of http://localhost:3000/businesses/42
I thought about making logic in the show action that would work for either URL request but it doesn't look very nice to the end user seeing an ID - I am sure there is something in Rails to mask this sort of information and still pass the ID parameter.
Thanks in advance for any help.

Yes, you can make the url as user friendly.So user can see the simple url that dosen't use the id.
There is a gem in rails that easily solve your problem.
Friendly_id

Related

How to create referral link like launchrock in ruby on rails?

I want to create referral links like.
www.abc.com/1234
www.abc.com/4345
Where number are the referral codes which will be unique for every user. I am sure this can be done in ruby on rails with some routes configuration. Means where the request will be routed. Which controller? which action? How to get value of unique code.
ps: launchrock is using referral links like this.
You can use this structure with route matching but you would need to have the referral codes match a specific pattern. If, for example, they matched the format of 3 letters followed by three numbers, you could put the following your routes file:
match '/:referrer_id' => 'app#index', :constraints => {:referrer_id => /[a-zA-Z]{3}[0-9]{3}/}
The reference to app#index should be changed to the controller in which you handle referrals and you can access the referrer_id through params[:referrer_id].
Certainly have a look at the link referenced in Markus' answer for suggestions on how to generate the tokens.
I have a link in my bookmarks with regard to token generation: http://blog.logeek.fr/2009/7/2/creating-small-unique-tokens-in-ruby
In your application you will need to store the individual tokens in the user table. Controller and action are up to you and for the routes you could go with something like www.abc.com/referral?123456.
routes.rb
match "/referral/:ref" => "controller#action"
access in controller with:
params[:ref]

Ruby on Rails: Custom actions

I'm new to rails, so I'll just explain my situation to you:
I've got a User Model and a UsersController. Users log in with their email address and a password. Special users can invite other users, by typing the email address of the invitee into a form and hitting submit. The invited user then receives a mail containing a link to activate his account, by entering his password for the first time.
Here's the problem:
The "invitation" form is mapped to the create action of my UsersController atm. But what do I map the "activation" form to?
Is it possible for me to define a custom action "activate" or something that can be accessed like /users/3/activate (of course, there should be some authentication token here too...) and would activate the user with id 3?
I've found some stuff on custom actions, but I don't quite get the hang of it yet.
Thx for any help
You probably have something like this in your routes file. (If not, please post that.)
resources :users
If you want to add a custom action that acts on a single User, you can add that as a :member like this.
resources :users do
member do
get :activate
end
end
Note that using a get for something that modifies data is a bit wrong, but you're talking about hitting this from a link in an email.
As you play with routes don't forget that rake routes will show you all of the routes that you currently have available to you.

Rails routes creating additional info in URL

Say if I have a model called 'deliver' and I am using the default URL route of:
# Install the default routes as the lowest priority.
map.connect ':controller/:action/:id'
map.connect ':controller/:action/:id.:format'
So the deliver URL would be:
http://localhost:3000/deliver/123
What I am trying to work out, is how to use another field from the database alongside or instead of the ID.
For example. If I have a field in the create view called 'deliveraddress', how do I put that into the routes?
So I can have something link this:
http://localhost:3000/deliver/deliveraddress
Thanks,
Danny
Since it sounds from your comments like you're trying to obfuscate the ID in your URL, I would suggest that you look at this question, which was asked a few days ago.
Obfuscating ids in Rails app
First of all, the url "http://localhost:3000/deliver/123" matches either default routing rule. However, only after you declared an "resource" it will generate such a RESTful URL.
In your case, just implement the "to_param" method of Deliver model:
class Deliver < ActiveRecord::Base
def to_param
return self.deliveraddress
end
end
it will generate the url you want by calling url_for method, like link_to #deliver
Do not forget to make sure you have unique deliver addresses in your database so you will never find duplicated records with one address.
After that, you need to update the finder methods in actions:
def show
#deliver = Deliver.find_by_deliver_address!(params[:id])
end
Hope this answer will be useful.

How do you redirect to an external website with rails?

I want links that when hovered over you see the link to look something like this:
http://www.website.com/redirct_to=linkID2
(maybe not exactly like that but try to get the idea)
I have a form area in my blog that I can input a website url but I want to make it redirect_to an external website when it shows the post.
redirect_to "https://website.com"
should do it as long as protocol is included. For added flexibility, you can parse it with URI to ensure that all fields are correct. You might want to URI.encode/URI.decode
redirect_to "https://website.com", allow_other_host: true
Create a new model, for example called Link, to store the URLs you want to redirect to.
Then generate a new controller (you can use scaffold to generate controller and model at the same time) and change the show action in order to fetch the record with given ID and redirect_to #link.url.
If you don't want to use the #show action for this step, create a new action do handle the redirect (for example goto, redirect...).
redirect_to isn't available in views or is not a helper method, be sure to use it in your controllersbut if you really want to redirect from view, use the javascript solution
window.location.href=<%= post.link_url %>

In RESTful design, what's the best way to support different kinds of GETs?

In a current project I need to support finding a User by login credentials and also by email address. I know that in RESTful design you use a GET to find resources. In Rails...
GET /users # => UsersController.index -- find all the users
GET /users/1 # => UsersController.show -- find a particular user
But I also need something akin to...
GET /users?username=joe&password=mysterio
GET /users?email=foo#bar.com
Is it conventional to add additional routes and actions beyond index and show?
Or is it more common to put conditional logic in the show action to look at the params and detect whether we're finding by one thing or another?
There's a similar issue with PUT requests. In one case I need to set a User to be "active" (user.active = true), and in another case I just need to do a general form-based editing operation.
Thanks guys. Eventually I'm going to figure out this REST stuff.
I'm new to SO, so I can't comment, but the checked green answer is not RESTful.
In a RESTful world, your controller grabs all the parameters and passes it to the model layer for processing. Typically, you shouldn't create another action.
Instead, you should do do something like this:
def show
#user = User.find_by_login_or_email(params[:user])
... #rest of your action
end
Your model can have a method like this:
class User
self.find_by_login_or_email(params)
return find_by_login(params[:login]) unless params[:login].blank?
return find_by_email(params[:email]) unless params[:email].blank?
nil #both were blank
end
end
Your view could look like this:
<%= f.text_field :user, :email %>
or
<%= f.text_field :user, :login %>
Note: untested code, so may be buggy...but the general line of thinking is usually not to create new actions for every one-off rule. Instead, look to see if you can push the logic into the models. If your controllers start to have too many non-standard actions, then it may be time to re-evaluate your domain modeling, and perhaps it's refactor the actions to some new models.
ps: you should never pass in passwords via a GET like that
I don't know how much of this is convention, but this is what I would do. I
would add another action, as long as it's specifically related to that
resource. In your example, show is a find by userid, so it makes sense as
another action on UsersController. You can turn it into a sentence that makes
sense, "get me the user with this email address"
For the other one, GET /users?username=joe&password=mysterio, I would do
that as another resource. I assume you're thinking that action would log in
the user if the password were correct. The verb GET doesn't make sense in that
context.
You probably want a 'session' resource (BTW, this is how restful_auth works).
So you would say "create me a session for this user", or something like POST
/sessions where the body of the post is the username & password for the user.
This also has the good side effect of not saving the password in the history
or letting someone capture it on the HTTP proxy.
So your controller code would look something like this:
class UsersController < ActionController::Base
def show
#user = User.find_by_id(params[:id])
# etc ...
end
def show_by_email
#user = User.find_by_email(params[:email)
end
end
class SessionsController < ActionController::Base
def create
# ... validate user credentials, set a cookie or somehow track that the
# user is logged in to be able to authenticate in other controllers
end
end
You would set up your routes like this:
map.connect "/users/byemail", :controller => "users", :action => "show_by_email", :conditions => { :method => :get }
map.resources :users
map.resources :sessions
That will get you URLs like /users/byemail?email=foo#example.com. There are
issues with encoding the email directly in the URL path, rails sees the '.com'
at the end and by default translates that into the :format. There's probably a
way around it, but this is what I had working.
Also like cletus says, there are ways to make your route match based on the format of the parts of the URL, like all numbers or alphanumeric, but I don't know off hand how to make that work with the dots in the url.
The first thing you can do is make your GETs as smart as possible. In your example, this can be handled programmatically. The argument can be processed this way:
Is a number? It's a userid;
Has a # in it? It's an email;
Otherwise? It's a username.
But I assume that you're not just talking about this example and want something to handle the general case rather than just this specific one.
There are basically two ways of dealing with this:
Add extra path information eg /users/email/me#here.com, /users/name/cletus; or
Be more specific in your "top-level" URL eg /user-by-email/me#here.com, /user-by-name/cletus.
I would handle it programmatically if you can.
Regarding the "ByEmail" request, have you considered creating a new email resource.
GET /email/foo_at_bar_dot_com
The response could contain a link to the related user.
I see so many people trying to apply RESTful design principles to their URL structure and then mapping those urls to procedural handler code. e.g. GET = Show, or is it GET = Index or ShowByEmail. By doing this you are really just pretending to do a RESTful design and then trying to create a mapping between a resource oriented URL space and procedurally oriented implementation. That is really hard to do and the procedural nature keeps leaking out into the URLs.
Resource oriented design often requires a very different way of thinking about problems that we are used to and unfortunately many of the frameworks out there keep sucking us back into the RPC model.
You might be able to set up different routes for different tasks. So for this case you could have one route to a method in UserControll dedecated to getting a user by email, and another for getting the information by credentials.

Resources