Categories
Rails

rails: handling errors for routes / controllers not found

Create a controller that will handle errors:

class ErrorsController < ApplicationController

  def routing

    render_404

  end

  def render_404

    render :json => {:status => “error”, :response_code => 404, :message => “no route found that match your request, please check your parameters and try again”, :results => {} }.to_json

  end

end

And then, in your router, include the following line (at the end, after all the resources are listed, so you can catch stuff in there):

  resources :some_resource_here

  # catch any unmatch paths:

  match ‘*a’, :to => ‘errors#routing’

another option

you can redirect to another page inside your controller, like this:

before_action :set_project, only: [:show, :edit, :update, :destroy]
... 

def set_project
   @project = Project.find(params[:id])
   rescue ActiveRecord::RecordNotFound flash[:alert] = "The  project you were looking for could not be found."
   redirect_to projects_path
end


Categories
rspec

rspec: mocking

# To mock any object's method
allow_any_instance_of(MyClass).to receive(:my_method).and_return(false)

Make sure you put this in the before(:each) do block, before your tests, if you put it on the test itself, it may be too late, and you don't get the behavior you are expecting (the overwriting of the method you requested)

Also, this doesn't work with before(:all)
Categories
Rails

Rails 4: add jsonp responses

On your controller’s method that handles the jsonp response:

render :json => your_data_object_here.to_json, :callback => params[:callback]

Categories
Uncategorized

Recipes: how to listen to DOM insertions

The technique described here (more details in there):

http://davidwalsh.name/detect-node-insertion

It basically involves putting a CSS animation to the elements that will be attached in the future. When they get inserted, they run the animation, and when the animation finish running, it throws an “animationstarts” event.

The last part involves attaching a listener to the parent DOM, so when the CSS animation thrown the event, it is catch and processed there:

parentEl.addEventListener("animationstart", insertListener, false); // standard + firefox

You could also use the ‘DOMNodeInserted’ event, but it will be deprecated:

currentBox.bind(‘DOMNodeInserted’, function(e){
currentBox.find(‘object’).attr(‘width’, currentBox.width()).attr(‘height’, currentBox.height());
});

Categories
impact.js

impact.js: the basics

Add characters: spacebar, then choose from the list.

Categories
Angular.js

Angular.js: the basics

$scope

$scope is what connects views and controllers.

Most logic goes in the controllers. Controllers shouldn’t know what view they are operating on, their job is to produce a $scope (to keep dependencies light)

The $scope can be considered a “quasi model”, it is the pure data variables and data objects that binds both the view and the controller.

Example (defining the controller, and then applying the variables in the view):

<script type=”text/javascript”>
function MyController($scope) {

$scope.musicList = [
{ title: ‘With or without you’, artist: ‘U2’ },
{ title: ‘Two princes’, artist: ‘Spin Doctor’ }
];

}
</script>
<div class=”container” ng-controller=”myController”>
<ul>
<li ng-repeat=”song in musicList”>{{song.title}} by {{song.artist}}</li>
</ul>
</div>

Note that each li will create it’s own internal $scope, but inherit from the parent $scope controller. Angular apps mirror the DOM in regards to parent DOM elements inheriting values down to their children elements.

Application flow

Routers take the URL from the browser, and call an specific controller. The controller will have the logic to handle the URL request, and pass the data to the corresponding view, via the $scope.

Controllers don’t do it all, usually they delegate work to services, factories, providers, or resources.

View also don’t do a lot on their own, they rely on directives and filters to make the DOM dance.

So, in summary: routes calls controllers, which in turn call services, factories, etc to complete tasks, and then load the final result into the $scope. Views take over from there.

Code organization

It’s always a good idea to encapsulate stuff in modules. The start line to do so in angular is:

var myApp = angular.module(‘myApp’, [ ‘someOtherModuleHere’ ]);

someOtherModuleHere is optional, you can chain any other helper modules you need here for your ‘myApp’ module. Kind of the requireJS of angular.

So now that you have your myApp module namespaced, you can start attaching controllers to it:

myApp.controller(‘MyMusicController’, function ($scope) {

$scope.musicList = [
{ title: ‘With or without you’, artist: ‘U2’ },
{ title: ‘Two princes’, artist: ‘Spin Doctor’ }
];

});

