I want to have a page where a User can enter a URL and on the back the page will be parsed and show back some information found in the page.
I am wondering what would be a naming convention for this case, given the fact that there is no model associated with this. It is just a pure processing of a URL and show some information back.
I was thinking giving the controller the name ParseController, but I am also thinking about the convention of giving plural names for controllers.
you could name it PagesController and have an action named parse
class PagesController < ApplicationController
def parse
end
end
And if you ever wanted to have a model, it could be called Page
Its just what i think. But there are many other names that you could call it.
Related
I would like to know how to create a HTML form to send data to rails application so that specific model method guess gets triggered.
I managed to get this work in rails console, however even using HTML form guides from https://guides.rubyonrails.org/form_helpers.html I can't seem to get my head around this concept.
to generate the basic setup I used:
rails g scaffold Riddle content image_url
my model file:
models/riddle.rb
class Riddle < ApplicationRecord
def guess(guess)
content == guess
end
end
If the guess is correct(equal to content of the current object) user should see "correct guess" on the HTML page.
A form upon submit can hit a controller action. So you could do something like this:
Have a view which has the form has a form which makes a GET/POST request to an action in RiddlesController; lets call it validate_guess passing the required parameters id of the riddle and guess which is the guess that is a user input.
app/controllers/riddles_controller.rb
class RiddlesController < ApplicationController
def validate_guess
riddle = Riddle.find param[:id]
guessed_correctly = riddle.guess(params[:guess])
if guessed_correctly
render plain: "correct guess"
else
render plain: "incorrect guess"
end
end
You would also have to declare a route for this in config/routes.rb. As this works on a single Riddle object; it would be a member_action for the Riddle resource.
resources :riddles do
member do
post :validate_guess
end
end
Controller - Its the controller that renders the view and a view can only interact with the controller. Views dont directly interact with a model, and the additional controller layer does this, which provides us with a lot of structure, i.e. we can keep all data related logic in the model(though it tends to creep out of these sometimes :)). Deal with requests generation/handling at the View/Controller level and contact model to get/set info related to the business objects.
For example - your guess method is a good example. It checks whether a given value is a correct guess for a given Riddle object and returns a boolean as result(by comparing it to some attribute in the Riddle object). Going forward one could also add authentication in the controller layer, add caching or add more presentation logic. Let the model do its job of just telling the controller if the guess is correct or not for a riddle. The controller and view then deal with how to show the user that result. (e.g. Internationalize the text, style the text shown in the view or return the response in different formats like JSON/XML/HTML or maybe on a correct guess inform some other 3rd party service that the guess is correct)
Read more about the MVC pattern here and some things it enables us to achieve here
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
As I understand it, routes will take you from a starting point to a controller, and an action. The action brings up the associated views; so what if I don't need any views for my controller, and just want to just call a controller's underlying method, without rendering the view or route.
Lets say I have a FoodsController with several methods, and there exists methods cake, pizza, and chips within that controller. Each one queries the database for a secret message and stores it in a variable, but the request for this is going to come from some other part of our application.
To accomplish this am I supposed to use a route for this or some kind of dot syntax such as food.cake().
So I guess what I am trying to say is, hey "Server" go do this and come back to where you left off once its done.
Controller are only for URL endpoints. For example if you hit http://my.app/my_route, you need to map the my_route part to a controller action in your routes.rb file. But what happens if you type this into your browser? You'll want to see something right? So you need to return some data (json, html, erc). You can use render for this.
This is different to writing 'normal' Ruby code, i.e. Ruby outside a web framework. Do you understand what a class is and how the following works?
class MyClass
def initialize
end
def my_method
puts "my_method_called"
end
end
MyClass.new.my_method # => "my_method_called"
This is very basic Ruby and works in Rails as well, although there are some rules about where code needs to be written.
By the way, if you really want to make a controller action that renders nothing, just use:
render text: "", status: 204
return false
The status: 204 means "No Content".
You can use render json or text, if the method does not render anything, I think it should be private.
In your example you could use the cake method in another controller like so:
cake = Food.cake
Please note that this method should live in the food model and not the controller, since you do not need a view.
at https://www.codecademy.com/en/courses/learn-rails/lessons/start/exercises/start-views, the controll action is described as 'pages#home':
Well done! Now when a user visits http://localhost:8000/welcome, the route
get 'welcome' => 'pages#home'
will tell Rails to send this request to the Pages controller's home action.
but when I made the controller I did rails generate controller Pages which is uppercase.
pages_controller.rb:
class PagesController < ApplicationController
def home
end
end
Is the pages part of pages#home determined by the first part of pages_controller.rb, ignoring the _controller.rb end?
What happens if I change pages_controller.rb to renamedpages_controller.rb but leave the class name as PagesController?
thank you
Action Controller is the C in MVC. After routing has determined which controller to use for a request, your controller is responsible for making sense of the request and producing the appropriate output. Luckily, Action Controller does most of the groundwork for you and uses smart conventions to make this as straightforward as possible.
Controller Naming Convention
The naming convention of controllers in Rails favors pluralization of the last word in the controller's name, although it is not strictly required (e.g. ApplicationController). For example, ClientsController is preferable to ClientController, SiteAdminsController is preferable to SiteAdminController or SitesAdminsController, and so on.
Following this convention will allow you to use the default route generators (e.g. resources, etc) without needing to qualify each :path or :controller, and keeps URL and path helpers' usage consistent throughout your application. See Rails Guides.
When a request is made like: http://localhost:8000/welcome, it matches a route in the routes.rb file where the route is mapped to a controller and an action.
In your routes file, you have:
get 'welcome' => 'pages#home'
get 'welcome' part matches with the url .../welcome and map this request to pages#home where pages is the controller name and home is an action (a method defined in pages_controller). This is Rails convention to name the controllers like this: ControllerName_controller.rb. So, basically pages is your controller's name and the last _controllers is common to each and every controller in your Rails application.
What happens next is, this action of the controller do some work and talk to the model/database and build the required variables/data that will be passed to a view. According to Rails convention, there has to be a matching view file like: home.html.erb which will render the response to the browser.
There are other ways to render different partials and views in different ways, but if you follow the Rails convention, then it becomes very easy to understand and work with different Models, Views and Controllers in Rails. This is called: Convention Over Configuration.
When you follow the Rails convention for naming things, Rails does a lot of work and configuration for you for free to make your life easier.
When you have get 'welcome' => 'pages#home' in your routes file, then when a request: /welcome comes, it maps to pages_controller and it will look for the pages_controller.rb file under the app/controller/. If you rename this to something else, then the program will not find it as it expected and will throw you an error and your request will not be completed.
Your controller's name has to match with the class name of that controller, This is also a Rails convention. If you change any one of them, then you will get an error and your request will fail.
Yes. and #home is the "action" in PagesController
You get a uninitialized constant PagesController error
So, your controllers should always be in the form NameController defined in name_controller.rb, and actions as public methods in NameController.
I have product with a foreign collection_id key
I want to pass an id to a controller.
To do so i have the following routes for my controller :
controller :magasin do
get "magasin" => "magasin#index"
end
The only view in my controller is magasin/index.html.erb
The link to magasin is link_to collection.nom, magasin_path(collection)
This kind of syntax usually works in controllers with models. Here my link is : http://localhost:3000/magasin.2 instead of http://localhost:3000/magasin/2
Later on i will need to call the same view with product_kind_id instead of collection_id and i will add sort by name/price ....
How can i have the ID as a normal argument (/:id)instead of a type(.id)?
A popular URL schema to follow is RESTful routing. Rails has this built-in and will set it up for you if you initialize your resource via rails generate scaffold Magasin nom:string.
If you put resources :magasins in your routing file, it will route /magasins to MagasinsController#index and /magasins/1 to MagasinsController#show with params[:id] set to "1". It will also set up a few other routes that will be useful in the future but for now will just raise an action not found exception.
You don't want to use the dot as an argument delimiter, since Rails places what comes after the dot in the request.format method or just in params[:format] (ordinarily accessed through the respond_to method that comes with the generated scaffolds). Save that dot for later when you are working on delivering alternative display formats like XML and JSON.
I realize I've said a lot in a small space, so feel free to ask any follow up questions once you've consulted the Rails Guide on the issue, and I'll be very glad to help!