Wednesday, June 17, 2015

Ruby on Rails 2015-06-16

1. Route the pages.
(1) If you want to be able to route to your new view, open config/routes.rb and add the line

get 'view_name/index'

(2) If you want to set the default page to a certain, open config/routes.rb file, add

root 'store#index', as: 'store'

So the index will be routed to the index of controller store. The as: 'store' tells Rails to create a store_path accessor method.

2. yield method in view/layouts/application.html.erb. This method will render the content of the view that user is currently browsing. For example, if the user is browsing http://localhost/store, then the content of views/store/index.html.erb will be rendered in the yield section. Similarly, if the user is browsing http://localhost/products, then the content of views/products/index.html.erb will be rendered.

3. Did "rake test" but encountered five errors:
(1) AbstractController::Helpers::MissingHelperError: Missing helper file helpers//users/alexsun/documents/rubys/workspace/depot/app/helpers/application_helper.rb_helper.rb

(2) ProductsControllerTest#test_should_show_product:
ActionView::MissingTemplate: Missing template products/show, application/show with {:locale=>[:en], :formats=>[:html], :variants=>[], :handlers=>[:erb, :builder, :raw, :ruby, :coffee, :jbuilder]} 

(3) - (5) similar to (2), all are "Missing template"

I didn't see these error when I was using Ruby 2.2.0. But after that I switched back to Ruby 2.0.0 and then these error appears. I fixed them by changing my workspace name "Depot" to "depot" and all errors are gone. It seems to me a Ruby bug which is in Ruby 2.0.0 but fixed in Ruby 2.2.0.

Monday, June 15, 2015

Ruby on Rails 2015-06-15

Object-Relational Mapping

ORM libraries map database tables to classes. If a database has a table called products, the program will have a class named Product. Rows in the table correspond to objects of the class -- a particular product is represented as an object of class Product.

ActiveRecord is the ORM layer supplied with Rails. It closely follows the standard ORM model: tables map to classes, rows to objects, and columns to object attributes. By relying on convention and starting with sensible defaults, ActiveRecord minimizes the amount of configuration that developers perform.

To understand the ActiveRecord, here is the example:
In models/product.rb, a class Product is define:
class Product < ActiveRecord::Base
end

In db/migrate/xxx_create_products.rb, a class CreateProducts is define:
class CreateProducts < ActiveRecord::Migration
    def change
        create_table:products do |t|
        end
    end
end

By this way, Product has been mapped to the prodcuts table in the database. And the cool thing is that the Product calss that wrap the database table provides a set of class-level methods that perform table-level operations. To understand this, here is the example:
(1) find the product with a particular ID
product = Product.find(1)
(2) collect the objects whos name is 'dave'
product = Product.where(name: 'dave')
You don't need to care about how to manipulate the SQL query to get the data. Rails class wraps them for you and all you need to do is code like OO programming.

Ruby on Rails 2015-05-23

1. Rails provides a simple way to do data validation. The model layer is the gatekeeper between the world of code and the database. If a model checks the data before writing to the database, then the database will be protected from bad data. The source code is in app/models/xxx.rb. An example of validation is:
    validates :title, :description, :image_url, presence: true

2. Rails provides a test framework. The framework is in test directory. You can test the entire framework by:
    $ rake test
Unit test cases can be created in test/models directory, and you can test a particular test case file, e.g.:
    $ rake test:models

3. We use assertion to tell the framework whether our code passes or fails.  The simplest assertion is the method assert(), which expects its argument to be true, e.g.:
    assert product.invalid?, "DEBUG COMMENTS"
    assert product.errors[:title].any?

4. Fixture is a specification of the initial contents of a model under test. Fixture data is specified in the test/fixture directory. The name of the fixture file is significant. The base name of the file must match the name of a database table. The default for the test is to load ll fixtures before running the test, but again you can control which fixtures to load by specifying the following line in the test/models/xxx_test.rb:
    class ProductTest < ActiveSupport::TestCase
      fixtures :products
      ...
    end
The name of the fixture file determines the table that is loaded, so using :products will cause the products.yml fixture file to be used.

5. There are three databases that has been created in the configuration that scaffolding provides.
(1) db/development.sqlite3 will be the development database.
(2) db/test.sqlite3 is a test database.
(3) db/production.sqlite3 is the production database.
rake test command automatically gets a freshly initialized table in the test.sqlite3 database loaded from the fixtures we provide. Also we can do it separately by running rake db:test:prepare.

Thursday, May 21, 2015

Ruby on Rails Note - 05/20/2015

1. css files are in app/asset/stylesheets/xxx.scss. Rails keeps application.html.erb as a framework page for the entire application. The application.html.erb file is located in views/layouts/ directory. In order to use the xxx.scss, it has to be introduced in the application.html.erb file, in such way as following.
  <body class='xxx.scss'> or <body class='<%= controller.controller_name%>'>
Then, the css classes can be used in index.html.erb.

2. Some rails helper function:
(1) cycle('a', 'b') sets the css class of each row to either 'a' or 'b' and automatically toggles between the two style names on successive lines.
(2) trunctate(string, length:n) is used to display just the first n characters of string.
(3) strip_tags(string) removes the html tags from the string.
(4) link_to('Product', @product) is equal to
     link_to('Product', controller:'products', action:'show', id:product)
     The link_to generates  a hyper link which execute show method in controller which invokes show.html.erb if nothing in the method.

