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!
Related
I'm very new to using Rails and at the moment am building an Instagram clone as a project to help me understand Rails a bit better. I am following this very helpful tutorial on how to implement the likes/unlikes feature:
https://medium.com/full-taxx/how-to-add-likes-to-posts-in-rails-e81430101bc2
However, I don't fully understand the Rails paths - please could someone explain the difference between:
post_like_path and post_likes_path as mentioned in the tutorial. I cannot see why one is like and one is likes? :(
Really trying to get my head around this so would be so grateful for any insight!
Thanks :)
In Rails as per the REST -
If trying to refer to the single resource then use post_like_path.
If trying to refer to a collection of resources then use post_likes_path
When you want to show or delete a particular resource then you will have to provide an :id for the resource so that the target resource can be found.
[/posts/1/likes/1] - A single record of "like" is being referred here.
While in case of all records plural path is formed to refer to all like records -
[/posts/1/likes] - All records of "like" are being referred here.
post model can have multiple likes. But when we do undo like it will be singular right. so post_like_path will handle the single like and it's going to trigger "delete" action in controller.
post_likes_path will trigger the new action for for creating new like.
Please routes resources concept then you come to know more about it.
post_like_path is used for show page, update and destroy path. The post_likes_path will give you the path for the index and create actions.
This link is the ROR guide and has quite a simple explanation on it:
https://guides.rubyonrails.org/routing.html#specifying-a-controller-to-use
I'd suggest to always run this command from terminal:
rake routes
Or just for LikesController:
rake routes -c likes
This shows all the routes related to likes controllers. That's the output, it tells a lot of things. You can see where the plural and singular is used.
# Prefix Verb URI Pattern Controller#Action
# post_likes GET /posts/:post_id/likes(.:format) likes#index
# POST /posts/:post_id/likes(.:format) likes#create
# new_post_like GET /posts/:post_id/likes/new(.:format) likes#new
# edit_post_like GET /posts/:post_id/likes/:id/edit(.:format) likes#edit
# post_like GET /posts/:post_id/likes/:id(.:format) likes#show
# PATCH /posts/:post_id/likes/:id(.:format) likes#update
# PUT /posts/:post_id/likes/:id(.:format) likes#update
# DELETE /posts/:post_id/likes/:id(.:format) likes#destroy
First column shows you the path, the second the pattern (with required parameters) and the third the controller with action (related to the view).
So, for example, take
# new_post_like GET /posts/:post_id/likes/new(.:format) likes#new
This says that the form for a new like can be placed to a page linked by this URL:
new_post_like_path(post_id: #post) note the parameter required. The page is views/likes/new.html.erb.
the controller is LikesController and the action is def new; end where you need to instantiate the objects to be used in that page: #like = Like.new and #post = Post.find(params[:post_id]).
The form is then submitted by POST action, so the line to check is the following:
# post_likes POST /posts/:post_id/likes(.:format) likes#create
As before, the page where the form is located is views/likes/new.html.erb, the url to submit the form is post_likes_path(post.id). The POST action when submitting the form is processed by the controller LikesController and the action is def create; end
Other example:
# post_like GET /posts/:post_id/likes/:id(.:format) likes#show
It tells that to show the Like object with a certain id, you need to visit this link_to: post_like_path(post.id, like.id), the controller is LikesController, the action is def show; end and the view is in views/likes/show.html.erb.
And so on..
I am somewhat confused as to how to properly access an action in a rails controller that is NOT associated with one particular model. The routing file, by default, seems to be routing the action name to "id". So if I type, say, /user/login, I end up with an error that says: "Couldn't find User with 'id'= login"
What is the proper way to access arbitrary action names in rails?
Make a route for it, obviously. The request goes this way:
first it hits a route
from there it hits a controllers' action
[an action may invoke a model] (optional, but common)
controller specified a view and fetches data to render
view is sent back in response to a request
resource and resources might not be obvious about what they do. But in fact, they are shorthands to corresponding collections of routes used quite often, like this is what resources adds. And they're not monoliths, they can be customised to fit your needs. Providing options is just a start, you can provide a block to define your custom action routes for this resource like so:
resources :users do
get :login
end
This will add a /users/login route that maps to UsersController#login, following Rails' conventions.
See this guide for more details and don't forget to run rake routes to see what you have at the moment.
I am quite new to rails but i have searched a lot how to do this but it doesnt seem to work for me. Im trying to create a new view called request for my model called steppy_steps, so i created a new file in the views directory called request.html.rb, added this to my routes, match '/request' => 'pages#request', also tried get "steppy_tests/home", and lastly added (def request, end), to my Steppy_Tests_Controller.rb but when i check the url it gives me an error:Couldn't find SteppyTest with id=home
I cant figure out what to do any help would be great! Thanks in advance.
You should read up on the MVC programming pattern (which is what Rails is based on)
In order to make a view, you need to have the controller and model aspects in place too. I think you're doing this already, but to help you understand more, I'll outline below:
Views : Controller Actions
If you want to show a view from the steppy_steps controller, you need to first have a controller action set up to handle the request. You'd normally use a self-named controller for this (controller name steppy_steps), and have various actions for that
In your routes, you'll then "capture" the request to your steppy_steps controller like this:
#config/routes.rb
resources :steppy_steps
This will create a set of RESTful routes, which you can then translate into your controller, like this:
#app/controllers/steppy_steps_controller.rb
def index
#Index code
end
def show
#Show code
end
This will allow you to create a views directory which can contain the views for /views/steppy_steps/show.html.erb and /views/steppy_steps/index.html.erb
Routes Are Super Important
The error you're getting is caused by you sending /home to your view
The problem here is that if you're using a route which has an in-built id param (the show action routes have this), then Rails will look for the extra params after the URL
To fix this, you'll have to provide more of your code, but I also believe you'd be better understanding the fundamentals of Rails a little more
Adding Routes
You can add routes & views as you wish
If you're looking to add a requests route / view, I'd do this:
#config/routes.rb
resources :steppy_steps do
collection do
get :requests
end
end
This will allow you to create /steppy_steps/requests
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)
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