Best practice for further actions in rails controllers - ruby-on-rails

i'm just writing my first app in rails and i wonder, if there is a best practice to do the following:
i have a customer model created by a scaffold and pumping it up. a customer has to be displayed in a google map, so if go to /customers/23, the customer information are displayed. additionally i have a link within this page to show the user in a map (with a query ui dialog that comes up via ajax).
The question for me is, how does this fits in the normal crud structure of the model. Should i do like creating an action, called "show_map" and give it an extra route additionally to the resources routes? How do you handle this kind of things?

Lets do it like
resources :customers do
resource :map, :only => [:index]
end
it will generate routes like this
{:action=>"show", :controller=>"maps"} customer_map GET /customers/:customer_id/map(.:format)

Related

Rails index on show page

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

Creating Questions in Ruby on Rails

I have been following this guide to make a Ruby on Rails web app:
http://guides.rubyonrails.org/getting_started.html
It is supposed to be a quiz where people answer questions.
I have made :questions a resource. However, the guide mentions a page on its website to be able to create and delete its resource articles. Obviously this makes no sense with quiz questions as I just want to create them once and after that no more can be created or deleted. However, there is no mention of this in the guide?
If you don't want to be able to create/update/destroy your questions through controller, you can exclude these restful routes with :except, or specify the routes you need with :only which is more obvious(take a look at the routing guide):
resources :questions, only: [:index, :show]
This will create following routes:
GET /questions questions#index
GET /questions/:id questions#show
To fill your database with questions, use seeds(which are described in AR migrations guide). Put your questions creation related code into db/seeds.rb file and run rake db:seed afterwards.
You should specify in your routes to only :show the questions.
Do something like this in your routes:
resources :questions, only: [:show]
So as much I understand, you want to create resources and data on your own but don't want other users to be able to create or delete a resource, right?
let's start with the basics:
In MVC, the model/resource is the main representation of the entities.
The routes file indicate what routes are available at the first place
for each entity to which HTML requests can be sent. It also matches the route with a respective controller action. The controller
provides a gateway for users to interact with your application, takes
a request from them, take actions needed( issue SQL commands to create, show, delete from the database etc) and give a suitable response at the end.
So, suppose you want users to create a new resource on your server. First, you provide a route on which they can send a request. Then, you give them a create new resource button in your view through which they can interact. That button will use the route, match it with a controller action and send a request to that controller method. Depending on what is inside the controller action, the controller then creates the resource and redirect the user with a 302 with a notification.
Now, suppose you don't want a request to go through. What will you do?
You will firstly not create a route on which a request can be sent. You will also not create a controller action on which request can be received.
That's the use case in your scenario.
Since you don't want users to be able to send a request to the server to create the resource:
Don't provide the routes for them to send any such HTML request
Don't provide any controller which will receive such request
And obviously, don't provide any button in the view to take that action.
Now, the question would be: Then how will I create the resource?
You have three options:
Use a seed file: You can use a seed file where you add all the data you want. This tutorial and many other resources on the web can help you out. http://www.xyzpub.com/en/ruby-on-rails/3.2/seed_rb.html
Use rails console: Give create commands: Question.create(:name => "hello", :description => "How you doing!"). See the link here: https://apidock.com/rails/ActiveRecord/Base/create/class
If you are a beginner, you need to work a little more before trying this: Create authorized users and what actions they can take. You can also create an admin dashboard and provide all actions to admin users using activeadmin gem.
This blog explains the process: http://www.onceaday.today/subjects/1/posts/9 3
Finally, as you do need to show all the questions: create only show route, match it with a controller action, write the method in the controller action which issues a SQL command to get all the resource from the database and give the respective show view the data it can render.
Hope it helps you out!

A good approach to different indexes of same resource in Rails?

Something I've been wondering about is the best approach to creating a different index view of the same resource in Rails.
For example, let's say you have a group of Users, and the current Index action of the Users Controller that generates a tabular view of the users. You then want to create a second Index view that plotted all the users on a map. Would the best approach be to create a new action in the Users controller, or to create a new controller (like UsersMap) with a new index?
Thoughts appreciated...
My route file looks like this:
resources :users, :only => [:index, :index_with_map, :show, :edit, :update] do
match '/index_with_map' => 'users#index_with_map'
end
But hitting "users/index_with_map" results in:
ActiveRecord::RecordNotFound at /admin/users/index_with_map Couldn't find User with id=index_with_map
You could add that action to the UsersController, but if you are going to have more actions including Users and Maps, you might wanna think of making a new controller (to conform to the Single Responsibility Principle).
From the guides:
If you find yourself adding many extra actions to a resourceful route,
it’s time to stop and ask yourself whether you’re disguising the
presence of another resource.
You could do this:
resources :users do
collection do
get 'index_with_map'
end
end
This will enable Rails to recognize a path such as /users/index_with_map with GET.
The best approach would be to add new action that will deal with the users map. Then you will only need to create the corresponding view file for that action.
The users are for the same table, the functionality is only different. So why the need of different controller?
Also if you will create the another controller just for map view then there is no use of that as it's just a wastage of resources.
Another point is -
Controllers provides the user to interact with the model. So two controllers means you typically want two models. So different controllers are used when you want to do different (categories of) things.

