Thursday, February 13, 2014

Vim syntax highlighting is too slow?

In some cases, yes vim syntax highlighting is slow, especially with ruby file with inline javascript, css, erb and html in the same file. When Vim starts fresh it is not that slow but after some time you will feel it a bit sluggish while you navigate the file. For a quick solution, I used to close all buffers and start a new vim session.

Vim used a slow regexp parser to parse the code to provide language specific syntax highlighting. Starting from vim version 7.4 vim uses a new faster regular expression engine.

If you complain, like me, about vim sluggish syntax highlighting, go upgrade your vim to 7.4 or newer version and put the following line on your .vimrc, and you will notice the improvement in speed.

:set regexpengine=1

Monday, December 30, 2013

How to make UTF8 work with Ruby 1.9/2.0, Rails and Mysql

Storing and presenting UTF8 was always a problem especially when each component in your web development stack has partial support for UTF8.

The data entered in the forms on the web pages are valid utf8, and Mysql databases were encoded with utf8, but the Rails app with the original mysql gem (version 1) was storing data in  latin1 encoding into the utf8 tables! Somehow the data retrieved from Mysql was displayed properly in utf8 if I take care to remove encoding :utf8 from mysql gem database configuration, and set the html character set to utf8.

With Ruby 1.9/2.0 and Mysql2 gem, something went wrong and the data no longer displayed correctly. I found that the best solution to fix this problem is by configuring Mysql correctly and reinserting the data in the correct encoding.

1) First, backup your database.

2) Add the following configurations in Mysql my.cnf file, do not add [client] and [mysqld] just add the options in their respective directives;
[client]
default-character-set = utf8

[mysqld]
character-set-server=utf8
collation-server=utf8_general_ci


3) Dump the database but prevent Mysql from converting the encoding of the data.
mysqldump -u root -p --opt --default-character-set=latin1 --skip-set-charset DATABASE_NAME > DATABASE_NAME.sql
 

mysql -u root -p --default-character-set=utf8 DATABASE_NAME < DATABASE_NAME.sql
Don't forget to check your data thoroughly to make sure that all characters are displayed correctly.
 

Sunday, November 10, 2013

Install CoffeeScript on Mac OSX

CoffeeScript is a Node.js module and could be installed using the Node.js Package Manager, npm. To install CoffeeScript on Mac osx (tested on Lion) first install Homebrew package manager.
 
