Rails 3.2.12 controller action hiding from URL - ruby-on-rails-3

I have scaffold 'Category' which has table 'categories' and fields like category_name etc.
Now on my home page, I am showing all records.
If I click on 'show' of any particular category, my URL looks like this -> "http://www.abc.com/categories/1" where 1 is the id.
Here instead of "categories/1", I want the url to be in this format : "http://www.abc.com/#{category_name}".
I use friendly id but that makes my URL like this "http://www.abc.com/categories/#{category_name}".
I want to hide controller name and id from url and only display the category name

You can add something like
match '/:path' => 'categories#show', as: :category
in your route. be warned that this should be placed at the bottom of your route so it takes least priority because it will match the index action of all your controllers. Use it like
category_path(category_name)
Or
"/#{category_name}"
You may also need to remove the show mapping to the show action so it doesn't conflict with the named_route generated by adding the as: :category option
resources :categories, except: [:show]

Related

Changing the default rails route

In the rails the default behavior shows the id in the url like
http://0.0.0.0:3000/users/1
Now to change the url to show me something other than the id, I know I could put this in model
def to_param
name
end
And then get something like http://0.0.0.0:3000/users/mikey
I am wondering how can achieve a twitter style url. Currently the model name is still showing in the url. Something like this http://0.0.0.0:3000/mikey without the model name
Get the name of the database column storing your users’ names (let’s say it’s ‘name’).
In config/routes.rb add, somewhere above the default route:
match 'users/:name', :controller => 'users', :action => 'show'
Now, in users_controller, find def show and change it to:
#user = User.find_by_name(params[:name])
Lastly, all the id-based urls pointing to your users need to be updated to reflect the name-based change. Like the one your Users index.html.erb file.
link_to #user.name, 'users/#{#user.name}'
Add a route, near the bottom of your routes file (right above your root route!)
get '/:id', :to => "users#show", :as => :friendly_user
This will act as a fall-through route, so /anything that wasn't caught by an earlier route will route to users#show and pass an :id accordingly. You can then use friendly_user_path(#user) to generate links to that user's Twitter-style profile.
Be sure that this is one of the lowest-priority routes, as you wouldn't want a user to be able to sign up with a username like "logout" and replace your /logout page with their profile!

