Permalink-fu - Display URL differently - ruby-on-rails

I'm using Ruby on Rails 2.3.8 and permalink-fu plugin. I would like to know how to generate permalinks like this: /posts/44444/this-is-the-title instead of /posts/44444-this-is-the-title
I've tried modifying my Post model as follows:
has_permalink :title, :update => true
def to_param
"#{permalink}"
end
And my routes file as follows:
map.show "/posts/:id/:permalink", :controller => 'posts', :action => 'show'
Then, if I manually type the url with that format, it will work, but if I make a link out of a post in my view as follows, it wont generate the link formatted that way:
<%= link_to p.title, p %>
Where p represents a post.
How can I do so when I call a post like that, I get a permalink formatted as /posts/:id/:permalink instead of /posts/:id-:permalink?

Try this one...
on model:
def to_params
[self.id, self.permalink]
end
on views:
<%= link_to p.title, show_path(p) %>

Related

How to include an image as link for datagrid gem?

I'm trying to implement the datagrid gem in Rails 4 but am not sure how to include a link in the Grid class.
I currently have for the UsersGrid class:
class UsersGrid
include Datagrid
scope do
User.order("users.created_at desc")
end
column(:avatar) do |user|
if user.avatar?
link_to ActionController::Base.helpers.image_tag(user.avatar.url, alt: "Profile"), user_path(user)
else
link_to ActionController::Base.helpers.image_tag("profile.gif", alt: "Profile"), user_path(user)
end
end
end
This generates the following error message referring to the link_to line :
undefined method 'user_path' for #<ActionView::Base:0x007f821d3115b8>
How should I adjust the code to make the link work?
Additional information:
View page:
<%= datagrid_form_for #grid, :method => :get, :url => users_path %>
<%= will_paginate(#grid.assets) %>
<%= datagrid_table(#grid) %>
<%= will_paginate(#grid.assets) %>
Controller method:
def index
#grid = UsersGrid.new(params[:users_grid]) do |scope|
scope.where(admin: false).page(params[:page]).per_page(30)
end
#grid.assets
end
I found the solution: I had to add :html => true to column(:avatar, :html => true). This way html code such as link_to work and I also no longer needed ActionController::Base.helpers to get access to the image_tage method.
It sounds like you don't have a route configured for a user resource in routes.rb.
To verify and see what path helpers are available, go to command line, navigate to the project directory, and type in rake routes. If properly configured you should see something like:
user GET /users/:id/(.:format) users#show
On the far left of the example above is the "Name" which is used to generate the path helper. So in the example above the name is "user" and Rails will automatically generate the helper user_path which accepts an argument that is a user's id. So user_path(1) is a helper for /users/1. If you pass in a User object (like you were in your example) it will just get the id from the User in the background e.g.) user_path(current_user) will find the id of current_user and return /users/1.
Read more about rake routes here.
Anyways, if user is missing from your routes.rb file you could add something like this to routes.rb:
get '/users/:id', :to => 'users#show', :as => :user
Keep in mind you likely already have something for the users resource, so you might be able to make an easier/cleaner change depending on how you have configured the file.

How do I pass more than one parameter into a link_to call where I specify controller and action?

I am using a link_to to initiate a controller method that requires two parameters in order to perform the steps I need it to take. I can't seem to get the syntax right, and I'm wondering if it is because you can't pass more than one parameter in using this particular syntax. Here is what I have so far:
<%= link_to 'Select',
{controller: 'groups',
action: 'associate_subgroup_with_org',
organization_id: organization.id,
subgroup_id: #activity.group.id},
class: 'button' %>
def associate_subgroup_with_org
#organization = Group.find(params[:organization_id])
#subgroup = Group.find(params[:subgroup_id])
#subgroup.parent_group_id = #organization.id
respond_to do |format|
format.js
end
end
The link is not working and I never enter my controller action associate_subgroup_with_org. Can someone help me get the syntax right?
You can make a route like this:
get '/groups/associate_subgroup_with_org' => 'groups#associate_subgroup_with_org', :as => :associate_subgroup
And you can send any no. of parameters with link_to:
<%= link_to 'Select',
{controller: 'groups',
action: 'associate_subgroup_with_org',
organization_id: organization.id,
subgroup_id: #activity.group.id},
class: 'button' %>
Or,
<%= link_to 'Select',associate_subgroup_path(organization_id: organization.id, subgroup_id: #activity.group.id),class: 'button' %>
You need to specify it in your routes. Something like this:
get "/groups/:id/subgroup/:state" => "groups#subgroup", :as => :subgroup
And write the link like:
subgroup_path(#organization, #subgroup)
With whatever symbols you're using.
Using controller and actions in link_to/form_url is not recommended. I guess you have a groups resources, I mean in routes.rb something like resources :groups. if so then add a collection method there like:
resources :groups do
#....
post :associate_subgroup_with_org
end
Now you can use associate_subgroup_with_org_groups_path(p1: v1, p2: v2, .....)
Or you can define one named route as:
post 'groups/associate_subgroup_with_org', as: :associate_subgroup_with_org
Now you can use associate_subgroup_with_org_path(p1: v1, p2: v2, .....)
Hope its clear

how to make ID a random 8 digit alphanumeric in rails?

This is something I am using inside my model
This is the URL that gets posted to another 3rd party website through API
Post Model (post.rb)
"#{content.truncate(200)}...more http://domain.com/post/#{id.to_s}"
The "id" is referring to the post id. How can I convert that into a random 8 digit alphanumeric?
Right now, it gets displayed as something that people can alter http://domain.com/post/902
I want http://domain.com/post/9sd98asj
I know I probably need to use something like SecureRandom.urlsafe_base64(8) but where and how can I set this up?
This is what I have in routes.rb
match '/post/:id', :to => 'posts#show', via: :get, as: :post
You only need to add one attribute to post. The attribute name is permalink.
Try running:
rails g migration add_permalink_to_posts permalink:string
rake db:migrate
You have twoActive Record Callbacks you can choose from: before_save or before_create (review the difference between both). This example is using the before_save callback.
note : for Rails 3.x
class Post < ActiveRecord::Base
attr_accessible :content, :permalink
before_save :make_it_permalink
def make_it_permalink
# this can create a permalink using a random 8-digit alphanumeric
self.permalink = SecureRandom.urlsafe_base64(8)
end
end
urlsafe_base64
And in your routes.rb file:
match "/post/:permalink" => 'posts#show', :as => "show_post"
In posts_controller.rb:
def index
#posts = Post.all
end
def show
#post = Post.find_by_permalink(params[:permalink])
end
Finally, here are the views (index.html.erb):
<% #posts.each do |post| %>
<p><%= truncate(post.content, :length => 300).html_safe %>
<br/><br/>
<%= link_to "Read More...", show_post_path(post.permalink) %></p>
<% end %>
"Altering the primary key in Rails to be a string" is related to your question.
I would:
Leave default ID on table
Not define resources routes, writing the needed ones with match (like match '/post/:code')
On controller#show, use Post.find_by_code(params[:code]).

How to make a custom route in Rails? By custom I mean one that reacts to params

So essentially I've setup a route to match "products/:product", which seems to respond to a page like baseurl/products/toaster and displays the toaster product. My problem is I can't seem to use link_to to generate this path, and by that I mean I don't know how. Any help on this?
There are several solutions on this one :
<%= link_to 'Toaster', { :controller => 'products', :action => 'whatever', :product => 'toaster' } %>
But it's not really Rails Way, for that you need to add :as => :product at the end of your route. This will create the product_path helper that can be used this way :
<%= link_to 'Toaster', product_path(:product => 'toaster') %>
Within your routes file you can do something like:
match "products/:product" => "products#show", :as => :product
Where the controller is ProductsController and the view is show
within the Products controller your have
def show
#product = Hub.find_by_name(params[:product])
respond_to do |format|
format.html # show.html.erb
end
end
Where whatever is in the products/:product section will be available via params.
Then, since we used :as in your routes you can do this with link_to:
<%= link_to product(#product) %>
Where #product is an instance of a product or a string. This is just an example and the param can be anything you want, the same goes for controller/action. For more info you should check out this.
Hope this helps!

Question about URL friendly links

I am trying to get my urls to look like this:
example.com/posts/id_of_post/title_of_post
I have this in my controller:
match ':controller/:id/:link', :controller => 'posts', :action => 'show'
Say I have a list of posts.. how can I link to them?
<%= link_to 'Show', post %>
Just gives the usual /posts/id
On another note, at the minute I am making a url-friendly link when a post is created and storing it in the database. Would it be better to create on the fly? Is that possible/better?
I saw this in an answer to another question:
def to_param
normalized_name = title.gsub(' ', '-').gsub(/[^a-zA-Z0-9\_\-\.]/, '')
"#{self.id}-#{normalized_name}"
end
That would work if I could change the - to a /. Possible?
I recommend just doing this instead of the gsub stuff:
def to_param
"#{self.id}-#{title.parameterize}"
end
Downside is that if the title changes, the URL changes. Which is a downer.
So a lot of implementations will do
before_create :permanize
def permanize
permalink = title.parameterize
end
def to_param
"#{self.id}-#{permalink}"
end
This is what I did:
I added this to my post#create:
#post.link = (#post.title.parameterize)
I will give the user the option to edit the title for up to 5 mins after posting.
My route:
match "/posts/:id/:link" => "posts#show", :as => "story"
and my index view for posts
<%= link_to 'Show', story_url(post, post.link) %>

Resources