#314 Pretty URLs with FriendlyId
If you are tired of model ids in the URL, overriding to_param can only get you so far. The friendly_id plugin can help by making it easy to generate a URL slug and maintain a history.
- Download:
- source code
- mp4
- m4v
- webm
- ogv
Very interesting idea. I can see this being useful on user models with an email address or user name. Does friendly_id assume the name column is unique?
If you don't use slugs, then yes. This is precisely the "user name or email" example that you mention. Otherwise if you use slugs, you can use a value that's not necessarily unique like a title or name, and FriendlyId will automatically append numbers at the end of the slug when necessary to keep it unique.
Somebody knows if this is also compatible with CouchRest Model? (Couchdb)
No, only Active Record.
I often use FriendlyId in combination with a UUID column. This way, the guessing of further resources is much harder (cp. /foo/1 → /foo/2 with random, 32-digit identifiers). Of course you will still need a authorization mechanism...
Ryan,
You forgot to add
gem install friendly_id in the web notes
Is friendly_id SEO friendly?
I read link about rails-sexy-url for SEO.
http://www.bingocardcreator.com/articles/rails-seo-tips.htm#sexy-urls
Will friendly_id help us about SEO?
Sure it will. It is crucial for SEO to include search terms in the URL. So if you want to sell a product and you include the title in the URL instead of the id, it is much more likely that people will find this page when they google the product name.
Clemens
rails-trouble.com
I have a question regarding the history module.
Let's say that I create a post titled "Hello" and get the url
site.com/post/hello
but I decide to update the title to "Hello World" and I now have an updated URLsite.com/post/hello-world
.I use the history module to redirect from the old url to the updated one.
What happens if I try to create a new post with the old title? (Imagine that I have
validates :title, :uniqueness=> true
)Will ActiveRecord take friendly_id's historic slugs into consideration when validating future user inputs?
Yes. History is taken into account for validating unique slugs. This can also create a problem if users can change titles or names. They could theoretically reserve various usernames.
thankyou, I've actually been using this gem since the early days of development but did not know about History module until today. It's a neat feature.
It's actually new in version 4.0, previously it was enabled by default.
Is there any way i could use a combination of two fields to use the Slug?
for instance I have
and would like to add the first name of the user field -
:fname
to make it more unique.Yup, you can pass friendly_id a method
Thanks for that Mike, works a treat :)
Tried to follow this tutorial off a scaffold using rspec
Threw the following failure:
Quick fix I'm using... but if there is a more eloquent way I'd love to know...
Nevermind - just realized my issue had to do with something else. I'd delete my comment above but I don't have the ability
What was the other thing? I'm having the same issue.
I'm seeing:
Does FriendlyId work with nested resources?
did you find any good resources ?
I'm having the same issue here; can't figure out what I'm doing wrong. Have
resources :shows do
resources :episodes
end
And am trying to get to a link such as
:slide_url => show_episode_path(@show, @episode)
But for some reason the episode id isn't being added:
started GET "/shows/the-first-show/episodes/" for 127.0.0.1 at 2013-09-12 00:54:30 -0400
I have an app that is using acts_as_tree and what I would like is for my url's on my page models to not include the model name, can friendly_id help with this?
Is there anyway for me to use both friendly_id and the record id? I'd like to use friendly_id in my consumer-facing URLs, but the record id in my admin URLs... is there anyway to do that?
EDIT: Ok, I see that I can manually change the parameter in the URL, and it still works as expected.. but my path helpers all use the friendly id, e.g.:
edit_admin_user_path(user.id) #=> /users/some-friendly-id/edit
How can I get this?
Nevermind... just figured out that I was passing in
user
instead ofuser.id
.History option is enabled for my model and when I update the slug, friendly_id_slugs slug is not getting updated. so when I create new record with the same title it is throwing uniquness error.. Please help me on this...
Anyone know if there's a way to remove the :id version of the url from working? For example, if someone visits
/users/:username
it brings them to that user's profile. If they visit/users/1
it brings them to the user with :id of 1. Is there a way to prevent this?Thanks!
Yes you can overwrite the find_one method. Look at https://github.com/norman/friendly_id/issues/197 for an example.
But make sure that you are starting with the right finder method, eg history uses another one.
I have a question about the history feature.
I implemented it on one of my models, but it seems that it only keeps a history of the original slug, even after every edit. Is this how it's supposed to work?
Say I have a title of "Hello World" which generates a slug "hello-world"
If I edit this to "Hello World 2" and then eventually to "Hello World 3", am I supposed to have all 3 history changes, or just the original?
hello-world - original works
hello-world-2 - doesn't work <-- does this not get stored?
hello-world-3 - latest works
Thanks!
I'm seeing this same issue. Only the original slug is saved in history. I had assumed that all past slugs would be recorded. Seems less than ideal.
Looks like the latest version has a fix for this:
https://github.com/norman/friendly_id/issues/224
Thanks for the tip!
I am trying to use friendly_id with ActiveAdmin and I am sending friendly_id in my model a function
showdate_as_url
to get this to work I have this in my routes:
All works great outside of active admin, but in the active admin scope this date based url dose not work. I have tried setting the to_param back to id with a before filter in active admin - which works again, but then leaving active admin my friendly_id does not work any more.
Any ideas anyone?
I ended up doing this, doesn't look elegant, but it works.
As far as SEO is concerned, is there a difference between mysite.com\records\1-my-record vs mysite.com\records\my-record ?
If the answer is no, this seems like a lot of work to remove a leading #?
Probably not any difference- but SEO isn't everything. If you're reading off a URL to a person, saying "one dash my..." doesn't make much sense.
Has anyone tried to build associations with friedly_id and having difficulties, and if so, how do you go about solving it?
Based on that i
Has anyone one tried to build associations, with nested resource with frienly_id and having difficulties, and if so, how did you go about solving it?
I've tried everything I could think of to get post requests to work on edit action for user_detail. I've also tried not nesting the the user_detail, still no cigar!
Yes - how does it work with nested resources?
I've used it do have resources like:
/orgaizations/lend-a-hand/needs/pillows
Works nicely.
Does slug support traditional Chinese character?
here is the code
Let's say I create an new article with Chinese title.
It seems friendlyId is unable to save the Chinese title in slug column. So the URL still show the id of the article.
If I do this
It works but I have to ensure no duplicate name.
Any way to solve this?
have you solved this? I have the same problem with Korean language.
I've got my app setup to have multiple organizations, and multiple pages per organization (identified via the subdomain). Is it possible to have FriendlyId check for uniqueness only on a per-user basis?
Thus that there can be multiple /home pages, but are unique within a given organization.
Very nice video :)
But I must convert ~ 1.300.000 records on my database.
Know you faster metod that this ?
Thanks for reply.
Use rake task. It's great for doing this kind of job.
Is there a way to disable friendly ID in development mode?
What about using a different column than "slug", I see some reference to setting configuration options in the documentation, but I have no idea how.
Any idea how to have it so that the controller is not being seen in the url?
For example, i got it working with this:
https://www.domain.com/users/jimmy-hendricks
I like it to be this instead:
https://www.domain.com/jimmy-hendricks
Just like facebook/twitter did in theirs.
Thanks
I know this is 6 months old, but:
You'll want to handle this in your routes.rb file.
Something like:
get ":id" => 'users#show', as: :name_your_path
The history feature isn't working for me. I've done exactly as the tutorial has done but I get the following error when I try accessing the old url after editing it to a new url:
"Render and/or redirect were called multiple times in this action. Please note that you may only call render OR redirect, and at most once per action. Also note that neither redirect nor render terminate execution of the action, so if you want to exit an action after redirecting, you need to do something like "redirect_to(...) and return"."
Friendly_ID was working for me before I edited by After editing the _add_slug_to_users.rb file then ran the command User.find_each(&:save)
For each user, I got an error that was similar to:
User Load (0.3ms) SELECT "users".* FROM "users" WHERE ("slug" = 'carleton-howell' OR "slug" LIKE 'carleton-howell--%'ESCAPE '\') AND (id <> 2) ORDER BY LENGTH("slug") DESC, "slug" DESC LIMIT 1
User Exists (0.2ms) SELECT 1 AS one FROM "users" WHERE (LOWER("users"."email") = LOWER('example-1@railstutorial.org') AND "users"."id" != 2) LIMIT 1
(0.1ms) rollback transaction
Found the issue which was that it an edit needs to be made for it to work with existing entries on Heroku :)
After watching this Railscast and researching a bunch of other articles online, I figured out a way to do it with all of the upsides and none of the downsides–you get a pretty URL with both ID and name, parameterized, fully functional in controllers/views, without having to add a slug field to the database or anywhere else. Pretty efficient, I think. This is it if anyone is interested:
https://gist.github.com/rceee/5021916
Thanks for this! Not understanding how exactly this worked, I wasn't able to get your code to work in my app. I found this post to be helpful. Any comments on it in terms of simplicity and/or limitations?
Question! I am trying to eliminate the use of regular model IDs to access my pages. IE, right now, you can still go events/1, as opposed to just the custom (for me it's a hash) such as events/12k5s
I want to eliminate any possible guessing of other pages. How would I eliminate the old option?
Ryan says that actually friendly_id history doesn't work for old records but only for new ones.
That is not true anymore.
You just need to create friendly_id table before adding slug column and save your object.
Like this:
and everything will work fine as expected.
I also suggest, if you don't want to loose old urls, to execute this code after adding frindly_id_slugs and before adding column to articles
current_timestamp if you are using postgresql
When you guys move on to Rails 4, use
puts "friendly_id :foo, use: [:slugged, :finders]"
puts "friendly_id :foo, use: :slugged"
Thank you! This was the easiest way to ensure that people couldn't use a brute force attack to find every user ID on my site.
If you are going to use :histroy with friendly_id 5 you should consider the new change in slugs' regenrations. As version 5 the slugs are not updated on save unless you set them to nill first.
I would recommend to override the should_generate_new_friendly_id? method, because it will only change the slug when ONLY needs to do it.
Like the URL to this very page, I want to have urls like this:
So I use friendly_id like so:
Now, since friendly id generates the slug before the object is saved I end up with an url like so (Please note the missing id in the URL):
Now while this is not too bad as such. As soon as I save another Product called "Table Lamp", I will get an URL like this:
So my question is, how can I make sure, friendly ID creates the slug containing the ID as well.