I have a controller that works without a table in the database.
At the moment, there is an action index that performs a request to the api from which it performs the action. Route looks like /car_collector.
And my question is how to create a route /car_collector/:id/edit without creating table in database.
Just creating a route get '/car_collector/:id/edit', to: 'car_collector#edit', as: 'edit_doc_collector', param: :id an error is generated ActiveRecord::StatementInvalid in Admin::CarCollectorController#edit
resources :car_collector, only: :edit
That's it, you don't need do sometning extra
After that just go to /car_collector/1/edit, /car_collector/2/edit etc.
Default param will be as params[:id]
Related
My application has several ways to create notifications:
A user can create a notification using the standard "new" method
A link in a view can create a notification from an action using a dedicated "new_action"
etc.
So I created additional route and views for the new_action_notification_path:
resources :notifications do
member do
get :new_action
end
collection do
get :index_all
end
end
In the controller
# GET /notifications/new_action
def new_action
#playground = Playground.find(current_playground)
#notification = #playground.notifications.build( playground_id: params[:playground_id], …
And in the view:
<%= link_to t('Reject'), new_action_notification_path(
playground_id: current_playground,
description: t("#{this_object.class.name}#{'Rejected'}"),
But this does not behave as expected:
If I write new_action_notification_path in the view, as above, the generated URL looks like /notification/729/new_action?code=QWSTZ ...
If I write new_notification_path in the same place, the generated URL looks like /notification/new?code=QWSTZ ...
Why is it different, and how can I remove the notification id from the first URL?
Thanks a lot!
The reason your url's are different is because you have a nested route for the new_action.
resources :notifications do
member do
get :new_action
end
end
With a nested route, you are going to get an id number between your resources. The 729 is the id you are passing in to the link_to helper. The other route helper, new_notification_path, is creating a new notification, so it doesn't need an id. If you look at your routes, with rails routes in your console or localhost:3000/rails/info/routes in your browser, you'll see that the new_action needs an id.
new_action_notification_path GET /notifications/:id/new_action
new_notification_path GET /notifications
The :id part of the route is a placeholder for an id number (although it can be anything you pass in, really) to look up the resource before it. In this case, the id is use to look up the notification.
For example, let's say I have a Post resource.
With GET /posts I retrieve all posts (index action). What if I want to retrieve trending posts (posts with a lot of likes in the last 24 hours)? Should I implement the logic in the index action (through a parameter), or should I implement a new action trending that responds to a new endpoint GET /trending, making the API non-REST?
Note: I read this article and I understand the parameter way, but I can't figure out how adding an extra endpoint works...
you can do both. I would opt for the new action. But you can pass an extra param as well in a link:
link_to posts_path(trending: true)
In your controller you can then check if params[:trending].present? and then only pass to the posts variable #posts the trending posts.
You can also assign the trending indicator to a variable that will be passed to the index view so that you can adapt the layout (change header from "posts" to "trending posts") with if params[:trending].present? then #trending = true end
Creating a new action makes controllers and views less cluttered with conditions (if ...)
By the way, creating a new action is still a REST logic if you make it a GET query. If your new action was about updating a post it would need be a PATCHquery
Problably you have the resource :posts inside your routes.rb. This is the place you have to add the new endpoint. In rails the route to the new action.
You have
resources :posts
You should have
resources :posts do
get 'trending', on: :collection
end
Now you can see all routes that rails generate to you line, index, show, create, update... and more one trending
/posts/trending
You can have a look here: Rails guides add restful
The guide Rails Routing from the Outside In has a section named Adding Routes for Additional New Actions in chapter 2, Resource Routing: the Rails Default, with this example:
resources :comments do
get 'preview', on: :new
end
which generates the following route:
Prefix Verb URI Pattern Controller#Action
preview_new_comment GET /comments/new/preview(.:format) comments#preview
The same result can be achieved at least in two other ways:
1) Adding a collection route inside resources :comments like get 'new/preview', to: :preview, on: :collection (if you don't bother about the route name)
2) Adding just this route to the corresponding singular resource:
resource :comment, only: :preview do
get 'new/preview', to: :preview, as: 'preview_new', on: :collection
end
which has exactly the same behavior.
So why there is a on: :new option? Is it just a shortcut? If it is, why it's just for 'new actions' and there are not any similar options for the other default REST actions, like on: :edit or on: :delete?
This is a shortcut that is unique to the RESTful action new, in which an object is instantiated but not yet persisted.
For example, if you are filling out a form for a new object, you would provide yourself with a link_to "preview", which sends all of the attributes to your preview action (instead of directly to create). This is similar to a show view, but for an object that only exists in memory.
This functionality isn't logical for destroy, update, index, show or create. I suppose you could use a preview on an edit action after assigning new attributes before sending to update, but you'd have to create the route manually.
Actually there is a subtle difference.
If you add it to the resources :comments the path helper generated has a pluralized resource name so it will be preview_new_comments and the path will be /comments/new/preview. If you add it to the corresponding singular resource it doesn't pluralize the resource name in the path so you get /comment/new/preview but the helper will be preview_new_comment. Using :on will generate the path helper with the singular resource preview_new_comment but the route will have the pluralized resource /comments/new/preview.
To get the same behaviour you could use the following more verbose route outside the resource
get 'collections/new/preview', to: 'collections#preview', as: :preview_new_comment, on: :collection
I'm not sure why there is no on: :<action other than new> option. They advise against having too many new actions in the documentation but if you are going to have a new 'new' it seems a reasonable possibility you might need an new 'edit' to edit your new 'new'. However, things become more complicated because to edit you would need a path like collections/<id>/edit/preview and the path helper of the solution above stops working as you might expect. More importantly at this stage maybe you start veering away from the original intention of the option.
To access a dashboard this is the url: http://localhost:3000/dashboards/1
I want to hide idand show nothing in the url to do this: http://localhost:3000/dashboards/
I see another questions but all of it show to substitute id for name for example.
How can I just hide the id?
You just need to define a new route in routes.rb. If you're using resources :dashboards then that path is already defined and conventionally reserved as an index to list all available objects. Something like this should work:
get 'dashboards' => 'dashboards#show'
Note also that if you need the id in the controller you can no longer rely on params to grab the id as it's no longer in the url and available. You will have to use sessions instead.
Map the controller as a resource instead of resources. In your routes.rb file change
resources :dashboards
to
resource :dashboard
This assumes your controller is called DashboardsController. If not, pass the appropriate controller name.
resource :dashboard, controller: 'whatever_controller'
You may also want to restrict to the show action only, unless you have other actions.
resource :dashboard, only: [:show]
This will create the route
GET /dashboard
If you don't limit the actions, you'll get also
GET /dashboard/new
POST /dashboard
PATCH /dashboard
DELETE /dashboard
I am having a little trouble understanding what config/routes actually routes to. For example lets say I started a brand new project and generated a Users controller and edited my config/routes.rb to look like this:
config/routes.rb
SampleApp::Application.routes.draw do
match '/signup', to: 'users#new'
end
I start the server and as expected, it says I don't have a "new" action in my Users controller. I create one:
users_controller.rb
class UsersController < ApplicationController
def new
end
I refresh the page and as expected it tells me I need a users/new template. So my question is: do my view templates always have to be the same as the controller and action names in "(controller name)/(action name)" format (in this case users/new.html.erb)? Is it not possible to name my template something random (e.g. users/rubyonrailsmeetup.html.erb instead of users/new.html.erb) if have a controller action linked to one of the site's functions?
Also, does adding "resources :users" to config/routes.rb by default match the view template file names with the behavior I mentioned above so that views must be named after their "controller/action" names?
Sorry for the bother, I'm just trying to figure out what's part of Rails' magic and what isn't.
Rails attempts to render the template with the same name as the action by default, if no other render or redirect is invoked in the controller action. Basically, there's an implicit render :action at the end of every controller action.
But you can override this easily enough by adding an explicit render, e.g.,
render :rubyonrailsmeetup
Edit for clarity: this call to render goes in the controller code, not in config/routes
do my view templates always have to be the same as the controller and action names in "(controller name)/(action name)" format
These are defaults, you can render any view from the action by giving render :view_file_rel_path at the end of the action
does adding "resources :users" to config/routes.rb by default match the view template file names
Anything added in routes.rb is directly related upto controllers only, i.e. it matches the request and maps it to the controller/action. Logic of view comes only inside the action code