So now, the way to put that controller to use, is to mark what DOM element of the HTML will be controlled by it, by means of the ng-controller directive:

<html ng-app=”myApp”>

<div ng-controller=”myMusicCtrl“>

<!— everything here will have access (and be binded) to the variables defined in $scope –>

</div>

By convention, you usually name your controllers [something]Ctrl. Each controller can support multiple views, so it can be used to get things synched. A view can also hold more than one controller.

This is how you declare it:

myApp.controller("dayCtrl", function ( $scope) {

Regarding code organization, it is better to keep everything separate. Usually you put the kickstarterd of the application on app.js (defining the namespace and the routers), and then controllers and services in their own space (for definition of services, see factories / services below). They can be tested separately, and called for different controllers this way, in a more modular fashion.

 Defining routes

Since angular 1.2, router functionality exist separate from the angular library itself, you would need to download separately from:

https://github.com/angular-ui/ui-router

Using config, you can define what URLs load what templates:

demoApp.config(function ($routeProvider) {
$routeProvider
.when(‘/’,
{
controller: ‘myMusicController’,
templateUrl: ‘View1.html’
})
.when(‘/someURL’,
{
controller: ‘anotherController’,
templateUrl: ‘View2.html’
}).
otherwise({ redirectTo: ‘/’ });

The html files that are being called out are off the root directory, but you can organize them in folders.

The app page has a “ng-view” container, that will automatically receive the template specified in the URL via the router above, the way that part is setup in the page is via a simple tag:

<div class=”container”>
<ng-view><!– the templates will dump their content here –></ng-view>
</div>

 Click events

They are handled in the view files via the ng-click directive, example:

<button ng-click=”doSomething()”>Click me</button>

And, inside the controller:

$scope.doSomething = function () {
// Things happening inside here
}

Reading form fields
It is also done via the $scope:
var localVarInsideController = $scope.objectName.objectVariable;
And in your view:

<input type=”text” data-ng-model=”objectName.objectVariable” />

Now the var localVarInsideController in your controller, and the input field in your view are binded.

To validate, you can add the following to the fields:

ng-disabled=“addForm.$invalid”

where addForms is the name=”addForms” attribute in your <form> tag. And then, in your input fields you mark ones required as:

<input type=“text” id=“name” class=“form-control” ng-model=“contact.name” required>

You can find some examples here

Data providers

In order to keep those modular and reusable, angular has some predefined objects for them. They all do sort of the same work, just in a different way:

1) Factories: creates a closure of methods and variables, which runs once, and expose certain methods so code can deal with its functionality. It is pretty much the thing you would usually do to envelop an object into a closure, with public and private methods.

This is an example of a factory that returns one value:

.factory('demoService', function demoServiceFactory(){
  return 'abc123';
});

In reality, factories are better off returning functions with methods instead of plain data.

2) Service: provides the functionality needed to create the data. Usually in the form of “this.someFunction = [anonymous function here] inside your controller. They are usually singletons that are accesible throughout the application, using the same data. The simplest form is creating constants via:

.value('demoService', 'abc123');

and then you can inject that service anywhere you need that value, like:

.controller('indexCtl', function($scope, demoService){
    $scope.demo = demoService;
});

3) provider: you define a $get inside of it that will contain the data to be returned. They can call other services to build upon.

Example of creating a factory for our app:

myApp.factory(‘simpleFactory’, function ($http) {

// In this case, we injected $http so we can call the data from backend

}

4) Directive: enclose functionality, the equivalent of web components. Example of setting one up:

myApp.directive(“highlight”, function () {
    returnfunction (scope, element, attrs) {
        if (scope.day == attrs[“highlight”]) {
            element.css(“color”, “red”);
        }
    }
});

You pass a factory function, so each time the directive gets called from the HTML, a copy of that factory function gets run (usually called a “worker”). Notice the $scope is passed via “scope” (without the $), element is the HTML element the directive was applied to (wrap in a jquery like object), and the attrs are the set of attributes on that element, including the directive one.

 Angular philosophy regarding UI architecture   

Angular === imperative! Meaning you build your static HTML as normal, and then you add directives to add the dynamic parts, and all the other fun event driven stuff on top of it

$rootScope

this is a global space in your app, that could be used to share data between components. To attach vars to it you could use something like

.controller('indexCtl', function($scope, $rootScope){
    $rootScope.contacts = [your array here...

and then call it on your views via:

<tr ng-repeat="contact in $root.contacts">

using global scope variables is a bad practice in general, use it sparingly

loose ends

Get a hold of angular elements from third party javascript code:

angular.element(document.getElementById(‘yourElement’)).scope().yourFunctionInsideThe$scopeVar();

ng-non-bindable // Use it to indicate an area of your HTML where you don't want the {{}} to be translated to a request for binding

Use $routeParams if you are using ngRoute, if you are using ui-router, use $stateParams instead

Categories
node.js

node.js: boilerplating a site with express.js

Install express globally in your system, so you can use it from anywhere:
$npm install -g express

Initialize your installation:
$express myapp; cd myapp;

Modify your package.json file inside of there, and run it. Here’s a boilerplate example of it:

{
  "name": "nameofyourapphere",
  "version": "0.0.1",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo "Error: no test specified" && exit 1"
  },
  "dependencies": {
    "express": "~3.3.5"
  },
  "author": "",
  "license": "BSD"
}

$npm install // only if you modify the boilerplate generated package.json

You can also save dependencies to your installation file. For example, if you need extra packages, specify the –save option and you will have them

$npm install less-middleware –save

Create a boilerplate using some of the express flags:
$express -s -e -c less -f cli-app
Where:
-s or –sessions adds session support
-e or –ejs adds EJS1 engine support, by default jade2 is used
-J or –jshtml adds JSHTML3 engine support, by default jade is used
-H or –hogan adds hogan.js engine support
-c or –css adds stylesheet support (e.g., LESS4 or Stylus5), by
default plain CSS is used
-f or –force forces app generation on non-empty directory
The directories created with this option are:
1. public for static assets
2. views for templates
3. routes for request handlers

Go to the directory you created with the boilerplate options, and start your app:
$ cd cli-app; npm install; # you have to install again because you have new options after boilerplating
$ node app # your server should start at this point, and you should see the Welcome to Express page

Deploy to heroku
Your root directory needs a Procfile file (no extension), with the following line:
web: node app.js

That will tell Heroku what to run (app.js)

Also, if you are using mongodb, you need to have the following line in your app.js, so Heroku switch to the proper connection:
var host = process.env.MONGOHQ_URL || “mongodb://@127.0.0.1:27017/test”;

You also need to set MONGOHQ plugin on your heroku account. It is free for low traffic.

Also, you have to make your port Heroku friendly, and be able to switch to a known port when you are in your local env, by doing the following (in app.js as well):

var port = process.env.PORT || 3000;

server.listen(port, function() {

console.log(“Server listening on port ” + port + “.”);

});

$git init; git add .
$git commit -am “Initial commit”
$heroku create [your app name]
$git push heroku master
$heroku open

Things to keep in mind

– Variables set with “set” are global to the app now. For example:
app.set(‘appName’,’SomeGenericName’);
and later, in your template, you can read it like:
head
title= appName // Inside a jade file

– To make jsonp work, you need to set the following:
app.set(‘jsonpcallbackname’,’cb’); // So now cb=[your cb function] will be the function used for jsonp

– etags are enabled by default:
app.disable(‘etag’);

Categories
Rails

Rails: barebones site template from the ground up, version II, using rails 4

Assuming you have rails 4 already running in your system. And git / heroku also ready to go.

$ rails new your-project

Add a bunch of static pages, remove the default page:
remove public/index.html (if there)
$ rails generate controller StaticPages home help about contact_us –no-test-framework
Inside config/routes.rb”
– Comment out the static pages you don’t need, or add the right routes to the ones you want:
# get “contact_us” => “static_pages#contact_us” (example)
– Add a default page as home:
root :to => “static_pages#home”

Add devise, and their views:
Modify your gem file to contain the following lines:
gem ‘devise’
gem ‘sqlite3’, group: [:development, :test]
gem ‘pg’, group: :production

$ bundle install –without production
$ rails generate devise:install # Follow the instructions printed

$ rails generate devise user
$ rake db:migrate
To be able to modify the devise views as any other template:
$ rails generate devise:views

Add source control, push to Heroku
$ git init
$ git add .
$ git commit -am “Initial commit”
$ heroku login # if you haven’t
$ heroku create [name of your app]
$ git push heroku master
$ heroku run rake db:migrate

Static assets

If images and such are not showing on heroku production, you may have to pre compile them locally, using the following command:

RAILS_ENV=production bundle exec rake assets:precompile

This will generate the static assets inside the public directory. Ideally you should use a CDN to serve your images, but this should be ok for small projects.

Extra gems you may need for Rails 4.0

gem ‘rails_12factor’, group: :production

That will take care of any errors related to assest

Categories
Rails

Rails: Active Record callbacks

There are simple filter-like, provided methods (aspect oriented style), to deal with the life and death cycles of models, the most common are:

  • before_create
  • after_create
  • before_save
  • after_save
  • before_destroy
  • after_destroy

If for any reason, the method returns false, the chain of events will stop, for instance:

def before_create
  false
end

will effectively stop any model creation.

To make things more readable, it is recommended you move your filters to the top of the model, just below the validation section, and list it as:

   after_create :email_article_author
   ...
   def email_article_author
      puts "stuff here..."
   end

This way you can also put multiple methods (comma separated) in the filter.

Categories
Rails

Rails: model associations

In SQL terms, you associate two tables using a foreign key reference in one, that points to an id on the other.

In rails, the convention is:

#{singular_name_of_parent_class}_id

For example: table articles has comments associated with it, so in the comments table there is an “article_id” column that points the records in there to the ids on the articles table. Once those tables are associated, you can do stuff in rails like this:

article.comments

One to One associations

The example below is establishing an association via the user_id:

rails generate model User email:string password:string

rails generate model Profile user_id:integer name:string birthday:date bio:text color:string twitter:string

To formalize the “marriage”, inside you model you can declare the one to one relationship as follows:

class User < ActiveRecord::Base
has_one :profile
end

class Profile < ActiveRecord::Base belongs_to :user end Once that is setup, you can do stuff like: user.create_profile :name => ‘Jane Doe’, :color => ‘pink’

To create a profile associated with that user

One to many associations

In this example, we are adding the user_id column to an existing “articles” table, via:

rails generate migration add_user_id_to_articles user_id:integer

Once you generate and run your migration, you upgrade your model to be able to handle the one to many relationship:

belongs_to :user # In the article model

has_many :articles # In the user’s model

You could also specify how the records are to be retrieved when calling all articles in a given user:

has_many :articles, -> { order('published_at DESC, title ASC')}

When you are dealing with dependencies, you can also specify what happens if a given record is deleted. For example, if the user’s record is deleted, you can delete all the articles associated with it via internal rails callbacks, by specifying the dependency in the model:

has_many :articles, -> { order(‘published_at DESC, title ASC’)},
:dependent => :destroy

And, that is also the difference between the destroy and the delete methods: the destroy one will call the internal rails callbacks when a record is erased, and follow through erasing the associated records.

Many to many relationships

If two tables have records in both sides associated with many records in the other, this is usually consider a has_and_belongs_to_many relationship. There is usually an extra table in the middle that stores the relationships themselves. If, for example, we have an “articles” and “categories” tables associated this way, rail will usually generate a table in the middle called articles_categories, which will store the ids of both as an association record.

This class of in-between, join table, is special in the sense it doesn’t have a primary key on its own. In this case, the migration file in rails will have something like:

      def change
        create_table :articles_categories, :id=> false do |t|
          t.references :article
          t.references :category
        end
      end

Notice how the :id=>false to avoid creating that.

Important: Not sure if there is a bug in rails, but the migration above produce an articles_categories table, with no columns… I had to manually add them to the schema.db file (definitely a “don’t do it”) to be able to continue. I am still searching for the issue. But be aware of that!

In your category and article models, you will specify the relationship as:

has_and_belongs_to_many :categories
has_and_belongs_to_many :articles

Going further with this, if you have a comment model, which is associated to the articles model, and you want to query all the comments a user has, you have to do that by using the articles model as the join table (or in substitution of it). This is expressed as has_many :through

In this case, you will create some “replies” object, that express the responses (via comments) that a user got in their articles:

has_many :replies, :through => :articles, :source => :comments # at the user's model

So now you have access to queries like:
user.replies.empty?
user.replies.size
user.replies.first
article.comments.create(:name => ‘Guest’, :email => ‘guest@example.com’, :body => ‘Great article!’)