Using both id and slug when building paths - ruby-on-rails

I have a model, let's say user, with both an id and a slug. I'd like to be able to generate a url using user_path(#user) that contains both the id and slug.
I know that user_path will use to_param method for the parameter it puts at the end of the url, but is there a way to use 2 (or more parameters) and get something like this:
http://domain.com/users/id/slug
Thanks!

Friendly-id is a great way to generate permalinks. It also offers pretty good customization options.

Did you try this in your model?
def to_param
"#{id}-#{slug)"
end

Related

Getting a username from url with params

I seem to find it difficult to get the username from a url with params, but works when finding IDs.
To get the id from this url: www.foo.com/users/1/post/new, you'd use:
User.find(params[:id]) # same as User.find(1)
I thought I could do the same, based on the docs, for: www.foo.com/users/joe/post/new
User.find_by(name: params[:name])
How to grab the user's name from url with params using the find or find_by method? Thanks
In your User model, override the to_param method like this:
def to_param
name
end
With this code, you're overriding the ActiveRecord default behaviour, so when you link to a User, it will use the name for the parameter instead of id.
Also, I recommend you to take a look at the friendly_id gem as well, using which you can achieve this goal.

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])

Rails path tags conflicting, want urls like /post/some-title but when editing/updating use the ID not title

Having some issues, I want my urls for the show action to be like:
/post/some-title
i.e. so wherever I reference the show_post_path tag (or whatever it is) it should make that url.
BUT, when editing/updating I want to do this using the ID of the post ie.
/post/234/edit
How can I achieve this, it seems what I am doing is messing things up because I used:
def to_param
#{title}"
end
In my post model.
I always add an attribute called 'slug' to posts and it acts as a slug for that post.
Then just find your posts with Post.find_by_slug(params[:id]).
You can even make it translatable.
Create a to_param method. For example:
def to_param
"#{self[:id]}-#{title.gsub(/[^a-z0-9]+/i, '-')}"
end
Assuming the field you wanted to be in the URL is title, then your posts' URLs would be like /posts/1-this-is-a-post.

Human readable URL causes a problem in Ruby on Rails

I have a basic CRUD with "Company" model. To make the company name show up, I did
def to_param
name.parameterize
end
Then I accessed http://localhost:3000/companies/american-express which runs show action in the companies controller.
Obviously this doesn't work because the show method is as following:
def show
#company = Company.find_by_id(params[:id])
end
The params[:id] is american-express. This string is not stored anywhere.
Do I need to store the short string (i.e., "american-express") in the database when I save the record? Or is there any way to retrieve the company data without saving the string in the database?
Send the ID with the parameterized value;
def to_param
new_record? ? super : "#{id}-#{name}"
end
And when you collect the data in the show method, you can use the whole parameter;
def show
#company = Company.find("12-american-express"); // equals to find(12)
end
There's also a plugin called permalink_fu, which you can read more about here.
I think friendly_id is more usable.
I do something similar with the Category model in my blog software. If you can guarantee that the only conversion the parameterize method is doing to your company names is replacing space characters with dashes then you can simply do the inverse:
def show
#company = Company.find_by_name(params[:id].gsub(/-/, ' '))
end
Try permalink_fu plugin, which creates SEO friendly URLs in rails
http://github.com/technoweenie/permalink_fu
cheers
sameera
I would suggest the friendly_id gem also.
It gives you the flexibility to use persited permalink slugs, also strip diacritics, convert to full ASCII etc.
Basically it makes your life a lot easier, and you get "true" permalinks (no to_param and the id workaround needed) with little effort.
Oh and did i mention that the permalinks are also versioned, so you can make old outdated permalinks to redirect to the current one? :)

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