Montag, 27. Oktober 2008

Mysql import

mysql -p -u{Benutzername} {DB-Name} < filename

Converting database time to human time

model.created_at.begining_of_day.strftime(%B, %Y)
>October, 2008
model.creted_at.strftime("%d").to_i.ordinalize
>25th

%a weekday name.
%A weekday name (full).
%b month name.
%B month name (full).
%c date and time (locale)
%d day of month [01,31].
%H hour [00,23].
%I hour [01,12].
%j day of year [001,366].
%m month [01,12].
%M minute [00,59].
%p AM or PM
%S Second [00,61]
%U week of year (Sunday)[00,53].
w weekday [0(Sunday),6].
W week of year (Monday)[00,53].
x date (locale).
%X time (locale).
%y year [00,99].
%Y year [2000].
%Z timezone name.

Donnerstag, 16. Oktober 2008

Memcache Rails

>sudo port install memcached
>/opt/local/bin/memcached -d -m 64 -u www -l -p 11211

see also
/Library/LaunchDaemons/org.macports.memcached.plist
memcached -h
man memcached

Montag, 13. Oktober 2008

Session Cookies and Application Strategy

- Do you need protection_forgery? Yes!
- Does a browser need cookies turned on? Yes!
- Is there no otherway around it? No!
Passing infomation in the url is neiter restful, nor safe!
- What about people that have their cookies turned off?
We have to give let them know that cookies are safe in the contect of our application, and they hold no personal information and they are encrypted.
- What about mobile phone browsers that mostly have no cookie capabilities?
Same as cookies turned off, may adding somthing about mobile phones too.
OR
The user can set up his account as "Mobile Phone Enabled" from a web browser and tell them about the cookie problem, but give them the solution to have the application use IP as the cooke key - with the small problem that if thier provider issues them with a new IP during the session, they will have to relogin.

Better Cookie Detect

In some cases, you might really really want to know it the visiting browser has thier cookies on or off. One reason that I an think off is that you are using some ajax stuff on your the landing page that lets unregistered users edit a list or somthing.

This is a way of doing it.

1. Check to see if a cookie has been set for the session,
2. if not then check to see if this ip is in the middle of cookie detection
3. if not then redirect to a method and check again - if no cookies are on now, then be sure they are off.

Now you can either ask them to put them on to gain full functionallity of the application, or let the application blend out functions that cause UPDATE, PUT or DESTROY requests and instead show a flash error message that informs them of the reduced functionality.

This means that you will force a redirect on each request for browsers that have thier cookies off.

In the application.rb add the following:

before_filter :cookies_required, :except => [:check_for_cookies]

protected

def cookies_on?
..!request.cookies["_yourapp_session"].to_s.blank?
end

def cookies_required
..return unless request.cookies["_yourapp_session"].to_s.blank?
..if DetectCookie.find_and_destroy_or_create_by_remote_ip(request.remote_ip, request.request_uri) then return end
..session[:return_to] = request.request_uri
..redirect_to detect_cookies_path
end

>ruby script/generate model DetectCookie remote_ip:string request_uri:string
>rake db:migrate

Create a controller: dectect_cookies.rb
add the following:

class DetectCookiesController < ApplicationController
..before_filter :cookies_required, :except => :show

..def show
....if request.cookies["_hausursel_session"].to_s.blank? #change to your cookie session name
......detect_cookie=DetectCookie.find_by_remote_ip(request.remote_ip)
......detect_cookie ? redirect_to(detect_cookie.request_uri) : redirect_to(cookie_path)
....else
......redirect_back_or_default(:controller => 'apartments')
....end
..end
end


Add the following to the detect_cokkie.rb file in the models folder:

class DetectCookie < ActiveRecord::Base

..def DetectCookie.find_and_destroy_or_create_by_remote_ip(remote_ip, request_uri)
....if detect_cookie=DetectCookie.find_by_remote_ip(remote_ip)
......DetectCookie.destroy(detect_cookie.id)
......true
....else
......DetectCookie.create(:remote_ip=> remote_ip, :request_uri => request_uri)
......false
....end
..end

end

Samstag, 11. Oktober 2008

Simple Cookie Detect

All PUT, UPDATE and DESTROY methods require the session cookie with protect_from_forgery or the application will break if a browser has cookies turned off when one of these methods are used.

Unfortunately, when a browser calls the application for the first time, the session cookie wil be written, but it wont be read untill the next page request. This makes it impossible to know if cookies are off, or of in the browser so anyone visiting the application first time and lets say, posts a form will be disapointed.

This is a simple solution to the problem. All controllers will call a cookies_required method when PUT, UPDATE or DESTROY methods are used. The cookies_required method looks to see it if the session cookie is empty - if it is, it will catch the http-referrer and redirect to the method check_for_cookies - if the session cookie is still empty, then we can be certain that cookies are off in the browser and refrain the user from using the
PUT, UPDATE or DESTROY methods. Instead we show a message about cookies being off and the application having limited functionality untill they are turned on.

