Dynamically generated routes/URLs from Model fields in Rails 3 - ruby-on-rails

Describing the following scenario:
A user signs up and provides a firstName (john) and a lastName (jagger)
A route is automatically generated for the default domain i.e. www.asdasd.com/john.doe
A guest visits www.asdasd.com/john.doe and is taken to the 'view' action of the controller for this user
Is something like this possible? I do not know how to form something like this in routes.rb
Thanks!

Take a look at friendly_id. It doesnt generate routes dynamically but instead it lets u use the name as the ID.

Rails provides method in your models called to_param. This method returns URL for your model instance. For example: you have model User user = User.find_by_name('John')
user_path(user) # => /users/1
You can ovverride to_param method to return URL such as:
/users/John
Here you can read more:
http://apidock.com/rails/ActiveRecord/Base/to_param

Related

Ruby on Rails - Setting different names for url

I am completely new to Rails and I have a database that links to a certain page depending on the user's search but it will always give me the id.
For example if a user searches, I will get, "localhost:3000/fruit/1" instead of "localhost:3000/fruit/apple". Does anyone know how to switch the url from an id to name?
You need to define a 'to_param' method in the model you are generating a link for, e.g.
class Fruit < ActiveRecord:Base
def to_param
name
end
end
Then in your controller you need to change the find for the show action to find by the attribute you are using in your 'to_param' method, e.g.
#fruit = Fruit.find_by(name: params[:id])
See http://api.rubyonrails.org/classes/ActiveRecord/Integration.html#method-i-to_param for additional details

Rails: Prevent id conflict with a method

I am using string as id in routes (e.g. resource/:id ) but id can also be 'new' (a method in my Controller) which rather than showing the resource with id=new, directs to create new resource. How can I restrict users from choosing id=new while creating new resource?
I can think of three solutions where you can set string instead of id
First: set a combination of the id and the attribute_name, add
in your model
def to_param
return [self.id, self.attr_name].join('-')
end
Second: prevent the user of adding any action method in your controller (that's safer than restricting only the "new" method, you may add other get methods in the future)
validates :attr_name, exclusion: { in: YourController.action_methods.to_a }
Third:
use friendly_id gem
Try to use exclusion validation in the model, http://guides.rubyonrails.org/active_record_validations.html#exclusion
In config.rb, change your route to:
resources :resources
You'll get the routes you need. I have a feeling you'll soon need some of the others that come with it, like create and edit.
Edit: to make life easier, in your model:
def to_param
return self.my_string_id
end
Where my_string_id is the string you are using in the URL as the identifier. That will make the URL use that as the :id param instead of the numeric ID.
See: http://guides.rubyonrails.org/routing.html#resource-routing-the-rails-default

Rails - how to set up path to action by own criteria (not ID)

When I have a path like this:
user_messages_path(current_user)
it generates following URL:
users/1/listings
I am storing in database users' unique codes, so I wouldn't like to display URLs like
users/ID/listings
but more like
users/CODE/listings
How I need to update routes for using paths with users' codes?
Thanks
user_messages_path(current_user)
is a shortcut for:
user_messages_path(current_user.to_param)
which generally does:
user_messages_path(current_user.id)
You can:
pass any string you want: user_messages_path('foo')
or override to_param in your model
Just beware to update your code responsible to retrieve the object from the params.
in user.rb
def to_param
uuid # or whatever attribute you want to use instead of the id
end
in the controllers instead of User.find(params[:id]):
User.find_by_uuid!(params[:id]) # adjust to the attribute name used in to_param
You can use a custom route, something like the following.
get 'users/:code/:listings' => 'listings#index', as: :user_messages
Then in your params there key :code will return that part of the url e.g. params[:code]
In your controller you could use the following
Rails 3.2
User.find_by_code(params[:code])
Rails 4
User.where(code: params[:code])

Is there any way to get the route scope from a Rails controller

So I have a polymorphic controller in rails, and my question is, is there any way for me to get the scope of the requester. for example, the rout is /users/1/messages, the request goes to the MessagesController, in that controller, is there any way to get the users portion of the route? or in this case it could also be admin or something else.
I cant just set up an if statement structure, because in this case, `POST '/users/1/messages' is a message going to a user, perhaps from an admin.
normally you should have put a type field (e.g. messagable_type), a message instance has the corresponding class (e.g. User) and the id field (e.g. messagable_id) will have the point to the id of the user. so you can ask a message instance:
message.messagable
=> user
it will return the user instance.
If you have a url such as: /users/1/messages and you want use this:
def load_messagable
resource, id = request.path.split('/')[1,2]
#messagable = resource.singularize.classify.constantize.find(id)
end
This is the solution given by Ryan Bates in this episode: http://railscasts.com/episodes/154

Permalinks with Ruby on Rails (dynamic routes)

I am currently developing a blogging system with Ruby on Rails and want the user to define his "permalinks" for static pages or blog posts, meaning:
the user should be able to set the page name, eg. "test-article" (that should be available via /posts/test-article) - how would I realize this in the rails applications and the routing file?
for user-friendly permalinks you can use gem 'has_permalink'. For more details http://haspermalink.org
Modifying the to_param method in the Model indeed is required/convenient, like the others said already:
def to_param
pagename.parameterize
end
But in order to find the posts you also need to change the Controller, since the default Post.find methods searches for ID and not pagename. For the show action you'd need something like this:
def show
#post = Post.where(:pagename => params[:id]).first
end
Same goes for the other action methods.
You routing rules can stay the same as for regular routes with an ID number.
I personally prefer to do it this way:
Put the following in your Post model (stick it at the bottom before the closing 'end' tag)
def to_param
permalink
end
def permalink
"#{id}-#{title.parameterize}"
end
That's it. You don't need to change any of the find_by methods. This gives you URL's of the form "123-title-of-post".
You can use the friendly_id gem. There are no special controller changes required. Simple add an attribute for example slug to your model..for more details check out the github repo of the gem.
The #63 and #117 episodes of railscasts might help you. Also check out the resources there.
You should have seolink or permalink attribute in pages' or posts' objects. Then you'd just use to_param method for your post or page model that would return that attribute.
to_param method is used in *_path methods when you pass them an object.
So if your post has title "foo bar" and seolink "baz-quux", you define a to_param method in model like this:
def to_param
seolink
end
Then when you do something like post_path(#post) you'll get the /posts/baz-quux or any other relevant url that you have configured in config/routes.rb file (my example applies to resourceful urls). In the show action of your controller you'll just have to find_by_seolink instead of find[_by_id].

Resources