So i'm wanting to have a url path in rails that looks like this.
baseurl/event/gigs
Basically the gigs will have its own show file
So im not sure if this is my php kicking in, However, I've got the file structure up like this
event > gigs > index.html.erb
Is this the correct way? and if so will i then have a controller like this?
class GigsController < EventController
def index
#vars will go here unless their inside the eventcontroller already?
end
end
Edit
So i had a blonde moment,
Whats happening now, Is i'm trying to get the gigs page to work but im getting stuck on the show method trying to get gigs and an id.
The url i'm putting in is /event/gigs
The error im getting
Couldn't find Event with 'id'= gigs
Ideas?
You have a resources :events, which by default generates many routes:
One of them is the GET /events/:id route. The URL you're visiting is hitting this route, and it's searching the DB for an Event ActiveRecord object with the :id 'gigs'.
I believe what you're wanting to do is define a static 'gigs' page under the /events/ namespace,
To do so, add this to routes.rb:
resources :events do
collection do
get '/gigs' => "events#gigs"
end
end
The file structure you're looking for, if you want to have a static /events/gigs page, is the following:
Your controller where you will supply variables and logic for the gigs action:
app/controllers/events_controller.rb
Where you will have the following:
def gigs
# Logic goes here.
end
And the view in question:
app/views/events/gig.html.erb
P.S - Like said above in the comments, you should skim over guides.rubyonrails.org/action_controller_overview.html in order to understand basic Rails concepts (folder structure, what controllers are and how routing works..).
You should check the output of rake routes. That will tell you how the URI's will map to controller actions. That's always a good way of debugging this kind of problem.
But from what you have posted and what #GigaBass recommended, I believe you should be pointing you browser at /events/gigs.
Cheers,
Niels
Related
Let me fair from the outset, and tell you that I've 'solved' the problem I'm describing. But a solution that you don't understand is not really a solution, now is it?
I have a resource, Newsbites. I have an index page for Newsbites. All my CRUD actions work fine.
I created a separate index (frontindex.html.erb) that acts as the front page of my website to show the newest Newsbites. The formatting is different from my normal index so readers get a larger photo, more of the text of the article(more ads too:).
In my routing table, I have the following statements:
resources :newsbites
get 'newsbites/frontindex'
root 'newsbites#frontindex'
Rake routes show the following:
newsbites_frontindex GET /newsbites/frontindex(.:format) newsbites#frontindex
If I load my website from the root (localhost:3000), it works great. There is a separate menu page that is rendered at the top, and it loads fine. I can click on all links, except the 'Home' link, and they work fine.
The 'Home' link is:
<%= link_to 'Home', newsbites_frontindex_path %>
When I click on the linked, I get the following error:
Couldn't find Newsbite with 'id'=frontindex
The error points to the 'show' action of my Newbites controller. Here are the frontindex and show def from the controller. They appear exactly as I'm posting them:
def frontindex
#newsbites = Newsbite.all
end
def show
#newsbite = Newsbite.find(params[:id])
end
I don't get it. Why is the show action being called by newbites_frontindex_path when there is both a def and views that match? Now, I can get around this by simply pointing home to root_path. But that doesn't help me understand. What if this was not the root of the site?
Any help would be greatly appreciated.
Actually I'm very surprised your code worked at all. A route must define two things
Some sort of regex against which the URL of the user is matched (newsbites/frontindex is different than newsbites/backindex)
What do you want to do for a given URL ? You want to point to a controller action
Rails won't usually "guess" what that action is. Or maybe, he was still able to "guess" that you wanted to use the newsbites controller, but it didn't guess the action right this time :(.
You should declare the root like this, which is what you did
root 'controller#action'
For the rest, there are two ways you can declare it. I prefer the second one
resources :newsbites
get 'newsbites/frontindex', to: 'newsbites#frontindex'
resources :newsbites do
# stuff added here will have the context of the `newsbites` controller already
get 'frontindex', on: :collection # the name of the action is inferred to be `frontindex`
end
The on: :collection, means that 'frontindex' is an action that concerns ALL the newsbites, so the URL generated will be newsbites/frontindex.
On the other hand get 'custom_action', on: :member, means that the custom_action targets a specific item, the URL generated would look like newsbites/:id/custom_action
EDIT : Rails also generate path_helpers based on the route declaration
get 'test', to: 'newsbites#frontindex'
get 'test/something', to: 'newsbites#frontindex'
resources :newsbites do
get 'frontindex', on: :collection
get 'custom_action', on: :member
Will generate path helpers
test_path
test_something_path
# CRUD helpers : new/edit/show/delete, etc. helpers
frontindex_newsbites_path
custom_actions_newsbite_path(ID) # without s !
You can always override this by adding an as: option
get 'custom_action', on: :member, as: 'something_cool'
# => something_cool_newsbites_path
Rails routes thinks that frontindex is an id. That's what the error message says. So it goes to GET newsbite/:id which maps to show.
You need to find a way let Rails routes know that frontindex is not an id.
On a side note: The order in which you define routes matters. The first one matched will be used. If you have GET newsbite/:id and GET newsbite/frontindex then the one that appears first will be matched. In your case this is the first one.
Maybe try to change the order.
What is the standard practice for a rails app when a standard 'show.html.erb' for one model essentially just lists its has_many of another model? There is no index for the 'child' model as without the context of its 'parent' model, a list of them would be useless.
Creating /parents/1/children/1 feels like the right thing to do (especially in terms of the API) and yet on the /parents/1 page there would be nothing but a bit button saying "carry on" ... again, useless.
Do I creat separate routes, like the one above, purely for the API or am I missing a cleaner more 'Railsy' way.
EDIT
I'm not sure the above is totally clear. If I have an Exam that was completely made up of Questions, would the Rails way to be to link to /exam/1/questions or purely to /exam/1 with a list of questions. Obviously the API would go to /exam/1/questions in most cases but what about the standard HTML page? It would seem like it wants to be /exam/1 but with nested resources the create route (by default) goes to the /exam/1/questions route. If there is a validation error on the /exam/1/questions/new route the form is rendered again on the create (/exam/1/questions) route; if the page is then refreshed you then get a 404 error as there is no index for the children.
All this leads me to believe that Rails expects be an index action for the majority of models; but in the above example this feels odd.
If I understand you right you dont whant the route to /parents/1 to be on your path. For this reason you should specify it in your routes.rb
resource :parents, except: :show do
resource :children
end
I want to have a link at the bottom of my show.html.erb that links to the new action in a different controller.
class Sample < ActiveRecord::Base
belongs_to :song
end
class Song < ActiveRecord::Base
has_many :samples
end
So, at the bottom of the show action for songs, I want to link to new for samples. This seems pretty easy, but I'm struggling to figure this out. I would also like to pass the id from the song to the form as :song_id
Fiddy, because you're new, let me explain how this works...
Routes
Your problem is that you don't understand the Rails routing structure - I'll hopefully explain it for you.
Rails, since it's an MVC framework, builds a series of "routes" for you. These "routes" are stored in the file available at config/routes.rb.
Routes, as described by the Rails documentation are as follows:
The Rails router recognizes URLs and dispatches them to a controller's
action. It can also generate paths and URLs, avoiding the need to
hardcode strings in your views.
The most important thing you should consider here is the way the routes generate paths for you. These paths are simply Rails "helper" methods, which you can call from your views. The reason these exist is two-fold -
They provide you with a DRY (don't repeat yourself) way of accessing / manipulating data
They are constructed around objects, helping maintain the object-orientated nature of Rails
These will likely mean nothing to you. However, what you need to realize that if set up your routes correctly, it seriously helps your app's infrastructure immensely.
--
Rails
This leads us quite nicely onto appreciating the way in which Rails works
Rails is an MVC (model view controller) framework. This might seem somewhat trivial, but in reality, it's one of the most important aspects to learn about Rails development, and here's why:
The Rails software system works by taking "requests" (user input) and then routing them to specific controller#actions. Those controllers then build model data from the database, and will translate that into either variables or objects, which you can use in your view.
The reason I mention this is that this type of development takes a lot of getting used-to, in that your program's flow is not about logic / functionality, but the accessibility of data. Therefore, when you ask about the routes or other parts of your app, you need to firstly remember what data you wish to show, and also how you want that data to be shown - this will give you the ability to construct & use the routes / controller actions which will get it to work properly
--
Fix
In terms of what you're saying, the way you'd go about achieving the result you want will be to use a nested route:
#config/routes.rb
resources :songs do
resources :samples #-> domain.com/songs/:song_id/samples/new
end
This will create a new route for you (which you can check by firing rake routes in your rails c (console). This will give you a path to use for your samples#new action:
#app/views/songs/show.html.erb
<%= link_to #song.name, new_song_sample_path(#song) %>
The above link will take you to the samples#show action, which you'll be able to populate with as much data as you require from the samples controller. The important thing to note is this action will have params[:song_id] available for you to either build an object from, or otherwise
<%= link_to "New Sample", new_sample_path(:song_id => #song_id) %>
Where #song_id is the variable that has that id in it.
Set paths in link_to tag which you can get by running rake_routes in terminal.
Ex
link_to "New song", new_sample_path(#song)
In the example given above #song is the instance variable of your current page.
You can also get some idea from here:
link_to Base URL Randomly Changed
Song Model:
accepts_nested_attributes_for :sample, allow_destroy: true
Route:
resources :songs do
resources :samples
end
Song's Show file:
<%= link_to "New Sample", new_song_sample_path(#song) %>
in url it will be:
/songs/:song_id/sample/new
Try this and let me know it works or not... I hope this helps you
I am trying to do something for hours and I'm stuck with rails routes.
So.. the idea is to have some even more user-friendly urls like for example /Laptops for a category and /Laptops/Apple-MacBook-Air-and-so-on. I should also use such links for simple pages like /MyDummyPage etc.
So my idea was to get the request_url and check if i can find the page myself. But it seems rails is initialising this request class after defining routes and right before calling the controller.
As you can see I am stuck and can't see any possible solution for my problem.
I will be glad if someone can help me.
Thank you in advance.
All the best!
(Whole thing revised)
If you want to allow dynamic matches along with normal restful routes, there are a couple options- (put it at the end of your routes or it will match everything)
match '*raw' => 'dynamic#show'
And in dynamic_controller.rb
def show
parts = params[:raw].split '/'
# do logic here to set all variables used in views
render #resource_or_page
end
You could also use the input in a search function and redirect to the first result of that search. Or return a 404 if there are no results.
def show
results = search_method_here params[:raw].sub('/', ' ')
if results.any?
redirect_to results.first
else
raise ActionController::RoutingError.new 'Not Found'
end
end
Also, for freindlier urls within restful routes, try out this: https://github.com/norman/friendly_id
I think its important to realize that people generally do not manipulate URLs by hand, and its nice to have readable urls, but its more important for them to be clear on what/where they are doing/going.
In response to your comment, I think you are mislead about routing. If you make 2 routes :category and :page, they match the exact same url, except one of them stores it in params[:category] and the other in params[:page]. To differentiate it, you would need to have a different amount of arguments matched like :category/:product or a namespace, or, perhaps, a restful route which specifies the MVC the route routes to.
Objective:
Be able to nest a resource, like records inside of users so that I can access /users/1/records to see all of the first users records. But I would also like to see /records to see all of the records ( or the new ones, or something like that ).
Problem
So I know I am missing something somewhere because that cannot be the way to do it. I know I can have like a static page or some other route for that, but I don't think that is very rails-y.
I would have users, so a user would see their page with their records, but also be able to browse records, so I assumed I would need a more general route for that.
Question
What is the appropriate way to browse a nested resource?
PS I have looked at things like this question, which almost address the problem, but deals with a static landing page for non logged in users, this is not what I am looking for.
Not sure how to handle this route later in controllers (never tried), but something like this should work:
resources :records
resources :users do
resources :records
end
I think you'll need to do something in records's index controller to check if its called for some user or not.
UPD: Ok, checked it. Check for params[:user_id] in your index controller.