Category: Ruby
Different ways to invoke a method in Ruby
1 2 3 4 5 6 7 |
class Person def my_name “Diana" end end diana = Person.new |
-
(Single run time) Using dot notation and calling the method on the object:
1diana.my_name - (Persist name of method to database) Using send method:
1diana.send(:my_name) -
Get the method and call it like a Proc:
1diana.method(:my_name).call -
Not good practice but useful sometimes. (Self-modifying method code):
1eval “diana.my_name"
Differences between class, object and module in Ruby
Ruby is a class-based object-oriented programming language. Meaning that every object is an instance of a class, and a class defines the state (variables) and behaviours (methods) of an object. An object is an entity with state and behaviour, as defined by its class.
Rails Portfolio Project – Recipe Manager – Walkthrough
Rails Portfolio Project – Recipe Manager
Recipe Manager was built using Ruby on Rails framework and Bootstrap. All users can safely signup, login and logout. I created authentication and authorization methods without using any gem. Recipe Manager include a third party signup/login via Github thanks to the OmniAuth gem.
Users can check the recipes, rate and comment them but only admin users can create and edit the recipes and the categories. The user can browse recipes by name and author and all the comments by author and recipe. The app include reasonable validations for its forms and an ActiveRecord scope method to get the newest recipe that can be seen in its own URL, in this case: http://localhost:3000/newest_recipe.
My models:
User
- Has many recipes
- Has many comments
- Has many ratings
- Attributes: name, email, password_digest, admin, and finally I added uid and provider for the signup/login with OmniAuth.
Recipe:
- Belongs to a user
- Has many recipe_ingredients
- Has many ingredients through recipe_ingredients
- Has many recipe_categories
- Has many categories through recipe_categories
- Has many comments
- Has many ratings
- Attributes: name, cooking_time, servings, directions, date created
Ingredient
- Has many recipe_ingredients
- Has many recipes through recipe_ingredients
- Attributes: name
RecipeIngredient
- Belongs to recipe
- Belongs to ingredient
- Attributes: quantity.
Category
- Has many recipe_categories
- Has many recipes through recipe_categories
- Attributes: name
RecipeCategory
- Belongs to Recipe
- Belongs to Category
Comment
- Belongs to user
- Belongs to recipe
- Attributes: content
Rating
- Belongs to user
- Belongs to recipe
- Attributes: score
Generate my new application:
1 |
rails new recipe-manager |
Generate my models with their associations and create my db:
1 |
rails g model ModelName attribute:type |
*Adding :default => true to boolean in existing Rails column
Implementing a sign-in, login and logout functionality:
In order to encrypt the passwords I will use the gem bcrypt, include “has_secure_password” in my User model and have a password_digest attribute in my users table.
Sign in with Github
- Add to your gemfile the OmniAuth gem and the provider-specific OmniAuth gem, in this case “omniauth-github”, and run bundle install.
- Create a file named config/initializers/omniauth.rb. I will contain the following:
- Create an application in Github.
[Settings/Developer Settings/OAuth Apps/Register a new OAuth application]
In homepage url enter: https://localhost:3000/
In the Authorization url: http://localhost:3000/auth/github/callback
After creating the app you get a client ID and a Client secret.
- Add dotenv-rails to your Gemfile and run bundle install.
- Create a file named .env at the root of the application and add your Github credentials.
- Add .env to your .gitignore file.
- Create a link to login via Github
- The User model needs these attributes, all strings: name, email and uid, that it is the user’s ID on Github. *I added a provider attribute later on.
- Create the route where Github will redirect users in the callback phase of the login process.
- And in our Sessions controller we find or create the user who logging via github.
- In our User model:
I want to add some helpful links:
Student Data Bank Walkthrough
Sinatra Portfolio Project
I would like to make a Content Management System for my daughter’s nursery. They keep the daily information about the children in notebooks full of very easy to lose post its and hope this app can help with it. The daily information will be referred to as activities.
-Create a repository in Github.
-The project structure following the MVC conventions.
-Set my environment and my config.ru. I am following the Modular Sinatra Pattern and having a config.ru
file is one convention of it. The purpose of config.ru is to detail to Rack (Sinatra gem is built on top of Rack) the environment requirements of the application and start the application, mount my application controllers. Rack is a convention, or specification, that lets web applications “plug” into a common interface for handling HTTP requests. To actually serve requests, we need a web server — something that can translate HTTP requests into Ruby calls. My gem ‘thin’ is a web server that do this job.
-Create my Gemfile with all gems that I am going to run trough Bundle, which is set up in my environment file.
Here are the gems I want to use:
sqlite3: sqlite is a library that implements a SQL database engine. sqlite is my database adapter gem.
thin: it is a web server.
I think that I will need at least 3 models, User, Activity and Student.
Is it works?
I am using Visual Studio Code and after creating the structure of my project with very basic info I tried to run shotgun and was getting the following error:
I had a server running in the background. After trying a lot of different things I could stopped it with the following I found in StackOverflow:
Ran lsof -i :9393
(9393 is the port I ran it on).
I killed the process using kill -9 *pid*
. My pid was: 58152.
When I ran lsof -i :9393
again, nothing showed up.
I then ran shotgun and everything works fine now.
Authentication system
Enable sessions in your AppController and use the gem bcrypt. Make sure your user model has_secure_password and that on your users table you store the password like “password_digest“.
Protecting the session secret by Martin Fowler:
I changed my configuration to look like this:
The password fails safe to a secure hex value if SESSION_SECRET
is unset.
Database
Create a Database folder (db), run your migrations to create your tables. I have created one table for the students, another table for my users and a last one for the activities.
I run:
rake db:create_migration NAME=create_students
rake db:create_migration NAME=create_users
rake db:create_migration NAME=create_activities
Then modify my migration tables according to my needs.
And finally run rake db:migrate, and all your tables will be added.
Play with my models and the database.
I run tux in my console but I got the following error
config.ru does not support require_relative so I changed my link and everything works fine!
Now it is time to be more creative and design my routes in the controllers and my views. I am using Bootstrap.
To check this project follow the link.
Artify walkthrough
Programming my classes
After all the previous steps now I have pretty clear how I am going to structure my code.
I want a CLI that displays art exhibitions and gives to the user more info about the one it chooses. I am going to scrape from a public website all the info concerning the art events (Artlyst).
I want three classes: a CLI, an exhibition one and a scraper.
This three classes will live inside a lib folder.
I finally changed the CLI class name for artify in case I want to publish my gem in RubyGems.org. So I have threes classes: artify, exhibition and scraper.
Let’s start coding!
To check my code go to my Github repository.
After programming my classes I require them inside the environment.rb file.
And that’s it!
If you want to play with this gem please check this link: readme page.
Hope it was helpful!
The executable file
I create a folder bin and create inside of this folder an executable file called in this case as the gem, ‘artify’.
When I type: $ruby bin/artify, everything run but I don’t want this. I want that the user from the bash can type: $ ./bin/artify.
So I type:
$ cd bin/
$ ls -lah
Ad I can see that artify doesn’t have executable permissions. To change this I type:
$ chmod +x artify
$ ls -lah
This executable file is not a ruby file so I have to include at the top the following:
#!/usr/bin/env ruby
Then I require our environment file to use all the gems already installed.
In this file I want to run for my still imaginary CLI class. I want to write here something like: CLI.new.run.
So, at this point, I know I want a class CLI, where I am going to build all the methods and keep all data to run my CLI.
I finally changed this name for ‘artify’ in case I want to publish it in RubyGems.org.