3. Git usage
(1) basic configuration
    $ git config --global --add user.name "Alex"
    $ git config --global --add user.email alex@gmail.com
    $ git config --global --list
These configuration info will be added every check in as the committer info.
(2) add a .gitignore file to specify a file list that you don't want to check in
(3) create a local empty repository in current directory.
    $ git init
(4) add all the files under the current directory to local repository.
    $ git add .
(5) commit the change to local repository
    $ git commit -m "first commit"

If you want to clear the local repository.
(1) rm -rf .git

If you have a github account, you can push your repository to the github
(1) create a repository on github
(2) $ git remote add origin "YOUR HTTPS GITHUB REPOSITORY URL"
(3) $ git push origin master




Tuesday, May 19, 2015

Ruby on Rails Note - 05/19/2015

1. To create a new project.
    $ rails new [project name]

2. Create a scaffold. A scaffold is a full set of model, database migration for that model, controller to manipulate it, view to view and manipulate the data, and a test suite for each of the above.
    $ rails generate scaffold Product \
            title:string description:text image_url:string price:decimal

The default database for Rails development is SQLite3. The config/database.yml file tells Rails where to look for the database.

3. To migrate database.
    $ rake db:migrate

The migration file is xxxxxxxxxxxxxx_create_xxxx.rb. A migration represents a change we want to make to the data, expressed in a source file in database-independent terms. These changes can update both the database schema and the data in the database tables.

4. To start rails server.
    $rails server

5. To import seed data to the database.
    $rails db:seed

The data can be defined in db/seed.rb.

Monday, April 20, 2015

Start Ruby on Rails!

Installing Ruby on Rails on Mac OS X Yosemite

1. Install latest Xcoder (6.3)

2. Install Command Line Tools which is premise for step 6:
    Xcoder -> Open Developer Tool -> More Developer Tools...

3. Install RVM:
    $ curl -L https://get.rvm.io | bash -s stable

4. Install latest ruby (2.2.1):
    $ rvm install 2.2.1 --autolibs=enable

5. Configure the environment to be ruby 2.2.1:
    $ rvm use 2.2.1

6. Install latest rails (4.2.1)
    $ gem install rails --version 4.2.1 (--no-ri --no-rdoc)

7. Make ruby 2.2.1 as the default environment
    $ rvm --default 2.2.1

After installation, there might be something that you would like to do, such as upgrade to newer version.
1. To find out all the versions of Rails that you have installed:
    $ gem list --local rails

Installing PostgreSQL on Mac OS X Yosemite
1. www.postgresql.org/download/macosx/  find a installer on the website and install PostgreSQL.
2. Install the database driver for PostgreSQL. Driver can be downloaded from https://bitbucket.org/ged/ruby-pg/wiki/Home. You have to specify the pg_config location. PostgreSQL installed by EnterpriseDB keeps pg_config in /Library/PostgreSQL/9.4/bin/pg_config
$gem install pg -- --with-pg-config=/Library/PostgreSQL/9.4/bin/pg_config

To be continued:
1. Version Control (Git) ?
2. Continuous integration (CI) system?
3. Editors?

Tuesday, November 25, 2014

Android Rookie Diary 11/25/2014

Just started a project that allows android phone talk to a STM32f103 (ARM 32bit Cortex-M3). It's been quite a while since I touched Android whose version was Gingerbread (2.3.3). As an android rookie right now, I'd like to keep a "diary" that could remind me of any mistakes that I made while I'm working on this project.

null exception.
It's easy to make such a stupid mistake if you've been off Java/Android for a while.
First, it's null exception in regards of View.
1:  @Override  
2:  protected void onCreate(Bundle savedInstanceState) {  
3:      super.onCreate(savedInstanceState); 
4:      mTextView = (TextView) findViewById(R.id.textview);  
5:      mTextView.setText("JunEnd");
6:      setContentView(R.layout.activity_register);
7:  }  
setContentView() sets the activity content from a layout resource, so should be called before findViewById(). Otherwise findViewById() will return null because of no layout resource and thus line 5 throws a null exception.

Second, it's null exception in regards of Spinner.
1:  public class RegisterActivity extends Activity implements OnItemSelectedListener {  
2:      private Spinner mSpinner;  
3:      private ArrayList<String> mArrayList_SpinnerList;  
4:      @Override  
5:      protected void onCreate(Bundle savedInstanceState) {  
6:          super.onCreate(savedInstanceState);  
7:          setContentView(R.layout.activity_register);  
8:          ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,  
9:                  android.R.layout.simple_spinner_item, mArrayList_SpinnerList);  
10:          adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);  
11:          mSpinner.setAdapter(adapter);  
12:          mSpinner.setOnItemSelectedListener(this);  
13:      }  
14:      @Override  
15:      public void onItemSelected(AdapterView<?> parent, View view, int pos,  
16:              long id) {  
17:          // TODO Auto-generated method stub  
19:      }  
20:      @Override  
21:      public void onNothingSelected(AdapterView<?> arg0) {  
22:          // TODO Auto-generated method stub  
23:      }  
24:  }  
I forgot to instantiate mArrayList_SpinnerList and passed it to constructor ArrayAdapter() and then thus gave Spinner this adapter holding an uninstantiated object. I believe this is causing a null exception and killed the app.