Where should I create my rails view - Rails 4.0 - ruby-on-rails

I have a rails app whose homepage is as follows:
www.person.com
I then have a model - Person who has an id attribute.
If I want to create a view based on that ID, and I want the URL to look like this:
www.person.com/{Person.id}, or www.person.com/1
where should I create my view and what should I name it? Should it just be Views/Person/index.html.erb?

Rather, create show.html.erb in views/person(s)/
You also need to create a controller method in persons_controller.rb:
def show
# Insert options for person's page here
end
The magic happens in routes.rb, where you'll define the route for that show:
resources :persons, :path => '', :path_names => {:show => '/:id'}

Related

How to implement same routes pattern for different models in Ruby on Rails?

I have a WP site with "/page/" routing pattern for static pages and "/category/" for categories. So WordPress understands that "/about/" is a page and "/science/" is a category. Now I'm trying to move it on Rails with same routing.
Both "Page" and "Category" are models and they should be able to be edited from an admin area.
How can i make it clear for Rails to check for existing page and if there is no page then check for a category?
P.S. I know I could do '/pages/:url/' but I'm really interested in how to do what i've asked before.
You didn't gave details about your code, so I'm going to write a generic answer. You can adjust to your code.
In most cases we have few static pages, like about, home and maybe something more
So, based on that, you can make specific routes for these static pages, and another route to categories.
get '/home' => 'static#action'
get '/about' => 'static#anotheraction'
get '/:category' => 'categories#action'
You can rename routes as the following:
get 'categories', path_names: { index: 'category' }
get 'pages', path_names: { index: 'page' }
See this link Override some routes
If you want change all routes that called categories to category Try it:
get 'categories', :path => 'category'
See this link Change all resources that called 'categories'
For /science to be show category that is name "science" Try this:
change routes as:
get 'categories/:name' => 'categories#show'
In action show in categories_controller read category using #category = Category.find_by_name(params[:name])
You can add remaining routes as the following using index_controller:
get '/home' => 'index#action'
get '/about' => 'index#anotheraction'
To change your URL between two controllers Try This:
In pages_controller in action show do this: if Page.where(name: params[:name]).first.present?
your code to show this page
else
render 'categories/show'
end
Check this link render to another controller whit another action

Do you have to define controller helpers to get paths for new routes in rails?

I have a Customer model and I want his controller to repond to a find method
I added this in my routes.rb file:
match 'customers/find/:name' => 'mymodel#find' resources :customers
In my controller I have something like this:
def find
#customers = Customer.fin_all_by_name(params[:name])
end
in my views, when I need to create a link for that resource I'm using this:
= link_to 'Find By Name', :controller => "customers", :action => "find", :name => #customer.name
now, I'm trying integration tests with cucumber and I have a problem: I have to create a step definition in my customer_step.rb file for customers having same name:
when /^customers having same name as "(.*)"/
url_encode('/customers/find/' + $1)
now that line doesn't work, it says undefined method `url_encode'
I need to encode that string because if the name contains a space I get obvious errors.
I'm new to ruby and rails and I think I'm missing something here.
Am I following the right pattern to accomplish this search?
Should I define an helper method in my controller to generate search urls?
Is it correct that line I have in my _step.rb file?
I don't want urls to be like this: customers/find?name=test
but: customers/find/test
I just sorted it out, I slightly modified my match expression and added the :as parameter
and this gave me the possibility to call find_path() helper method
match 'customers/find/:name' => 'customers#find', :as => :find
Is this correct?
Using :as should indeed create a route helper for you. If you want to get a list of your matched routes, to which controller/action they route, and the name of the route helper, use rake routes in console.