Adding a new record that has a foreign key relationship using new_foo_path(#bar)

I'm trying to add a new location to a restaurant using Ruby on Rails.
In the restaurants#show action I run:
<%= link_to 'Add Location', new_location_path(#restaurant) %>
And I get a URL: http://localhost:3000/locations/new.1, where 1 is the id of the restaurant. But the new location form doesn't appear.
What is the rails way to handle this simple case? Is using new_FOO_path even the right thing to be doing?
In this case, I shouldn't have a drop down to select the restaurant because I want the end user to only be able to add a location to their own restaurant. I would somehow need to have a hidden input with the restaurant ID in the add location form, and also validate the id on the backend.
I would create a nested resource in your routes.rb. Example:
resources :restaurants do
resources :locations
end
Then your link target would be new_restaurant_location_path(#restaurant). In your controller, you can find the restaurant via Restaurant.find(params[:restaurant_id]).
Alternatively, set the restaurant id as a GET parameter with new_location_path(:restaurant_id => #restaurant.id).

Rails - How to include a hyperlink in a text field

I have a notices model which contains records of notices for each user. Each notice record contains a message which is a text field with the notice message. These messages look like:
"#{current_user.username} liked your photo '#{#photo.name}."
In the example above, I would like the user and the photo to also be hyperlinks to that user and photo.
Here is a snippet from my likes_controller which generates a notice when a new like is created:
class LikesController < ApplicationController
def create
#photo = Photo.find(params[:id])
#like = Like.new(:photo_id => #photo.id, :user_id => current_user.id)
if #like.save
#notice = Notice.new(:user_id => #photo.user_id, :message => "#{current_user.username} liked your photo '#{#photo.name}'
end
Any thoughts on how I can include links in the message; is this even possible? Thanks.
Adding a link to your message is a rendering issue. In my opinion, you're rendering the message too soon, I would render it in the view.
If you change your Notice model so that it contains a the user_id and the like_id, you can render the notice text in the view (which also lets you localize the text later, should it prove necessary).
Rendering in the view lets you use the standard link_to helper to generate your links.

How to user defined friendly URLs in Rails 3?

Now i have something like this
http://myapp.com/pages/1
http://myapp.com/pages/2
http://myapp.com/pages/3
http://myapp.com/pages/4
And each page belong to one user
What i need is to each user to set it's own custom name for the page.
I was thinking of using the friendly_id gem http://norman.github.com/friendly_id/
but I don't find any method to directly edit the slug to set a custom friendly url
how should i proceed?
FriendlyID is a great gem.
It shouldn't be hard to implement user defined page URL.
Create table pages with user_id and link
class User < ActiveRecord::Base
has_many :pages
class Page < ActiveRecord::Base
belongs_to :user
has_friendly_id :link # link is name of the column whose value will be replaced by slugged value
On the page#new you add an input for the link attribute.
Alternatively, you could set friendly_id on title or something else with :use_slug => true option. This way FriendlyID will take the title and modify it so it doesn't have and restricted characters. It will use it's own table to store slugs. Use cached_slug to increase performanse.
Updated
To give users a choice whether they wan't to set a custom link, you could do this:
Set friendly_id on the link field without slugs..
Make a virtual attribute permalink so you could show it in your forms.
In the before_filter, check whether the permalink is set.
If it is, write it to the link field.
If it's not, write title to the link field.
FriendlyID uses babosa gem to generate slugs. If you decide to use it as well, this is how your filter could look like:
protected
def generate_link
#you might need to use .nil? instead
self.link = self.permalink.empty? ? make_slug(self.title) : make_slug(self.permalink)
end
def make_slug(value)
value.to_slug.normalize.to_s #you could as well use ph6py's way
end
Adding to_param method to one of the models should help:
def to_param
"#{id}-#{call_to_method_that_returns_custom_name.parameterize}"
end
Hope this is what you are looking for :)
I am not using the friendly_url gem and am not sure whether my way is efficient. But it works fine for me.
I have a model called Node with id and friendly url field called url_title.
My routes.rb file:
resource 'nodes/:url_title', :to => 'Nodes#view'
nodes_controller.rb
class NodesController <ActiveController
def view
#node = Node.find_by_url_title(:params(url_title))
end
end
And use the #node variable to populate your view.
Now, whenever I type www.example.com/nodes/awesome-title , it takes me to the proper page. One argument against this can be need to create an index on a non-primary field. But I think that might be required for better performance even in the friendly_url gem. Also, the non-primary field url_title needs to be unique. Again, this might be required even for correct working for friendly_url .
Feel free to correct me if I am wrong in these assumptions.
There are a variety of ways, you can achieve this-
1) using Stringex
2) sluggable-finder
3) friendly_id
A complete step by step methodology with reasons for each to be used can be found out here. Happy reading!

Web app design questions - RoR 3

This is my first web app that i am developing and i have some design questions, i have a few book about RoR3 but i dont seem to find answers to my questions.
My application is based on Ruby on rails 3
I am not looking for detailed answers here, if you can just point me to a topic name that i could learn about that can answer my qustions, such as "names resources" , "hidden fields" .....
My questions:
1- How to send information between View A and controller B. Example, i am on the View for "Company" when i click create employee i am calling the "new view" for the employee so i am now on a different view, how can i pass to the new employee action the ID of the company? Since i am now on a different view ? i don’t want to use nested resources
What are the different ways to send information across different controllers/views
2- ruby URLs: i can view am item in my model via the URL: http://localhost:3000/Companies/1
I don’t want the url to contain the index of the item, each company has a name and i want to display this name in the url such as http://localhost:3000/Companies/myCompany
How can i change the url structure of rails?
For your first question, you can pass the parameters with the link (assuming you have employee and company variables accessible to your view):
Edit: this should work:
= link_to "create employee", :controller => "employees", :action => "new", :company_id => #company.id
And in the Employees controller:
def new
company_id = params[:company_id]
# check that company_id is not nil before doing stuff with it
end
I'm not sure why doing this ignores any extra parameters:
= link_to "create employee", new_employee_path, :company_id => #company.id
For your second question, this is what you're looking for.
Pass the company id as parameters at create employee link .
In the controller ,receive the params like
def new
company_id = params[:company_id]
....
end
For using some string instead of id , use gem 'friendly_id'
Make sure your reference string should be unique.