fscore
fscore

Reputation: 2619

How are resources connected to controllers without a Model

I am writing a basic application that scrapes data. I have the following in my routes.rb.

Rails.application.routes.draw do
constraints subdomain: 'api' do
 namespace :api, path: '/' do
   resources :apps, :only => :show
 end
end

In controllers I have something like this although I am not sure how are resources connected to Controller.

class AppsController < ApplicationController
  def show
    puts "this works"
    respond_to do |format|
      format.json { render json: @user }
    end
  end

  def apps
    puts "my app"
  end

end

Also, I dont have a Model. Does that mean that in my resources :apps calls a method in AppsController called apps? If I wanted it t call apps then how's it possible ?

Upvotes: 1

Views: 2281

Answers (3)

dylanjha
dylanjha

Reputation: 2523

Routing simply maps URLs to a controller/action, the existence of a model with the same name does not matter.

To get to the apps action that you defined in the AppsController you need to define a route that maps to apps#apps < This syntax means AppsController, apps action.

An example of a route that would map to the AppsController apps action:

get '/apps', to: "apps#apps"

This is a weird example. It's not conventional to have a def apps action inside AppsController, what exactly are you trying to accomplish with this action?

If you want a rest call to /apps that returns a JSON list of apps, then this all you need to do.

router

resources :apps, only: [:index]

controller

class AppsController < ActionController::Base

  def index
    puts "This is the index route in AppsController"
  end

end

In the router, when you specify resource :apps, only: [:index]. This routes the request GET /apps to AppsController#index

Upvotes: 1

Josh Bodah
Josh Bodah

Reputation: 1243

In controllers I have something like this although I am not sure how are resources connected to Controller.

Rails.application.routes.draw provides a DSL which hooks into Rack (the interface between the HTTP server and Rails). It generates rules for where to route the response from Rack.

The DSL is provides has a lot of ways to do the same things. In this example, the resources :apps, :only => :show line basically says you want to generate all of the REST verbs for the AppsController, but you only want the :show verb, so the router will only generate a route to AppsController#show. Note that you can run rake routes to get a list of your routes.

Also, I dont have a Model. Does that mean that in my resources :apps calls a method in AppsController called apps? If I wanted it t call apps then how's it possible ?

Models are totally separate abstractions. Once the code reaches your controller you are in plain Ruby land until you return out of that controller action. Models are simply plain Ruby objects with the ability to talk to the database.

In your code if you wanted to call apps from the show method (or action) then you can just call it from there since it's in the same scope.

how does a controller in rails know that ok that is my route. In this case, apps

I'm not sure I understand this question, could you elaborate?

I am trying to add a GET /apps?filter=5 that returns my scraped data in the form of JSON and with filter as parameter to that it means that return 5 JSON objects to me

For one, you'll need to add a route for /apps. There are several ways you can do this. Here's one approach. I'm going to call it index instead of apps since that's more conventional:

# config/routes.rb
get '/apps' => 'apps#index'

# app/controllers/apps_controller.rb
class AppsController < ApplicationController
  respond_to :json

  def index
    limit = params[:filter].to_i
    @users = User.first(limit) # Implement this however you wish
    respond_with(@users)
  end
end

My syntax might be a little off here with the respond_to and respond_with, but it should explain how the controller routes

Upvotes: 1

Richard Peck
Richard Peck

Reputation: 76784

#config/routes.rb
constraints subdomain: 'api' do
   namespace :api, path: '/' do
       get :apps, to: "apps#apps", on: :collection #-> api.url.com/apps
   end
end

A much more coherent way to do it would be...

#config/routes.rb
constraints subdomain: 'api' do
   namespace :api, path: '/' do
       resources :apps #-> api.url.com/apps -> apps#index
   end
end

I think you're getting confused with how Rails works, especially with your data.

I post this all the time, maybe it will help you:

enter image description here

As you can see, your request is not tied to a specific "model", nor is a controller bound to it either. I'll explain the importance of the MVC (Model View Controller) aspect of rails in a minute.

Your thought process is that each request / resource has to have a corresponding model / dataset to pull from. Strictly, this is not the case, although many would believe it to be.

Remember that Rails is just an application framework - it has to work with all the same protocols & restrictions as the other frameworks & languages out there.

When you send a request to Rails (through your browser URL), it takes that request, and matches it to the appropriate controller. This controller action will then pull data from your model (if you've set it up like that), render the view with that data, and return the processed HTML to the browser.

Thus, you don't have to have a model bound to a particular controller action, or anything. You just need to make sure your controllers & views are mapped accordingly.


OOP

enter image description here

I think the part you're getting hooked up on is the object orientated nature of Ruby / Rails.

Although every part of the Rails framework is meant to work with objects, this only applies on a request-basis.

For example, whilst it's typically recommended to keep your controllers resourceful, you don't have to adhere to that methodology if you don't want to. Many newbies don't know the difference.

Thus, when you use the following:

#config/routes.rb
constraints subdomain: 'api' do
 namespace :api, path: '/' do
   resources :apps, only: :show #-> api.url.com/:id -> apps#show
 end
end

... what you're denoting is a controller bound by its resourceful nature. This would typically be expected to use model data, but it's not essential...

enter image description here

Upvotes: 1

Related Questions