# Install Homebrew 
ruby < (curl -fsSk https://raw.github.com/mxcl/homebrew/go)
#Install Node.js 
brew install node
# Open .bashrc and add this line (create .bashrc if its not in your home directory already) export NODE_PATH=/usr/local/lib/node_modules
# Install NPM
curl https://npmjs.org/install.sh | sh
# Install CoffeeScript
npm install -g coffee-script  Related links: coffeescript.org , Frobitz

Sunday, December 14, 2008

Rails ActionController facelift using ResourceController and named_scope

I am pretty sure that it is not only my Rails controllers which changed appearance more than once during the past 3 or 4 years. Concepts like RESTful controllers, nested resources, ActiveRecord scoping kept on changing the way we build our Rails controller. Nowadays, my Rails controllers are barely similar to what they looked like 4 years ago.

During pre REST days, my controllers were so ugly and fat. with too many actions to count and do a lot more than the controller meant to do in an MVC framework. Then came RESTful controller which was really, really a nice way to help application designer to organize and "design" the application. RESTful controllers concept is revolutionary in that it simplified or abstract away the complexity of the application plumbing and repetitive routines and made my poor little mind focus on the application design instead.

And then came resources scaffold
The scaffold generator now do us all the work to have a nice RESTful controller that can CRUD your model and responds to HTML, XML, JS. But I need to confess that I've never liked generators. Heck, it is the only reason why I don't use IDEs. They pollute my code with lines I didn't write, and that's plain ugly. It is lovely to have your controller speak REST in XML, but it was not a good feeling when I see all those respond_to lines scattered all over my controllers at the time when my application is not yet designed to be used as such.

And what made it really worse is that most of the time the generated controller needed almost 80% editing, to scope my models I use in the controllers, like @site.pages, @user.posts, and to paginate results, set model attributes assignments..etc. So it was obvious that generators wouldn't cut it. We needed some help to abstract all the repetitive codes in our controller and find a solution for problems like relations aware controller that respect scoping, can deal with nested resource and namespaces. I am sure that any rails developer (or any MVC web developer) knows the kind of problem I am talking about.

Resource Controller plugin
More than a year ago I found some Rails plugins to do just that. But I was too skeptical to use them in production. Time passed and there are now a really good, tested and tried solution for the kind of problem I am talking about. It is called "Resource Controller".

It is a fine plugin written by James Golick. Thank you James. The other plugins like resource_this and make_resourceful were steps in the right direction but Resource_Controller is the way to go.
Link
After months of using it I feel pretty confident with resource controller. And as all tools that abstract away repetitive noise it allowed me to focus more on my application design and actually I developed more productive patterns in developing my application. Patterns that changed the face of my rails controllers beyond recognition. Here is a minimal Resource Controller.



1
2
class UsersController < ResourceController::Base
end

Suddenly, I had this ActiveRecord thrill again, but with Resource Controller this time. I bet this is the skinniest controller one could dream about. Come on Rails core team, when will we see Jamis' Resource controller merged!

Well the next thing to do is playing around and try to see how to solve the problems I mentioned above. But only after introducing my newest love, "Named scope". which prove very useful in DRYing my controller even more.

Named Scopes
I always thought that the best feature in ActiveRecord is scoping through associations. Like, '@user.posts.find(:all, :limit => 10)'. This feature alone is enough to use ActiveRecord. The next best ever feature in ActiveRecord is named_scope. I couldn't recommend enough using named_scope. Just use it. It is core since Rails 2.1.

Coupling named_scope with Resource Controllers really open new application design territory. Imagine the following requirement.
  • One pages controller that can be used to list all the pages in a portal
  • It could be used nested under users resource, so it should scope pages to user.
  • It should handle posts pending for approvals.
  • It should fetch the next and previous pages according to the context or the scope it works within, be it portal pages, users pages, or user's pending pages or portal's pending pages.

Let's build the controller
First we do the routes, a simple nested routes and then the controller.



1
2
3
4
5
6
7
8
map.resources :users do |user|
user.resources :pages
end
map.resources :pages

class PagesController < ResourceController::Base
belongs_to :user
end
This is the simplest form of controller to make it serve routes like /user/12/pages/new and do all the REST actions, be it scoped to user or not. But certainly life isn't that simple. What if you want to paginate results and get user by user_name instead of user_id like "/user/hany/pages".




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class PagesController < ResourceController::Base  
before_filter :set_scope
belongs_to :user

private

def parent_object
@parent ||= User.find_by_name(params[:user_id]) if params[:user_id]
end

def set_scope
@scope = @portal.pages
@scope = @scope.by_user(parent_object.id) if parent_object
end

def collection
@pages ||= @scope.paginate(:all, :page => params[:page])
end
end
Here I added some private methods. The parent_object method to get the parent object by name. I introduced the set_scope method which does set the scope (or context) of the collection set of pages we need to work with. Actually, parent_object and collection are both overridden methods of resource_controller. and set_scope method is mine, and I run it in a before_filter and use it in the controller to find the pages within the set scope. I could have just do scoping inside collection method, but later I will need to have a handle for the scope in different places in the controller other than "collection".

The set_scope method is interesting because I stack up the scope conditionally according to the context within which the controller is running. I mean if the controller is nested in users resource it will find params[:user_id] and the parent_object return a user object and then the @scope of users pages will be added. Which is a named scope in this case "Page.by_user()". I could have use parent_object.pages which is the natural association scoping of ActiveRecord I got with the "has_many :pages" but because my application serves several portals, and @portal got assigned according to subdomains on the application controller, I don't won't to loose the @portal scope '@portal.pages' so it was either make a named_scope for portals or users.

Notice here that @scope.find(:all, :conditions => {:user_id => parent_object.id}) will not do us any good because you will not be able then to narrow down those scopes by stacking them. But sure an inline or anonymous named_scope will suffice instead.

Now I need to make the controller serve pages pending for approvals and fetch the next and previous pages properly according to the scope. Some routes need to be set first. Changing the scope is only a matter of adding a new line to the set_scope method according to the passed params[], so all I need to do is passing non blank params[:pending]. Of course passing it hanged on the url like '/user/hany/pages?pending=1' is not an option. I need it to be clean like '/user/hany/pending_pages' and to say the truth it is not about cleanliness, it is about setting proper url automagically as I will show you later.




1
2
3
4
5
6
7
map.resources :users do |user|
user.resources :pages, :requirements => {:pending => false }
user.resources :pending_pages, :controller => 'pages', :requirements => {:pending => true }
end
map.resources :pages, :requirements => {:pending => false }
map.resources :pending_pages, :controller => 'pages', :requirements => {:pending => true }


Here I added pending_pages resources and pass explicitly the controller name because I will use my same pages controller. I made the resources properly set the pending parameter to true or false. I don't believe Rails 2.2 shallow routes option will spare me the pages resources repetitions. May be we need another way to make the parent resources optional?! but anyways, now that we have the routes properly set, let's see the controller.




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class PagesController < ResourceController::Base

before_filter :set_scope
belongs_to :user

private

def parent_object
@parent ||= User.find_by_name(params[:user_id]) if params[:user_id]
end

def set_scope
@scope = @portal.pages
@scope = @scope.by_user(parent_object.id) if parent_object
@scope = @scope.pending(params[:pending])
end

def collection
@pages ||= @scope.paginate(:all, :page => params[:page])
end

def route_name
params[:pending] ? 'pending_post' : 'post'
end
end

Here I added one line to set_scope to add the pending scope if the params[:pending] was true. But for a change I didn't check for params[:pending], instead I pass it to the named_scope which will check internally if it set or not and do the scope accordingly. Actually I did this in my real application to not be forced to make another not_pending named_scope. Because in real life you will need not to publish unpublished pages. errr.. ok, i mean the pending scope is unlike users scope, which is like, "if parent user is not set just show all the pages anyway", this will not work here, we need it to be, "if pending status is false just list only the published pages". And now it's a good chance to demonstrate how to pass arguments to named_scope.



1
2
3
4
class Page < ActiveRecord::Base
named_scope :by_user, lambda{|u| {:conditions => {:user_id => u} } }
named_scope :pending, lambda{|s| {:conditions => {:published => s} } }
end
where is the next and previous links?
It is a very healthy practice to provide a next and previous item links in your show item page. For many obvious reasons, for one is to spare the user going back to pages list which will stress your server as well. Just give her the links or previous and next page. But you have to prepare the links first in the show action. In Resource controller actions are abstracted so you don't have to do the repetitive code each time, just do what is specific to each controller action. In this case I need the show action to fetch the next and previous page according to the scope within which the pages controller works. And do that just before rendering the template or to be precise just before responding.




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class PagesController < ResourceController::Base

before_filter :set_scope
belongs_to :user

show do
before do
@next_item = @scope.next_to(object).first
@previous_item = @scope.previous_to(object).first
end
end

private

...

end
This was easy, just assign your next and previous variables to the first item returned by the named scopes "next_to" and "previous_to". To be precise, named_scope are not results set (Array) so we need to do ".find(:first)" or ".first" as of Rails 2.1, to just hit the database and fetch the records. I passed 'object' to the named scopes which is a method refers to @page, you can override this method just to find your page the way you want it, say you want to find_by_premalink, for example. The following are how those named scopes were implemented.




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Page < ActiveRecord::Base
named_scope :by_user, lambda {|u| {:conditions => {:user_id => u} } }
named_scope :pending, lambda {|s| {:conditions => {:published => s} } }
named_scope :next_to, lambda {|item|
{
:limit => 1,
:conditions => [ 'id > ?',item.id] ,
:order => 'id asc'
}
}

named_scope :previous_to, lambda {|item|
{
:limit => 1,
:conditions => ['id < ?', item.id] ,
:order => 'id desc'
}
}
end
Well, that's all well a good, but pretty DRY controllers are not the end of all our sufferings, are they? the views are always the primary cause of migraine in web development, at least they are for me. This resource controller is doing all what I asked it for. But how the views will handle such complex set of nested and or conditional scoping? When I first asked myself this question and start to figure out what may the solutions be. I found my self saying, Hell, no no, I will not make all those conditions and the ever nested loops of if/else to just decide which url routes I shall use in the new and edit forms. But Alhamdulillah, thanks God, there is this most useful piece of code that ever existed in Rails view helpers, excuse the drama but it is really that good, it is the "Urligence" library which is a url helper that helps you generating urls! It is included in Resource Controller, so no need to download. This url helper is not only useful in views it is already used in the controller in redirect_to statements taken place deep inside resource controller, like after create for example it is by default redirect to show action. In this case which show route will it use? In our case we have at least three show routes:
/pages/:id
/user/:user_id/pages/:id
/user/:user_id/pending_pages/:id
The surprise is that Resource Controller will know exactly which route to use according to the context. Actually it does it using Urligence url helper. The helper themselves are too easy. You will have object_url and collection_url, that's it. In Rails resources native tongue: object_url to refer to any member action, and collection_url to refer to any collection action. And of course the HTTP verb or the request method will decide which action to address, like, post to collection_url to create and put to object_url to upate and such.




1
2
3
4
5
6
7
<% form_for :page, @object, :url => object_url, :html => {:method => :put} do |f| %>
<%= f.text_field :title %>
<%= submit_tag "Save" %> or <%= link_to "Cancel", object_url %> and go back to page.
<% end %>

<%= link_to("Next", object_url(@next_item)) if @next_item %>
<%= link_to("Previous", object_url(@previous_item)) if @previous_item %>
These snippets from the edit and show templates are pretty much clear and amazing at the same time.

What about controlling the flow of the application. What if you need to change the default flow of the resource controller and make the "delete" action redirect to the next item show page if it exists and to the pages index if there is no next page.




1
2
3
4
5
6
7
8
9
10
11
12
delete do
before do
@next_page = @scope.next_to(object).first
end
after do
if @next_page
redirect_to object_url(@next_page)
else
redirect_to collection_url
end
end
end
All we need to do is to explicitly add the delete action. I tried to fetch the next item in the current @scope "before" deleting. And "after" deletion I should redirect properly as required.

There are lot more in ResourceController, it lets you customize flash message for success and failure, add responds to methods, respect namespaces automagically and more.

Anyway, that's it regarding how ResourceController and Named Scopes has changed the way I write Rails ActionControllers. for more information refer to the following links:

Sunday, June 22, 2008

Working with remote Git branches

You are about to start a brand new module in your project. Your project is already in production. You cannot develop and test your new module while fixing minor bugs in your production line. You need branching.

So suppose we are on master branch and you have remote "origin" repository. And we need to create a new remote branch called "search" to track the development of the search module. the plan is to develop the search module on this branch "search" locally and push updates remotely for testing on a staging server or just to share the search module code with a colleague developer without polluting the master production branch with the unfinished yet search module.

First make sure your master branch are up to date.
$ git pull origin master
Then push your master branch to a new remote branch, notice that you enter the destination remote repository name first "origin" then the source which is local branch "master" then a column ":" and the path of the new remote branch we want to create "refs/heads/search"
$ git push origin master:refs/heads/search
After pushing and creating the remote "search" branch, we will examine the remote "origin.
$ git remote show origin
* remote origin
URL: ssh://ibrahim@kenana.org/git/portals.git
Remote branch(es) merged with 'git pull' while on branch master
master
New remote branches (next fetch will store in remotes/origin)
search
Tracked remote branches
master
Notice how there is a new remote branch and that next time we use "git fetch" the new remote branch "search" will be stored in remotes/origin.
$ git fetch
* refs/remotes/origin/search: storing branch 'search' of ssh://ibrahim-ahmed.com/git/portals
commit: 8bd83c4
Now we have all the remote origin branches stored locally in "refs/remotes/origin" including "search" branch, but there is no local branch yet to track it.

To make a branch out of the remote branch which is stored locally, we will use "git checkout", the "-b" search" is the argument we use to create a local branch. "--track" parameter is used to link the local branch "search" with the remote branch "origin/search"
$ git checkout --track -b search origin/search
Now you should be on "search" branch.
$ git branch
master
* search
Now you can edit, commit, pull and pull to your heart content. And when you need to fix something on remote/master which is used for production server, you just use the following to fix the bug, push to the remote master and then back again to your search module.
$ git checkout master
$ vim files_to_be_fixed
$ git commit -a -m "just fixed the bug"
$ git push origin master
$ git checkout search
Check SourceMage Git manual for further advanced usage examples.

Sunday, April 6, 2008

Design an accessible Website using CSS

Designing the web page layout is an essential step in the website development. It affects almost every aspect of the website development, from styles, content types, photos, search engine optimization SEO, and definitely the website user friendliness.

There were a deep misunderstanding to the Web as a capable media for content publishing and a potent marketing tool, the graphics designer were using the Internet shamelessly as a mere brochure. I mean they were designing a brochure (a real one) and convert it to a web page using one of the web graphics application like Fireworks, or Dreamweaver. The conversion was usually done using image maps and slicing. Graphics slicing were obscenely abused, I saw many crimes where developer create or import a brochure into Photoshop and start slicing the image into small chunks of gif images, and export the whole design as an HTML. At best they export part of the design from Photoshop and integrate the dynamic parts into the body area of the layout.

Leaving Photoshop and brothers to do the HTML is not a good idea. Really. It is like translating an English site to Arabic language using a machine translator. The end product is gibberish. The sliced layout with mixed Html and images, is harmful for many reasons I will try to highlight them in this post.

HTML is not a presentation layer. Using HTML to design the layout is not the job of HTML. HTML is an XML format to define the data structue of the web page document. I like to describe a document in terms of paragraphs, menu list, sidebar, blockquotes, ordered list, unordered list, those elements are unsurprisingly the elements of HTML. But how you want to render or represent the menu lists, the sidebar, the blockquote, representing those elements is entirely the job of CSS (Cascading Style Sheet) and not the HTML.

What made me a true believer of CSS layout, CSS styling and using HTML only in representing the document in its basic elements is that our eyes are not the only consumer of the web page we develop, there are others, like; search engines crawlers, blinds, mobile web browsers, printers..etc all those consumers will not see or use our graphics as we intended for it to be seen

Search engines will not understand that my website is concerned about farming and agriculture if I did export the titles of the agriculture sections as images from Photoshop. So People searching Google will not find your site only because Google didn't find thesearch keywords in your site. The same goes for blinds. There are using the Internet in a daily basis in Egypt, Arab countries and around the world. For blinds they use Text to speech software to convert "text" to speech, it will simply ignore images, so blinds will miss your website sections menu if it was made of a bunch of images racked into an HTML Table.

Another reason for using CSS is that blinds are needlessly forced to listen to a lot of repeatable content on the top of each of our pages, for no reason but that HTML is rendering first things first, so if we want to put the site menu, contact us, about us, login, and sidebars on top of the page, you could render it on top if you want to, but there is no need to fill the blind with boredom in order for him / her to reach the body of your page content, and force him / her to read through all those content again and again in each of your website pages. We can always use CSS to render different page elements in any position regalrdless of its order as an element in the HTML document.

To summarize the characteristics of a good Website design I can say;
  • No style graphics are embeded in HTML, all design and decoration images located in a separated CSS file. No menu list, titles, or any content is represented only by graphics, it should be a text first and then styled and decorated with any graphics the designer decide.
  • No Tables are used to define layout columns, Tables are only for tabled data, and not for layout.
  • Web page content comes first in the order of HTML document. The title and body of the article of the web page is the first thing you see if you open the source code of the page or see the page without CSS styles, that's good, cause that's how other blinds, search engines, mobile browser will see your page.

I am yet to see CSS developers in Egypt, job posts for CSS developer in Egypt are none. Employers do not know what they are missing, they bet on graphic designers to do the job, and usually graphic designer have no idea what CSS is all about, they will use CSS for styling at best, and not for layout. That's why I will do a small contribution and start a mini series of CSS lessons (hopefully in Arabic too), in order to implement the mentioned principles in designing a good website design.

Git the Version Control System - part one

Git is a Version Control System, it is used to keep a history of all the changes you made into your code, manage releases, makes it easier for more than one programmer to share his/her code with the rest of the group.

There are tens of good VCS out there, the most famous was CVS Concurrent Version System, then came Subversion from the same team of CVS with the same concepts but cleaner than its ancestor. Both CVS and Subversion was free. There are other sophisticated VCS out there some of them are free and the other are proprietary. Linux was developed using a free license version of Mercurial which is pretty good CVS but for more some reason Linus Torvalds was challenged enough to start writing his own VCS, and Git was born.

There are two types of VCS, Central and Distributed. In central VCS like CVS and Subversion, there is always one central repository, you checkout a copy of whatever version you like from the repository, start working on it and then submit your changes into the central repository again.

The Distributed type like Git, there is one or more central repository, and you clone the repository into your local machine, and then you will have a standalone repository. Which is more like forking the development of the code at certain point in its development line into another repository. You then maintain your repository and change to your heart content, and it is up to you or the original (upstream) repository maintainer to merge your changes.

I will write a note on the basic operation of managing my code in GIT. For the sake of simplicity I will not write in this post about how to serve or access remote GIT repository using SSH, I will just assume that all repositories are on local machine.
$ mkdir myapp
$ cd myapp
$ git init
Initialized empty Git repository in .git/
I created a folder for my application, and inside the folder I make Git initialize a new repository.

At this point we should have a folder named .git inside the 'myapp' and that .git folder by itself is a repository, in this folder GIT will store all the transaction, changes, version, releases of your code. The beauty of GIT is that it does not pollute your code folder with other files like Subversion does. Subversion was creating an .svn folder inside each folder in my app folder.

As I said .git is the repository and the rest of your folder is now then called the working copy. the working copy is an important concept. It is your current version files, in Git if you switch to another version of your code, all the files in the folder will be changed to reflect the real version you switched to. We can create a repository without a working copy and that's what we do in case we need to make a central repository where programmer are pulling and pushing changes into it, in that case we do not need a working copy with the repository, this is called a 'bare' repository.

The .git repository folder is now empty, it has no files (or changes) in it. To start populating the repository we use the 'add' Git command. but we actually do not have any files yet, so let's make some files.
$ echo "hello" > dialog.txt
I created a file 'dialog.txt'. Now i will ask Git about the status, and it will answer me with the following information, which match files in three cases:
  • The modified files in my working copy that needs to be committed.
  • The modified files that are marked for committing.
  • The files that are not yet tracked by Git, and they need to be added first to the repository.
Now that we only have one file in the third case.
$ git status
# On branch master
#
# Initial commit
#
# Untracked files:
# (use "git add ..." to include in what will be committed)
#
# dialog.txt
Git suggest to use the add command to start tracking the file. What tracking means? Ok, in a working copy there is either tracked files that you want to keep track of, and untracked files which are either newly created and needs to be added to the repository or non source code files like log files, object and comoiled files and in this case we need to tell Git to ignore them and not notifying me about them when we use the 'status' command.

To be more specific the 'add' command does not add the files to the repository here or even convert the untracked files into tracked ones, the 'add' command is actually preparing the files to be committed or added to the repository in the next time you use the commit command. Actually 'add' is adding the files, tracked or not, to an area which is called the 'index', and after you add all the files you need and you feel satisfied that your all the changes you need to commit is in the stage, then you can use the commit command to commit your changes into the repository.
$ git add dialog.txt
Now that we added the dialog.txt it is now in the 'index' and will be commited by the next commit command.
$ git status
# On branch master
#
# Initial commit
#
# Changes to be committed:
# (use "git rm --cached ..." to unstage)
#
# new file: dialog.txt
#
Well, it is time of our first commit. Git is storing the name and email of the committer with each commit, so we need to identify ourselves first to Git.
git config --global user.email "ibrahim@mymail.com"
git config --global user.name "Ibrahim Ahmed"
$ git commit -m "saying hello"
I committed the dialog.txt and notice the '-m', commit always needs a log message, try to write a message describing the changes you've done to the file.
$ echo "what's your name" >> dialog.txt
$ git status
I added one more line to dialog.txt, and git status to see the changes, and Git should giving me that dialog.txt is modified and will be committed in the next comit.

One more time, and excuse my boring repetition, you will need to add first the dialog.txt to the index area, before it is ready to be commit.
$ git add dialog.txt
$ git commit -m "asking about your name"
Ignoring files
Git status will always nag about untracked files, so we should either 'add' it or ignore it.

There are always some files in your app that you do not need to track, files like logs for example.
$ touch myapp.log
$ git status
# On branch master
#
# Untracked files:
# (use "git add ..." to include in what will be committed)
#
# myapp.log
$ echo "*.log" >> .git/info/exclude
$ git status
# On branch master
nothing to commit (working directory clean)
Notice how git status listed myapp.log in untracked files, and when we add a line containing '*.log' to '.git/info/exclude', git status ignored the myapp.log file and gives the message 'working directory clean'

Remove files
'git rm' removes files from the working directory and from the repository. But it also used to remove files from the 'index' using the following;
$ touch delete.me
$ git add delete.me
$ git commit -m "adding delete.me"
$ git rm delete.me
$ echo "how old are you?" >> dialog.txt
$ git add dialog.txt
$ git rm --cached dialog.txt

That's it for the first part of my note about Git, on the second note I will write about diff, clone, pull, adding remote repository, merge, and conflict resolution.