In Ruby on Rails, what does "resource" mean? - ruby-on-rails

I see the word resource in many different places like: resource Routing, resourceful controller, and resources: photos. What does resource actually mean?
One more question: What does RESTful route mean?

That's a big question!
I'd start here to better understand what 'resource' or 'resources' does as it relates to routing: http://guides.rubyonrails.org/routing.html#resource-routing-the-rails-default
The short of it is that that it formalizes a set of actions (for a specific controller) invoked by URL/HTTP Verb pairs that are responsible for modifying the state of a given resource. Think of resources as nouns: Order, LineItem, Offer and think about what you might want to do with those nouns: typically create them, delete them, modify them, retrieve some set of them, etc. As such, resources are often (but certainly don't have to be) your core model objects and/or some composite representation of those core models.
Again - the Rails Guides summarize what resourceful routes Rails very succinctly in Section 2.1 of the above link: 'In Rails, a resourceful route provides a mapping between HTTP verbs and URLs and controller actions'
If you're unfamiliar with REST, Wikipedia has some decent - but not exhaustive - coverage on the architecture: http://en.wikipedia.org/wiki/Representational_State_Transfer.

Related

What is a good naming convention for Rails custom controller actions regarding formulation (noun vs verb)?

When defining new actions in controllers I often find myself asking how should I formulate the name of the action correctly. Rails default CRUD actions all seem to follow the pattern of verb (new, create, edit, update, destroy, index) but is it a bad habit to use a noun? For ex. payment_history?
I found a lot of information describing the naming conventions for different files and classes and regarding the proper syntax but none about controller#actions from formulation part.
EDIT: I am asking about custom-defined actions not renaming the Rails default CRUD actions.
In my opinion, important thing about choosing name of the action should not be based on whether it is a noun or a verb, the name of the action should describe the behavior of the action itself, whether it calculates/gets/loads/renders/etc something. So that, when another person (or you after a long time) reads the code, he/she should be able to easily understand what is this action used for and what is expected result from this action.
Otherwise you could just name it is as * whatever * since ruby doesn't prohibit you to do so.
As example we can take a look at payment_history and list_payment_history. If I am reading the code and see action named list_payment_history, I understand that it lists the history, even without looking at the code I understand the purpose of the action. However if I see payment_history, I can only understand that it has something to do with history, not the exact meaning, does it show history, or may be sort history, archive history... no concrete understanding towards the purpose of the action.
Assuming you're following the conventional RESTful methodology, it is going to be easiest to follow the convention of index, show, new/create, edit/update and destroy. That is, unless you have a well-grounded reason not to, but then you ought to be able to justify to yourself and possible other developers why the default action names are not sufficient.
Using the default method names, you get a lot of the routing etc. stuff "for free", as Rails assumes you're following the convention. Also, do note that things that might not immediately sound like "resources" can often easily be modeled as such, e.g. your example "payment_history" may well be a subresource of another resource (a User?), in which case you'd have a singular nested route such as GET /users/{user_id}/payment_history. This route would then call PaymentHistoryController#show, as demonstrated in the Rails guide section on singular resources.
I don't know that it matters so much, though in general I think you're looking for a verb. Your models are typically nouns, and controllers define actions.
Controllers In rails acoording to my reading and experience
Controller class names use CamelCase and have Controller as a suffix. The Controller suffix is always singular. The name of the resource is usually plural.
Controller actions use snake_case and usually match the standard route names Rails defines (index, show, new, create, edit, update, delete).
Controller files go in app/controllers/#{resource_name}_controller.rb.
Example:
# app/controllers/bigfoot_sightings_controller.rb
BigfootSightingsController < ApplicationController
def index
# ...
end
def show
# ...
end
# etc
end
# app/controllers/profiles_controller.rb
ProfilesController < ApplicationController
def show
# ...
end
# etc
end

What is the "_path" method in ruby on rails?

I'm learning RoR, and I'm getting very confused by the "_path" method as it's used in Controllers and Routes. To be more specific, I'm referring to the many different calls that take the syntax "(something)_path". So far as I know, they all seem to either encode or manipulate a URL or link. I'm having a hard time mastering the use of this type of method because I can't figure out what it's core functionality is supposed to be.
For example, I could use the following code to redirect an old URL structure to a page of listed Tweet instances in my config/routes.rb file:
get '/all' => 'tweets#index', as: 'all_tweets'
Only now can I use the following in an .erb file. Notice the "_path" code at the end of the line.
<%= link_to "All Tweets", all_tweets_path %>
I could also use the following code to create a link to an edit page (and another action) in a different .erb file:
<p><%= link_to tweet.user.name, edit_tweet_path(#tweet) %></p>
I've tried reading through my study materials as well as the RoR documentation, but I always end up more lost than when I began. Does anybody know the low-level definition of this "_path" method?
Helper
It's called a route helper, which means that Rails will generate them to help provide you with resource-based routing structures. I'll explain more in a second
--
To explain properly - Rails is just a framework.
Like all software, it is a series of files loaded in a particular order. As such, Rails creates a series of helper methods in the booting process. These "helper" methods can then be used throughout your application to call functionality / information as you require:
The Rails framework provides a large number of helpers for working
with assets, dates, forms, numbers and model objects, to name a few.
These helpers are available to all templates by default.
In addition to using the standard template helpers provided, creating
custom helpers to extract complicated logic or reusable functionality
is strongly encouraged. By default, each controller will include all
helpers. These helpers are only accessible on the controller through
.helpers
The route helpers (which are generated from your config/routes.rb file give you the ability to call routes which are resourceful. These might seem strange to begin with, but once you understand them, will help you inexorably.
--
Resourceful
To give you more clarity - Rails routes are known as resourceful
This means they are constructed around resources. To give you a brief definition of this, you need to appreciate that the resources of your application are the pools of data you can add to, and pull
from.
To explain further, because Rails is object orientated. If you're new, this won't mean very much, but keep it in mind, as when you progress through the language / work, you'll begin to see why this is important.
Object orientated programming puts OBJECTS at the center of the flow. Typically, you'd put logic at the center, but with OOP, it's the objects. This is very important for us, as it means that everything you do in Rails is based around the objects you can create.
As per the MVC principle (which, again, is what Rails is built on), you'll create / invoke your objects from your Models:
This means that if you want to create a series of routes to "CRUD" (Create Read Update Destroy) your objects, Rails is able to create the routes necessary to do that. This is where the resources directives come from inside the routes file:
Hope this helps!
Actually, these paths are generated based on your routes.rb. If you run this command at your project, you would be able to see all available on your app
rake routes
For example, if I declare my resources in routes.rb like this
resources :posts
then I would automatically have following available paths
posts_path
post_path
new_post_path
edit_post_path
If you use some strange abc_path which has not been declared in routes.rb, then you will get errors.
Hope this is helpful, you will definitely need to work more with Rails and then eventually you will understand all of these things :)
you could find definition for these methods in rails repository:
https://github.com/rails/rails/blob/master/actionpack/lib/action_dispatch/routing/route_set.rb#L127

rails, implementing a master detail yet staying RESTful

Say that I have a Customers and an Orders tables, where each Customer may have many Orders.
Since in rails we are encouraged to represent these resources in a RESTful style, each of our resources, will respond to the following actions
index
show
edit
new
create
delete
So far, it all is very fair and plain. But now say that each time i open the show page of my Customer, i want to show a detail table containing all his/her orders.
This is a very common need, but doesn't this "unclean" the correctness of restful approach?
Is there some workaround, like "mashing" the two resources at a "view level", leaving them separate from the rest point of view?
Rails' default conventions ensure a RESTful application, and the only way this might become non-restful would be if you used custom-names on the routes, in which case you would have you add an extra bit of code to specify the HTTP method.
So, to accomplish what you're suggesting, at the view level, you may have something like this:
app/views/customers/show.html.erb
....
<% if customer.orders.any? %> #the orders method is provided on `customer` by defining the `has_many` and `belong_to` associations
<%= render #orders $>
And you would make sure to define #orders in the show action of the customers_controller.rb file.
This not only is RESTful, but also works within Rails' default conventions.
Those actions you list are not what makes something RESTful. There are a bunch of characteristics an application must have to be considered RESTful. Some of these characteristics are:
it is thought of as a repository of resources
resources are identified by a URI
there is a uniform interface for interacting with resources - the HTTP verbs of GET, POST, PUT, DELETE, etc.
Rails takes care of receiving HTTP requests and calling your application's functionality, regardless of whether it is RESTful in nature or not, through routing. Rails routing takes those HTTP verbs I mentioned, in combination with a URI, and determines which controller to call. By default Rails follows the RESTful paradigm, and by convention will map verb/URI combinations to those actions you listed - but the actions themselves, and the fact that they are lumped into a single controller, are not part of REST - they are just the rails convention.
In fact, the rails default routing maps 4 different resources to that single controller and its actions:
/customers // the list of all customers, GET/POST -> index/create
/customers/new // a form for creating a customer, GET -> new
/customers/{id} // a single customer, GET/PUT/DELETE -> show/update/destroy
/customers/{id}/edit // a form for editing a customer, GET -> edit
Resources can contain sub-resources, and Rails completely supports that. A sub-resource might be:
/customers/{id}/orders // the list of all orders for a particular customer
Another key part of REST is that it supports a resource having different representations, whether that is HTML, XML, JSON, etc. Clients use HTTP headers to convey what representation they are passing into the app (using the Content-Type header) and (usually) what they will accept in response (using the Accept header).
Its up to the application to determine what a resource representation looks like. Typically a resource will either be "thin" or "fat". A "thin" resource is one that simply has links to its sub-resources and further calls must be made to get them. A "fat" resource will contain the fully-fleshed out sub-resources it contains. Typically with an HTML representation, an application will return some form of "fat" resource. There is nothing non-RESTful about this - and is exactly what you are describing you want for your application.
So that was my long way of saying "don't be afraid of not being RESTful by displaying sub-resources - it's perfectly OK" :-)

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

Routing Question in Rails

How would i go about routing www.homepage.com/site/about to www.homepage.com/about for example? I still would like to use "site" as a controller, I just want to remove it from the route.
On a separate note, ss this how you usually setup routes for pages like about and contact that appear right after the site name?
For the first question, you could put something like this in your routes.rb:
map.about '/about', :controller => 'site', :action => 'about'
As for the second question, i don't quite undestand it, can you be a little more specific?
On a separate note, ss this how you usually setup routes for pages like about and contact that appear right after the site name?
If you follow the principles of REST (and you probably should), then by and large every URL should be terminating in a "resource" (ie: a noun, a "thing"). Each resource in turn has a controller, and these controllers have a standardized and limited set of actions.
This is a bit different from the "classic" routing scheme, where a controller would have more varied actions (and thus you could lump more functionality into a single, larger controller)
So, for example, in a RESTful system:
/contact would map to a ContactController, and not a "contact" action in some other controller (as it could in classic routing)
/about would similarly map to an AboutController.
/site/about would map to an AboutController, but this would be a "nested" route under the Site namespace. If you want to get hardcore about the nesting (and I typically do), I would:
Put AboutController in the Site module (thus Sites::AboutController), which in turn is stored in the file /app/controllers/site/about_controller.rb
Create a SiteController
Map /site to SiteController
If you had a preexisting Site:AboutController mapped to /site/about and you wanted to remap it to /about, you could do so using #rbaezam79's method. However, I'd seriously consider relocating and renaming the class itself just for consistency.
All of the resources I listed above would probably be considered "singleton" resources. This means:
you use map.resource instead of map.resources to map your routes
the default action is "show" (and not "index" as it is with non-singleton resources). Typically this will be the only action you need. (You wouldn't ever want to create or delete your about page, would you?)
the names are typically singular instead of plural. (Although I've run into some stumbling blocks with this)
When setting up routes like this, be sure to run the command "rake routes" regularly; this will show you exactly what you're getting at any given time.

Resources