I have a RoR app. And in app users can create posts. I've connected Posts table in my routes.rb
via resources :posts
. And right now - link to created post look like: http://mysitename.com/posts/1
(where 1 is post number).
What i want to do, is to make rails generate link to post. So users didn't see how much posts I have in my DB. And as result it must look like http://mysitename.com/post/generatedlink
. It must generate, for example post theme.
For start, we must create link
column in Posts table. And make it to generate something like that:
@post.link = @post.theme.parameterize.underscore
But I don't understand, where to put this code.
And the next problem is: "How to replace post/1
for @post.link
?"
Hope, I make my self clear. If you'll say I can provide information, what is needed to resolve my question.
UPDATE
What I did after @SteveTurczyn advise.
I've created new column, called random_link
as a string
.
I didn't touch my routes.rb
:
resources :posts
My post.rb
(post model) look like this:
after_validation :add_link
def add_link
self.random_link = self.theme.to_slug_param
# to_slug_param it's a gem for translating from other language into english
end
def to_param
random_link
end
I don't have find method. My posts_controller.rb
look like this:
def show
@post = Post.find_by_random_link(params[:id])
right_menu_posts
random_link_to_other_post(@post)
end
private
def random_link_to_other_post(post)
random_post = Post.where.not(id: post.id)
@random_post = random_post.sort_by {rand}.first
end
def right_menu_posts
@posts_for_video_in_right_menu = Post.where(video: true)
end
And html.erb:
<%= @post.theme %>
<%= @post.content %>
<% for post in @random_post %>
<%= link_to post %>
<% end %>
<% for post in @posts_for_video_in_right_menu %>
<%= link_to post %>
<% end %>
And on a main page (where i have a list of posts) a keep getting an error: NoMethodError in Home#index private method 'to_param' called for #<Post:0x007fae3096bf78>
.
The technique is referred to as slugifying
and you need to do three things...
(1) create a new field called slug
in your posts
table.
(2) add this code to your Post
model...
after_validation :generate_slug
private
def generate_slug
self.slug = theme.parameterize.underscore
end
public
def to_param
slug
end
(3) finally, in your controllers where you have find_post
methods, rewrite it to be...
def find_post
Post.find_by_slug(params[:id])
end
The to_param
method in the model is how things like post_path(@post)
build the url... the to_param
if not replaced substituted the id
field but by writing your own to_param
method you can ensure that the slug
field is substituted instead.
Ensure that 'to_param' is a public method! Don't put it in the private part of your model. You can do that by putting public
immediately before the to_param
method. You should then put private
after the method definition if subsequent methods are to be private.