Ruby on Rails

From Sinfronteras
Revision as of 17:51, 21 June 2020 by Adelo Vieira (talk | contribs) (Adelo Vieira moved page Rails to Ruby on Rails)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search



https://guides.rubyonrails.org/getting_started.html

https://en.wikipedia.org/wiki/Ruby_on_Rails

Ruby on Rails, or Rails, is a server-side web application framework written in Ruby under the MIT License. Rails is a model-view-controller (MVC) framework, providing default structures for a database, a web service, and web pages. It encourages and facilitates the use of web standards such as JSON or XML for data transfer, HTML, CSS and JavaScript for user interfacing.



Installation

Ruby installation:

sudo apt install ruby


Rails installation:

sudo apt install ruby-railties
sudo apt-get install rails


For gem installation:

sudo apt-get install gem
sudo apt-get install nodejs
sudo gem install bundler



How to create a Rails Application

When you install the Rails framework, you also get a new command-line tool, rails, that is used to construct each new Rails application you write.

Why do we need a tool? Why can't we just hack away in our favorite editor and create the source for our application from scratch? Well, we could just hack; after all, a Rails application is just Ruby source code. But Rails also does a lot of magic behind the curtain to get our application to work with a minumum of explicit configuration. To get this magic to work, Rails needs to find all the various componenets of your application. Aas we'll see later, this means we need to create a specific directory structure, slotting the code we write into the appropriate places. The rails command simply creates this directory structure for us and populates it with some standards Rails code.

To create your first Rails application:

rails new myrailsapp

The above command has created a directory named myrailsapp.

Examine your installation using the following command:

rake about

Once you get rake about working, you have everything you need to start a standar-alone web server that can run our newly created Rails application. So, let's star our demos application:

rails server

Rails 4.2.10 application starting in development on http://localhost:3000

At this point, we have a new application running, but it has none of our code in it.



Hello Rails

Let's start by creating a "Hello, world!"

Rails is a Model-View-Controller framework. Rails accepts incoming request from a browser, decodes the request to find a controller, and calls an action method in that controller. The controller then invokes a particular view to display the results to the user. To write our simple "Hello World!" application, we need code for a controller and a view, and we need a route to connect the two. We don't need code for a model, because we're not dealing with any data. Let's start with the controller.

In the same way that we used the rails commands to create a new Rails application, we can also use a generator script to create a new controller for our project. This command is called rails generate . So, to create a controller called say, we run the command passing in the name of the controller we want to create and the names of the actions we intend for this controller to support:

rails generate controller Say hello goodbye
      create  app/controllers/say_controller.rb
       route  get 'say/goodbye'
       route  get 'say/hello'
      invoke  erb
      create    app/views/say
      create    app/views/say/hello.html.erb
      create    app/views/say/goodbye.html.erb
      invoke  test_unit
      create    test/controllers/say_controller_test.rb
      invoke  helper
      create    app/helpers/say_helper.rb
      invoke    test_unit
      invoke  assets
      invoke    coffee
      create      app/assets/javascripts/say.coffee
      invoke    scss
      create      app/assets/stylesheets/say.scss


Notice the files that were generated for the rails generate command. The first source file we'll be looking at is the controller:

app/controllers/say_controller.rb
class SayController < ApplicationController
  def hello
  end

  def goodbye
  end
end

SayController is a class that inherits from ApplicationController, so it automatically gets all the default controller behavior. What does this code have to do? For now, it does nothing, we sinply have empty action methods named hello() and goodbye(). To understand why these methods are named this way, we need to look at the way Rails handles requests.



Rails and Request URLs

Like any other web application, a Rails application appears to its users to be associated with a URL. When you point your browser at that URL, you are talking to the application code, which generates a respondse to you.

Let's try it now. Navigate to the URL http://localhost:3000/say/hello

You'll see something that looks like this:

Rails sey hello1.png



Our first action

At this point, we can see not only that we have connected the URL to our controller but also tat Rails is pointing the way to our next step, namely, to tell Rails what to display. That's where views come in. Remember when we ran the script to create the new controller? That command added several files and a new directory to our application. That directory contains the template files to the controller's view. In our case, we created a controller named say, so the view will be in the directory app/views/say.

By default, Rails looks for templates in a file with the same name as the action it's handling. In our case, that means we need to replace a file called hello.html.erb in the directory app/views/say. (Why .html.erb? We'll explain in a minute.) For now, let's just put some basic HTML in there:

app/views/say/hello.html.erb
<h1>Hello from Rails!</h1>

Save the file hello.html.erb and refresh your browser.

In total, we've looked at two files in our Rails application tree. We looked at the controller, and we modified a template to display a page in the browser.

These files live in standard locations in the Rails hierarchy: controllers go into app/controllers, and views go into sub-directories of app/views:

.
├── app
│   ├── assets
│   │   ├── images
│   │   ├── javascripts
│   │   │   ├── application.js
│   │   │   └── say.coffee
│   │   └── stylesheets
│   │       ├── application.css
│   │       └── say.scss
│   ├── controllers
│   │   ├── application_controller.rb
│   │   ├── concerns
│   │   └── 'say_controller.rb'
│   ├── helpers
│   │   ├── application_helper.rb
│   │   └── say_helper.rb
│   ├── mailers
│   ├── models
│   │   └── concerns
│   └── views
│       ├── layouts
│       │   └── application.html.erb
│       └── say
│           ├── goodbye.html.erb
│           └── 'hello.html.erb'
├── bin
│   ├── bundle
│   ├── rails
│   ├── rake
    .
    .
    .



Making it dynamic

So far, our Rails application is pretty boring, it just displays a static page. To make it more dynamic, let's have it show the current time each time it displays the page.

To do this, we need to change the template file in the view, it now needs to include the time as a string. That raises two questions. First, how do we add dynamic content to a template? Second, where do we get the time from?



Dynamic content

There are many ways of creating dynamic templates in Rails. The most common way, which we'll use here, is to embed Ruby code in the template. That's why we nemed our template file hello.html.erb; the '.html.erb suffix tells Rails to expand the content in the file using a system called ERB.

ERB is a filter that is installed as part of the Rails installation that takes an .erbfile and outputs a tranformed version. The output file is often HTML in Rails, but it can be anyting. Normal content is passed through without being changed. However, content between <%= and %> is interpreted as Ruby code and executed. The result of that exwcution is converted into a string, and that value is subtituted in the file in place of the <%=...%> sequence. For example, chage hello.html.erb to display the current time:

app/views/say/hello.html.erb
<h1>Hello from Rails!</h1>
<p>
    It is now <%= Time.now %>
</p>
Rails sey hello2.png

Notice that if you hit Refresh in your browse, the time updates each time the page is displayed.



Adding the time

Our original problem was to display the time to users of our application. We now know how to make our application display dynamic data.

The second issue we have to address is working out where to get the time from.

We've shown that the approach of embedding a call to Ruby's Time.now() method in our hello.html.erb template works. Each time we access this page, the user will see the current time substituted into the body of the response. And for our trivial application, that might be good enough. In general, though, we probably want to do something slightly different. We'll move the determination of the time to be displayed into the controller and leave the view with the simple job of displaying it. We'll change our action method in the controller to set the time value into an instance variable called @time.

app/controllers/say_controller.rb
class SayController < ApplicationController
  def hello
    @time = Time.now
  end

  def goodbye
  end
end

In the .html.erb template, we'll use this instance variable to substitute the time into the output:

app/views/say/hello.html.erb
<h1>Hello from Rails!</h1>
<p>
    It is now <%= @time %>
</p>

When we refresh our browser, we eill again see the current time, showing that the communication between the controller and the view was succesfull.

Why did we go to the extra trouble of setting the time to be displayed in the controller and then using it in the view? Good question. In this application it donen't make much difference, but by putting the logic in the controller instead, we buy ourselves some benefits. For example, we may want to extend our application in the future to support users in many countries. In tat case, we'd want to localize the display of the time, choosing a tie appropriate to their time zone. That would be a fair amount of application-level code, and it would probably not be appropriate to embed it at the view level. By setting the time to display in the controller, we make our application more flexible, we can change the time zone in the controller without having to update any view that uses the time object. The time is data, and is should be supplied to the view by controller. We'll see a lot more of this whewn we introduce models into the equation.



Linking pages together

Normally, each page in your application will correspond to a separate view. In our case, well also use a new action method to handle the page (although that isn't always the case, as we'll see later in the book). We'll use the same controller for both actions. Again, this needn't be the case, but we have no compelling reason to use a new controller right now.