Add the following to application.rb

..before_filter :cookies_required, :except => [:show, :check_for_cookies]


..def check_for_cookies
....if request.cookies["_cookie_detect_session"].to_s.blank?
......render :text => 'You absolutly Need Cookies on to use this function'
....else
......redirect_back_or_default(:controller => 'home')
....end
..end

protected

..def cookies_required?
....return unless request.cookies["_cookie_detect_session"].to_s.blank?
....session[:return_to] = request.request_uri
....redirect_to(:controller => 'home',:action => 'check_for_cookies')
..end

..def redirect_back_or_default(default)
....session[:return_to] ? redirect_to(session[:return_to]) : redirect_to(default)
....session[:return_to] = nil
..end

Freitag, 10. Oktober 2008

Montag, 6. Oktober 2008

Javascript and RJS

To descide how to handle javascript in ruby you should seperate between.

1. Effects (hide, show, highlight, fade ect), and
2. Interactive data (with or without visual effects)
3. Embedding Javascript the good old way.

1. Effects
Visual effects being anything that just tells the client side javascript engine to do somthing with one or more its DOM's.

2. Interactive Data
Interactive data, would be somthing like a calculating user input and diplaying the resulting sum in realtime.

3. Embedding Javascript the good old ways
If you like cluttering every things up javascript, you probably should not being using rails. Apart from needing a lot more programming time, and lines of code and making everything a millon times more dificult to test there is no reason what so ever to fall back to embedding javascript in the views as it used to be.

The difference between the 1 and 2 is that in the first case, you don't need to use an RJS file, whereas in the second case you will need and observer and an RJS file to handle the resulting data update when the observer registers user data changes in one or more input fields on a page.

Rails Javascript Engine.
==============
This engine can only do one thing. Wack out javascript to the client side browsers java engine for rendering. The Rails engine has no concept of the state of the page being manipulated by the client side browser java engine.

This means conditionals are not directly possible. i.e.
if page[:input_field_name] == 'red'
page[
:input_field_name] = 'blue'

What you can do is this:
page << "if $(('input_field_name').value == 'red' {" # this is a straight javascript string which does not get interpreted page[:input_field_name]=='blue' # this get turned into a java script statement and sent to the client page << "}"
# this is a straight javascript string which does not get interpreted and finishes the conditional

Note the conditional has nothing to do with rails - the engine in the browser interprests the code output by page.

Renanaming URL routes

Renaming the URL'S defaults generated with the controllers.

i.e you have a resource you address in your code:

<% link_to("award", certificate_path(1)%>

This might be because you actually only have one certificate. You have the link on the page showing Awards, but when the user clicks on the link the URL will show:

/certificates/show/1

To change this you need to edit the routes.rb

map.resources :certificates

to the following:

map.the_certificate 'award', :controller => certificates, :action => 'show', id => 1
map.resources :certificates


Now you can change:

<% link_to("award", certificate_path(1)%> to <% link_to("award", the_certificate_path %>

NOTE 1:

doing this does not work properly:

map.certificate 'award', :controller => certificates, :action => 'show', id => 1
map.resources :certificates


i.e. trying to overwrite mapped resource with the same name to point to the proxy url.
It messes up when you render a form with somthing like
<% form for @certificate %>

NOTE:

Whenever you make any changes to the routes.rb file you will need to restart your server!!!!

Loading Tables with Defauls Application Data in Migrations

1. Rake a migration to make the table
2. Make a new directory 'development_data' in app/db/migrate/
3. Make a YML file with the "tablename.yml" (check pural!) containing the default data for the table you need for the application (don't mix wiht test data)
4. Run rake db:migrate to create the tables and load them with the default data from the YML

==== Table Create Migration example

> ruby script/generate migration Certificates title:string description:text

==== YML example


certificate:
..id: 1
..title: "All About This Certificate"
..description: "Blah Blah."

..id: 2
..title: "All About This Certificate"
..description: "More Blah Blah."

==== Create Load Migration example

> ruby script/generate migration Certificates title:string description:text

==== Load Data example


class LoadCertificatesData <>
..def self.up
....down
....directory=File.join(File.dirname(__FILE__),"development_data")
....Fixtures.create_fixtures(directory,"certificates")
..end

..def self.down
....Certificate.delete(:all)
..end
end


==== Load Data example

This strategy might fail over time if you are adding and deleting existing colums in migrations, so you might have to end up doing all your load migrations after all the structural migrations have finished.

However, this might fail to if table relations ships are complex - so then you might have to fall back to an administration interface in the application where you build the tables from the YML file with your own programming.