Rails nested resource creation on separate pages

resources :books do
resources :chapters
end
Let's assume I have the above properly nested resources. I want to create a page where I create parent book resources and another page to create the chapters resources. When creating chapters, I want users to be able to select parent books they created.
Right now I have...
protected
def find_book
#book = Book.find(params[:book_id])
end
...in the chapter controller but I believe this only works when there is already a book id present in the URL. So to create a new chapter I would have to visit "rootpath/book/book_id/chapter/new" when I want to be able to create chapters on a separate page.
Although I'm really not sure how to approach the problem, right now my plan is to put an association(?) form on the chapter creation page that links the nested resources.
The problem is, I'm really new to web development and I'm not sure if I'm approaching this right at all. How would I put a form that sends :book_id to the chapter controller? Would this method work at all? Are there more efficient ways to go at it?
I realize my questions might be a little vague but Any help would be greatly appreciated!
The dull answer is: your proposal does not make sense with only the nested route.
The nested route implies that upon accessing the chapters#new action, you already know exactly which book that should contain the chapter.
But on the bright side: you can use both nested and non-nested routes at the same time.
If you want to keep the nested route, but also provide a new and create actions that lets the user choose the desired Book for the chapter, you can add a non-nested route for Chapter creation.
For example:
resources :books do
resources :chapters
end
resources :chapters
Note that your controllers may need to be rewritten a bit to accomodate the dual routes.
If you want, you could create both resources in the same page. Look up accepts_nested_attributes_for to do that. It's really easy, once you get the hang of it.

What is a "resource" in Rails?

Dumb question but I have some lingering confusion of what, exactly, a "resource" is in Rails. The term is used everywhere but I get a funny feeling it might be being used rather loosely. It's referenced in the model, the controller and, quite literally, in routes.rb.
Is it the specific route? For example, map.resources maps the 7 RESTful "resources". So an example of one resource would be the call to, say, the index action of a particular class's controller?!?
Is it a reference to the whole page/object being retrieved? or perhaps, more narrowly, a database table? or the row being retreived?
Is it something else?
Anyway, hopefully someone can set me straight...
Any object that you want users to be able to access via URI and perform CRUD (or some subset thereof) operations on can be thought of as a resource. In the Rails sense, it is generally a database table which is represented by a model, and acted on through a controller.
For example, you might have a User resource (with a users table in your DB). This is represented by a User model, is mapped to users_controller with map.resources :users (which then generates routes like /users (a collection of User resources) and /users/1 (a specific User resource).
You act upon those resources by using the appropriate HTTP method when making calls to those resources. POST to the resource collection (/users) creates a new record; GET retrieves a list of resources (/users) or a specific user (/users/1). PUT updates a specific user (/users/1/), and DELETE destroys that user. The URLs are the same, but the result (and controller action) may be different based on the HTTP verb. The idea, though is that /users/1 always means "I'm interacting with the User that has ID #1", regardless of the action.
Here's a good article discussing how most developers think that "Resource" is synonomous with the database table, the argument, I guess, being that mapping to the resource is mapping the controller to that database table (or, with ActiveResource, to another REST url).
Basically, I think a "resource" is "persisted data." map.resources maps the 7 RESTful actions to a particular suite of persisted data.
But I haven't thought about it too much in depth. Good question!
I think they probably mean it in the general web sense, i.e., Resource (Web):
the referent of any Uniform Resource Identifier
I don't think it has anything to do with database tables.
open your model folder, that is a hint of what resources you have!
example: users, pictures, comments...
A lot of people here say that resources refer to the database tables you have. It might be true sometimes but not necessarily true always. I could give you a lot of examples where you don't have a corresponding table in your database for a particular resource. Hence asssociating it with tables is rather wrong.
I would define a resource as a route which maps to related requests. So instead of declaring separate routes for the actions you want to do you can simply declare them using a resourceful route.In Rails, a resourceful route provides a mapping between HTTP requests and URLs to controller actions.
So say you define resources :users in config/routes.rb. You can now use a number of helpers to the controllers in your application like edit_user_path which returns users/edit .
Here's a good link: https://api.rubyonrails.org/v5.2.1/classes/ActionDispatch/Routing/Mapper/Resources.html
Which basically says: Resource routing allows you to quickly declare all of the common routes for a given resourceful controller. Instead of declaring separate routes for your index, show, new, edit, create, update and destroy actions, a resourceful route declares them in a single line of code:
resources :photos

Resources