We already defined a goodbye action for this controller, so all that remains is to create a new template in the directory app/views/say. This time it's called goodbye.html.erb because by default templates are named after their associated actions:

app/views/say/goodbye.html.erb
<h1>Goodbye!</h1>
<p>
    It was nice having you here.
</p>

http://localhost:3000/say/goodbye

Rails say hello3.png

Now we need to link the two screens. We'll put a link on the hello screen that takes us to the goodbye screen, and vice versa. In a real application, we might want to make these proper buttons, but for now we'll just use hyperlinks.

We already know that Rails uses a convention to parse the URL into a target controller and ac action within that controller. So, a simple approach would be to adopt this URL convention for our links:

app/views/say/hello.html.erb
<h1>Hello from Rails!</h1>
<p>
    It is now <%= @time %>
</p>
<p>
    Say <a href="/say/goodbye">Goodbye</a>!
</p>

and the file goodbye.html.erb would point the other way:

app/views/say/goodbye.html.erb
<h1>Goodbye!</h1>
<p>
    It was nice having you here.
</p>
<p>
    Say <a href="/say/hello">Hello</a>!
</p>


This approach would certainly work, but it's a bit fragile. If we were to move our application to a different place on the web server, the URLs would no longer be valid. It also encodes assumptions about the Rails URL format into our code; it's possible a future version of Rails might change this.

Fortunately, these aren't risks we have to take. Rails comes with a bunch of helper methods that can be used in view templates. Here, we'll use the helper method link_to(), which creates a hyperlink to an action. (The link_to() method can do a lot more that this, but let's take it gently for now) Using link_to(), hello.html.erb becomes the following:

app/views/say/hello.html.erb
<h1>Hello from Rails!</h1>
<p>
    It is now <%= @time %>
</p>
<p>
    Time to say
    <%= link_to "Goodbye", say_goodbye_path %>!
</p>

There's a link_to() call within an ERB <%=...%> sequence. This creates a link to a URL that will invoke the goodbye() action.

We generated the link this way:

link_to "Goodbye", say_goodbye_path

If you come from a language such as Java, you might be surprised that Ruby doesn't insist on parentheses around method parameters. You can always add them if you like.

say_gooodbye_path is a precomputed value that Rails makes available to application views. It evaluates to the /say/goodbye path. Over time you will see that Rails provides the ability to name all the routes that you will be using in your application.

We can make the corresponding chage in goodbye.html.erb:

app/views/say/goodbye.html.erb
<h1>Goodbye!</h1>
<p>
    It was nice having you here.
</p>
<p>
    Say <%= link_to "Hello", say_hello_path %>! again.
</p>
Rails say hello4.png



Playtime

Here's some stuff to try on your own:

  • Experiment with the follosing expressions:
    • Addition: <%= 1+2 %>
    • Concatenation: <%= "cow" + "boy" %>
    • Time in one hour: <%= 1.hour.from_now.localtime %>


  • A call to the followingg Ruby method returns a list of all the files in the current directory:
@files = Dir.glob('*')
use it to set an instance variable in a controller action, and then write the corresponding template that displays the filename in a list on the browser.
Hint: you can iterate over a collection using something like this:
<% for file in @files %>
  file name is: <%= file %>
<% end %>
You might want to use <ul> for the list.
You'll find hints at http://www.pragprog.com/wikis/wiki/RailsPlayTime



The story so far - What we just did

We constructed a toy application that showed us the following:

  • How to create a enw Rails application and how to create a new controller in that application.
  • How to create dynamic content in the controller and display it via the view template.
  • How to link pages together.


Let's briefly review how our current application works:

  • Rails then matches the route pattern, which it previously split into two parts and analyzed.
The say part is taken to be the name of a controller, so Rails creates a new instance of the Ruby class SayController' (which it finds in app/controllers/say_controller.rb).
  • The next part of the pattern, hello', identifies an action. Rails invokes a method of that name in the controller. This action method creates a new time object holding the current time and tucks it away in the @time instance variable.
  • Rails looks for a template to display the result. It searches the directory app/views for a subdirectory with the same name as the controller (say) and in that subdirectory for a file named after the action (hello.html.erb).
  • Rails processes this file through the ERB templating system, executing and embedded Ruby and substituting in values set up by the controller.
  • The result is returned to the browser, and Rails finches processing this request.