undefined method `medium_url'

I have a 'media' model, and the controller through which I am doing any changes to that table is called 'MultimediaController'.
When creating a new media and trying to redirect, I get the following error: undefined method 'medium_url' for #<MultimediaController:0x007f86f49ca400>
I dont have any tables, models, controllers or anything else called "medium". I'm assuming rails is doing this automatically based on my table named 'media'. Is there any way I can overwrite this?
edit: my redirect looks like this: respond_with(#media, {:controller => 'multimedia', :action => 'index', :id => session[:user_id], :collection => #media.collection_id})
"Media" is plural for "medium" so it sounds like you've got some renaming to do or customizations in inflections.rb.
Medium_url would mean rails is looking for a single "Medium" record (or whatever database you are dealing with .. media etc). You'd have to pass in an id in order to redirect to the Medium object when using medium_url.
If you want to redirect to a list of all Mediums (Your index action) you should be using mediums_url.
Rails has a fantastic guide on restful routing.
http://guides.rubyonrails.org/routing.html
def create
# Code to create the record goes here blah blah.
# Redirect to a list of all mediums
redirect_to mediums_url
# Or redirect to the medium object we just created
# redirect_to medium_url(#object)
end

Rails Routing with Query String

I have a problem where I need values passed in from a GET request and I don't know how to set up the routing definition.
My Category object has a type(string),a color(string) and many products. I want to create a simple web service that lets the caller get all of a Category's products by passing in the Category's type and color:
http://www.myapp.com/getProducts?catType=toy&color=red
or ?
http://www.myapp.com/categories/getProducts?catType=toy&color=red
How do I define the correct routing for this situation? Are there better ways to do this in a Restful manner... because I know that Rails is Restful, so if there is a way to do it "correctly" then that would be even better.
Thanks
Your first example:
map.getproduct '/getProduct', :controller => 'your_controller', :action => 'your_action'
In controller you will have catType and color in params hash:
params[:catType]
=> 'toy'
params[:color]
=> 'red'
Is there better way? Probably yes, but it depends on your needs. If you will always have catType and color parameters, than you can add route like this:
map.getproduct '/getProduct/:catType/:color', :controller => 'your_controller', :action => 'your_action'
You will have access to those parameters with params hash like in previous example. And your urls will look like this:
www.myapp.com/getProduct/toy/red
If your parameters may change, you can use route globbing:
map.getproduct '/getProduct/*query', :controller => 'your_controller', :action => 'your_action'
Then it will catch all request that has www.my.app.com/getProduct/... at the begining. But you will have more work in controller. You will have access to query with this:
params[:query]
and for www.myapp.com/getProduct/color/red/catType/toy it will give:
params[:query]
=> ['color', 'red', 'catType', 'toy]
So you have to parse it manualy.
One RESTful way to to do this would involve a product resource nested beneath a category resource, like so:
http://www.myapp.com/categories/toy/products?color=red
Your routes.rb would need to contain:
map.resources :categories do |category|
category.resources :products
end
Since my url above using the Category's type attribute for routing, I'm implying that each type is unique, like an id. It'll mean that whenever you're loading a category in the Categories controller (or anywhere else) you'll need to load the category with Category.find_by_type(params[:id]) instead of Category.find(params[:id]). I like routing categories this way whenever possible.
Your ProductsController controller index action would find products using lines like:
#category = Category.find_by_type(params[:category_id])
#products = #category.products.find(:all, :conditions => { :color => params[:color]} )
Remember, your Category model must contain the line:
has_many :products
It's probable a good idea to enforce that in the model with validations:
validates_presence_of :type
validates_uniqueness_of :type
To make routing work you should also overwrite the to_param method in the Category model to return type instead of id:
def to_param
self.type
end

Help with Rails routes

Say if I have a controller, profile, which has just two actions. The first one is list, which will just show the list of names. I want these names to be links which will then take you to a page that shows the full profile. So I need a second action, view, which can then bed fed a parameter to indicate which profile to view.
For example: I would access /profile/list, then if I want to view John's profile, I will click on his name which should take me to /profile/view/john. My view action will read the john parameter and then make the appropriate database queries.
What changes do I have to make to routes.rb for this to happen? Cheers.
I'd rather use the default :controller/:action/:id route to protect against cases where there are 2 John's in the list.
To have a custom route like you mentioned
edit Routes.rb to include a new one
map.connect ':controller/:action/:user_name'
Now a request like profile/view/john should reach you as
#params = {:controller => "profile", :action=> "view", :user_name => "john"}
Use the params[:user_name] value to locate and display the relevant record in the controller's view action. You can also want to setup some requirements on the :user_name part of the url, e.g. it has to match /SomeRegexpToValidateNames/
map.connect ':controller/:action/:user_name',
:requirements => {:user_name => /\w+/}
if you want to identify profiles by name, as "/profile/view/john" you can use the permalink_fu plugin
http://www.seoonrails.com/even-better-looking-urls-with-permalink_fu
which will keep you out of trouble when there's name duplication...
If the model is "user" you have to override the to_param method. This will allow you to return the "id-name" of the user instead of the "id". (ex: /profile/view/23-john)
I know, it's not exactly what you asked for but this should be a easy solution.
class User < ActiveRecord::Base
def to_param
"#{id}-#{name.gsub(/\W/, '-').downcase}"
end
end
And just add a simple resource declaration to the routing configuration:
map.resources :users

Resources