Wednesday, March 22, 2023 | Permalink
Continue from previous article, let's add one more route /about/company
. You know the steps now to make this route working in Rails application.
First, add a route entry like this.
Rails.application.routes.draw do
get "/about" => "about#index"
get "/about/company" => "about#company"
end
Second, we already have the AboutController
. So, we just now need to add company
method.
class AboutController < ApplicationController
def index
end
def company
end
end
Finally, we already have about
folder. So, we just need to create company.html.erb
with following code inside this file.
Visiting the /about/company
should display this About company
header in the browser.
Labels: rails
Sunday, March 19, 2023 | Permalink
Open the http://localhost:3000/about in the web browser. Obviously, you get the No route matches [GET] "/about"
error. Because, this route doesn't exist.
The routes for the Rails application are defined in config/routes.rb
file. Open this routes.rb
file in the text editor. You should see the following code.
Rails.application.routes.draw do
# Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html
# Defines the root path route ("/")
# root "articles#index"
end
Remove all the comments from this code.
Rails.application.routes.draw do
end
Add the /about
route line like this.
Rails.application.routes.draw do
get "/about" => "about#index"
end
This line means, when GET /about
is called, run the about
's index
method. This about
is a controller (or class) and index
is an action (or method within class).
Reload the /about
in the browser. You should now get uninitialized constant AboutController
error. Because, we do not have AboutController
in about_controller.rb
file.
All the controllers for the Rails application are defined within app/controllers
folder. In app/controllers
, create a file with name about_controller.rb
. Open this file in text editor and write the following code.
class AboutController < ApplicationController
end
We defined the AboutController
controller that Rails is looking for. This controller is extended with helpful functionalities from ApplicationController
controller provided by Rails.
Reload the /about
in the browser again. You should now get The action 'index' could not be found for AboutController
error. Because, AboutController
does not have index
action.
Let's define an empty index
method in this controller like this.
class AboutController < ApplicationController
def index
end
end
Reload the /about
in browser for one more time. You should now get No template for interactive request
error. Because, we do not have index.html.erb
template or view for the method to fulfil the request.
All the views for the Rails application are defined within app/views
folder. Create a file with name index.html.erb
in folder with name about
inside the app/views
folder. Here, we need to create about
folder first and then index.html.erb
file in this created about
folder. Open this file in the text editor and write the following code.
Reload the /about
in browser for the last time. You should see the About
header in browser now.
In summary, Rails check for the routes in routes.rb
file and run the associated action from given controller. Finally, with the help from associated view, request will be fulfilled.
Labels: rails
Tuesday, March 14, 2023 | Permalink
Go ahead and create a new Rails application using following command.
This will create a Rails application in hello-world
folder.
Go inside the hello-world
folder.
Run the created Rails application using following command.
This command boots up the server at http://localhost:3000. Open this in web browser and you should see the Rails default welcome page. If that is the case, you just have created your very first web application using the Rails framework.
Labels: rails
Wednesday, March 8, 2023 | Permalink
Vala is the programming language but the interesting one. After compilation, it produces the C code and then this C code further fed to C compiler to get the final output.
Create a dump.vala
file and write the following code. Nothing is new in this code and we already write this same code in previous articles.
public class Hello {
public string name;
public Hello(string name) {
this.name = name;
}
public void greet() {
stdout.printf("hello, %s\n", this.name);
}
}
int main(string[] args) {
string name = "world";
Hello hello = new Hello(name);
hello.greet();
return 0;
}
Let's run this file using Vala compiler but with -C
option.
This -C
flag outputs the C code into the file with same name as the Vala file i.e. dump.c
file. Open this dump.c
file and you should see the following code.
/* dump.c generated by valac 0.56.3, the Vala compiler
* generated from dump.vala, do not modify */
#include <glib-object.h>
#include <stdlib.h>
#include <string.h>
#include <glib.h>
/* ... more core ...*/
/* ... more core ...*/
/* ... more core ...*/
int
main (int argc,
char ** argv)
{
return _vala_main (argv, argc);
}
You don't have to worry about this C code and even you don't need to know this C code produced by Vala compiler. I show this step to you to give some background information such as Vala use GLib Object and GLib libraries extensively as you can see from the header files of this C code. Some of the code and syntax you'll going to use in Vala depends on these libraries and C in general. So, don't be surprise!
Apart from this, even though Vala is general purpose programming language, it is mainly used to develop the GUI application for the GNU/Linux system using GTK library as it has tight integration with GTK library and the ecosystem. elementary OS extensively use the Vala language to build most of their applications including the Pantheon, their desktop environment.
Vala gives nice abstraction like higher level languages such as Java and C# to make desktop application using GTK which is written in C language. That being said, let's continue with Vala language and build the hello, world desktop application using GTK library (GTK4).
Labels: gtk, vala
Saturday, March 4, 2023 | Permalink
In this article, we're going to do some structural changes in existing Hello.vala
file that we created in previous article. Following is the code we currently have in the Hello.vala
file.
public class Hello {
public void greet(string name) {
stdout.printf("hello, world\n");
}
public static int main(string[] args) {
string name = "world";
Hello hello = new Hello();
hello.greet(name);
return 0;
}
}
I don't think that main()
should be within the Hello
class as main()
has nothing to do with Hello
class and we should follow separation of concern.
public class Hello {
public void greet(string name) {
stdout.printf("hello, world\n");
}
}
public static int main(string[] args) {
string name = "world";
Hello hello = new Hello();
hello.greet(name);
return 0;
}
As main()
is not part of the class, we don't have to worried about public
and static
.
public class Hello {
public void greet(string name) {
stdout.printf("hello, world\n");
}
}
int main(string[] args) {
string name = "world";
Hello hello = new Hello();
hello.greet(name);
return 0;
}
Let's run this program and confirm the output. It should not effect the output as we did structural changes for refactor.
$ valac Hello.vala && ./Hello
hello, world
Yes, it is working!
Even further, I don't think we should have the main()
method within Hello.vala
file at all. Because, Hello.vala
file should suppose to the Hello
class and nothing else. main()
method is a special method and we should have it in the main.vala
file.
Let's create a new file with name main.vala
and cut-paste the main()
method from Hello.vala
file to newly created main.vala
file. After doing this modification, we should have the following code in the Hello.vala
file.
public class Hello {
public void greet(string name) {
stdout.printf("hello, world\n");
}
}
Following is the code we now should have in the main.vala
file.
int main(string[] args) {
string name = "world";
Hello hello = new Hello();
hello.greet(name);
return 0;
}
With these modifications, you or our colleague can easily guess from the file name that Hello.vala
should contains the Hello
class code and main.vala
should contains main()
method.
We now have two files instead of one. We need to compile both files at the same time otherwise it'll generate errors. In such a case, the command to run two or more file is follow.
$ valac Hello.vala main.vala -o Hello && ./Hello
hello, world
Here, we've compiled both Hello.vala
and main.vala
files using valac
compiler. After successful compilation it'll generate an object file (-o
) or an executable with name Hello
. You can give any name you like, but Hello
make more sense here. Finally, we're ran the executable and it print the hello, world as expected output.
Before I complete this article, I would like to cover one more concept in Vala and that is constructor. We'll cover the constructor in more details in future articles. But, in this article, I want to give a glimpse of it.
Continue with the name
variable in our hello, world example, instead of passing name
variable while calling the greet()
method, it make more sense to pass it while creating an object in main.vala
in following way.
int main(string[] args) {
string name = "world";
Hello hello = new Hello(name);
hello.greet();
}
Notice, I removed the name
from greet()
method call and now passed it while creating an object from the Hello
class. Based on this, we need to do some changes in Hello
class to accepts this modification.
First, let's define the class attribute or class variable with name name
in the Hello.vala
file.
public class Hello {
public string name;
public void greet() {
stdout.printf("hello, %s\n", name);
}
}
Next, let's define a method with name Hello()
i.g. same name as the class name that accepts the name
parameter with type of string. This is our constructor method and it'll accept the arguments passed while creating an object or instance of this class. We can assigned this passed argument to created class variable using this
keyword.
public class Hello {
public string name;
public Hello(string name) {
this.name = name;
}
public void greet() {
stdout.printf("hello, %s\n", name);
}
}
Finally, within greet()
method, instead of name
, we need to write this.name
to access the set value of the name
variable.
public class Hello {
public string name;
public Hello(string name) {
this.name = name;
}
public void greet() {
stdout.printf("hello, %s\n", this.name);
}
}
Our program now is back in shape to print the hello, world in the terminal. But, this type we've used class constructor in Vala. Let's run the programs and confirm.
$ valac Hello.vala main.vala -o Hello && ./Hello
hello, world
Yeah. It is working!
I don't want to hold you more with this article. Enjoy rest of the day. See you in the next chapter after sometime.
Labels: gtk, vala
Thursday, March 2, 2023 | Permalink
In this article, we're again going to write the hello, world program. But, this time with object-oriented paradigm. Create a new file with name Hello.vala
(H
is capital in file name) and open in your favorite text-editor.
Let's define a Hello
class with class
keyword. CamelCase is used to name the classes in Vala.
It is always good practice to use access modifiers with class while defining it such as public
, protected
, private
, etc. I don't have any reason to hide this Hello
class.
Class can have many things inside it. But, it is important to have the main()
method. Otherwise, our program wouldn't run! Let's add the minimal version of the hello, world program code we know from the previous section.
public class Hello {
int main(string[] args) {
stdout.printf("hello, world\n);
return 0;
}
}
But, this wouldn't work. Why? Because, method within class not run automatically. We need to either run by creating an instance of the class or mark it as static
as class method. We'll going to mark this method as static
.
public class Hello {
static int main(string[] args) {
stdout.printf("hello, world\n);
return 0;
}
}
As I said for the class, it is also good practice to define methods with access modifiers. In case of the main()
method, it must be public
otherwise you'll get the error.
public class Hello {
public static int main(string[] args) {
stdout.printf("hello, world\n);
return 0;
}
}
That's it! This is how you can write the hello, world program in Vala using object-oriented way. Let's run and confirm the output!
$ valac Hello.vala && ./Hello
hello, world
Yeah! The program work as expected.
Let's do the same modifications as we previously did after our hello, world program was written correctly. You're correct! We're going to define the greet()
method within Hello
class.
public class Hello {
public void greet() {
stdout.printf("hello, world\n");
}
public static int main(string[] args) {
stdout.printf("hello, world\n);
return 0;
}
}
Like I said previously, to call this greet()
method, we need to create an instance of class or an object using new
operator.
public class Hello {
public void greet() {
stdout.printf("hello, world\n");
}
public static int main(string[] args) {
Hello hello = new Hello();
hello.greet();
return 0;
}
}
Running this program should print the same hello, world as the output.
$ valac Hello.vala && ./Hello
hello, world
Next, let's define a name
variable with world
as the initial value to print the same hello, world text like we did previously.
public class Hello {
public void greet(string name) {
stdout.printf("hello, world\n");
}
public static int main(string[] args) {
string name = "world";
Hello hello = new Hello();
hello.greet(name);
return 0;
}
}
Again, running this program should print the same hello, world as the output.
$ valac Hello.vala && ./Hello
hello, world
With these changes for the hello, world program, let's take a break. We'll meet again in next article and do further modifications in this same hello, world program. The plan is to do some re-structure in next article.
Labels: gtk, vala