Mittwoch, 3. Dezember 2008

Start/Stop Mysql on Leopard

sudo /usr/local/mysql/support-files/mysql.server start

sudo /usr/local/mysql/support-files/mysql.server stop

Donnerstag, 13. November 2008

Rspec installation

>sudo gem install ZenTest
>sudo gem install rspec-rails

in application root:
>ruby script/generate rspec

autotest (if it hangs use >RSPEC=true autotest)


rake spec
rake spec:app

rake spec:models
rake spec:controllers
rake spec:views
rake spec:helpers
rake spec:plugins
rake --tasks:plugins

Freitag, 7. November 2008

Compare time

module ApplicationHelper
..SOMETIME_FORMAT = "%a %b %d %H:%M:%S %z %Y"
..SOMETIME_FORMAT_DB = '%Y-%m-%d %H:%M:%S'

..def sometime_this_month(time, format='user')
....return time.beginning_of_month.strftime(SOMETIME_FORMAT) if format == 'user'
....return time.beginning_of_month.strftime(SOMETIME_FORMAT_DB) if format == 'db'
..end

..def sometime_today(time, format='user')
....return time.beginning_of_day.strftime(SOMETIME_FORMAT) if format == 'user'
....return time.beginning_of_day.strftime(SOMETIME_FORMAT_DB) if format == 'db'
..end

end


Time based finds.

created_at time from the database is: "2008-10-24 22:06:18 +0200"

However retrieving the Time.now results in the format as follows: "Fri Nov 07 15:31:56 +0100 2008"

end

Named scope with variables

in model *.rb (in this case weight_meassurements.rb)

named_scope :user_weight_meassurements, lambda { |user_id| { :order => 'created_at DESC', :conditions => ["user_id == ?", user_id] } }

named_scope :today, lambda { |today| { :conditions => ["created_at > ?", today] } }

Calling from the controllers or helpers @user.weight_meassurements.today('2008-11-07 00:00:00') wil retrieve all weight_meassurement record belonging to the user created after midnight of the passed date.

You can also call WeightMeassurements.user_weight_meassurements(@user.id) for all this user weight meassurement records.

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.

Dienstag, 30. September 2008

Sessions and, or Cookies

Rails 2.0 + uses a cookie on the client bowser to store session data. Sesion data is used to protect against misuse and data theft.

If the client browser has cookies disabled the application with throw an exception for any and all PUT, UPDATE and DESTROY requests.

To safeguard this you should diable any code that results in
PUT, UPDATE and DESTROY requests if cookies are disabled in the browser client.

Just add a protected method in the application controller.

helper_method :cookies_on?
protected

def cookies_on?
..request.cookies["_appname_session"].to_s.include?('_appname_session')
end


The "_appname_session" defalts to the name for your application and is defined in the app/config/environment.rb

config.action_controller.session = {
:session_key => '_appname_session',
:secret => 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
}


In your controllers and views you can now write:

<% if cookies_on? %>
# show the form with the submit button
<% else %>
# show the form without the submit button and display a message telling the user that this site protects the identiy of users with coded cookies and they cannot sumbit the form without cookies enabled in the browser.
<% end %>


As the session cookie won't be avilable until the user has loaded at least two pages of your application, until then your application will be in a state of "cookies disabled".

This is all a bit of a pain, especially in the light of mobile browsers, most of which do not support cookies. However in the light of data protection, there is a real need to come up with practices to deal with this. And rails does a great job - so lets not get pissed off with rails, but more with the twits that seem to think the web is some sort of data free for all.

BTW: Setting your own cookie is as easy as
cookies [:my_name_of_cookie]="hello this string will now be in a cookie in the users browser"

The next time the user views somthing you can read the cookie:
value=cookies[:my_name_of_cookie]
puts value ->
"hello this string will now be in a cookie in the users browser"

Rake migrations effecting exisitng tables

Things that can done:

Adding a new table, Removing a table, Adding a column to an existing table, Removing a column, Renaming a column, Renaming a table, Adding an index, Adding a primary key.

>ruby script/generate migrtion add_price

This creates a new migration file in db/migrations

class AddPrice
...def self.up
.....add_column :products, :price, decimal, :precision => 8, :scale => 2, :default => 0
...end

...def self.down
......remove_column :products, :price
...end
end

Samstag, 20. September 2008

error_messages_on

BIG GOTCHA!

1. don't use redirect_to in the controller otherwise the view wont get, i.e. display the error message. user ender instead.

2. error_messages_on wants the name of the instance variable used in the controller, ie if you use,

error_messages_on 'instance_variable'

then make sure you use
@instance_variable in your controller code. Its this vairable that has the method @instance_vaiable.errors which error_on_messages uses.

Freitag, 19. September 2008

Capistrano Deployment.

Capistrano gets the latest version of the application from a given reposity and puts it online under a specific web domain.

Install Capistrano
1. install gem >gem install capistrano
2. check that worked out >cap -h

Setup app for Capistrano
1. in root directory of the application>capify

Configure Capistrano
(don't use cap deploy:cold - which is suposed to workout the configuration - you have to do the following once)
1. in app/config - edit the deploy.rb file

set :application, "nameofapp"
#Note: This will also be the name of the directory created for the app files
set :repository, "git@git.whateverthedomainis:whateverthenameis.git
#Note: This is the location of the repository of the application
set :deploy_to, "/full/path/from/server/root/directory/to/app/directory/on/server/#{application}
#Note: This is absolute location on the server where the application root directoy will be placed after being fetched from the repository
set :scm, :git
#Note: This is the resposity type (in this case a git)
set :scm_user, "name"
#Note: This is the user_name that is needed to access the repository. note: the need for a password is normally replaced by a ssh public key

set :user, "name"
#Note: This is the ssh username for the domain i.e. >ssh username@yourdomain.com

set :use_sudo, false
#Note: Capistrano will want to make some directorys on the server, it this is set to true it will use sudo before making them. I suggest to keep this false - capistrano does not need it and less things can go wrong, especially the first time.

set :branch, "whateverbranch"
#Note: The deal here is that after capistrano has cloned the repository on the server is will checkout this branch. I could not get this to work - and so expect the last version of the master branch to be checked out (at least with git and v2.5 of capistrano)

role :app, "yourdomain" # i.e. www.whatever.com
#Note: This is the address of the server that hosts the application server (i.e. mongrel, mod_rails etc)
role :web, "yourdomain" # i.e. www.whatever.com
#Note: This is the address of the server that hosts the webserver server (i.e. apache, etc)
role :db, "yourdomain" , :primary => true # i.e. www.whatever.com
#Note: This is the address of the server that hosts the database (i.e. mysql, postresql)
#Note: The :primary tells capistrano which server to run any migrations against.

Setup publickey of your server to access the application repository.
1. Login to server with a ssh shell session (i.e. >ssh name@dominnameofserver (i.e. ssh me@happy.com)) - If you are not working with public keys, then you should be asked for the password to access - after entering it you should be it.

2. cd to home on the server >cd

3. cd to the .ssh directory > cd .ssh
#Note: check for a file id_rsa.pub if its not there, then run ssh-keygen (just enter return at prompts)

3. enter on command line >more id_rsa.pub

4. Copy the key and add it to your existing repository key
Note: github.com and assembla.com have a web interface for your to do that if your repository is hosted there.

5. Check that that works by cloning the application repository by hand on the server

Freeze Rails.

>rake rails:freeze:gems

Vendorize gems #TODO.
If you are using gems but cannot install them on a sharehost then you have the option to vendorize them.

>rake gems:install
>rake gems:unpack:dependencies
>rake gems:build

Make Spin Script.
This is a small script in app/script/ called spin.rb
This script is called by capistrano after the app has been deployed to start the app and web server

#!/bin/sh

#{deploy_to}/current/script/process/spawner \
mongrel \
--environment=production \
--instances=1 \
--address=127.0.0.1 \
--port=#{port}

(#TODO Check the above)

Update Git repository.

git add .
git commit -m 'ready to deploy'
git push origin master

Deploy Setup.

git add .
git commit -m 'ready to deploy'
git push origin master


cap deploy:setup

Check Dependencies.

cap deploy:check

Deploy the Update.

cap deploy:update

Server stuff.
open a shh session on the server

>shh name@domin.xx
>cd to your app root directy
>rake RAILS_ENV=production db:schema:load
note: If this does not work - then obviously you will have to find out why and fix it before continuing.
>script/console production
note: The production environment should load up without any errors.
>>app.get("/")
note: This should return a status code of 200, 302 or similar.

Deploy Start.
On the local machine:

>cap deploy:start
note: This should return a status code of 200, 302 or similar.

Now everthing should have fired up and be working.

Dienstag, 2. September 2008

Developing Rails Plugins with RSpec

To use RSpec while developing plugins install this rspec generator plugin as follows.

Install RSpec Plugin

script/plugin install git://github.com/pat-maddox/rspec-plugin-generator.git

Create Plugin Framework
script/generate rspec_plugin new_fu


Setup Autotesting
create a file: discover.rb to vendor/plugins/new_fu/lib/autotest/


insert the following at the top of the discover.rb file:
$:.push(File.join(File.dirname(__FILE__), %w[.. .. rspec]))
Autotest.add_discovery do
rspec
end

create a spec.opts file in the plugin/new_fu/spec folder and add the following:

--colour
--format progress
--loadby mtime
--reverse

Set Plugin Location
This avoids naming conflicts with other plugins.
create a directory structure within nuw_fu/lib somthing like this.
your_name/name_or_your_company

Now move the new_fu.rb file into the directory name_of_your_company.

Your new_fu.rb file should now be in
app/vendors/plugins/new_fu/your_name/name_of_your_company/new_fu.rb

Start Autotest for Apllication
Open a terminal window and go to the root of your apllication
first type: rake spec
It should run through and sync the app with your rspec environment
Then type: autotest
The autostest should start and re-run everytime you change a file in your application

Set test environment
open a terminal window - locate the base of your app and type:
export RAILS_ENV=test

Start Autotest for Plugin
Open a terminal window and go to the root of your plugin directory
app/vendor/plugins/new_fu/
and type in autotest
The autostest should start and re-run everytime you change a file in your plugin

Set up Plugin init.rb file.
Locate the init.rb file in vendor/plugins/new_fu
add: include 'your_name/name_of_your_company/new_fu'

Set up Plugin as a module
Open your plugin file
vendor/plugins/new_fu/your_name/name_of_your_company/new_fu.rb
add the following.

.module YourName
....module NameOfYourCompany
.......module NewFu
.
...........def hello_world
..............puts "Hello World"
...........end
.
......end
...end
.end

Then in the new_fu_spec.rb file - located in vendor/plugins/new_fu/spec/ - add the following:

.require File.dirname(__FILE__) + '/spec_helper'
.
.describe YourName::NameOfYourCompany::NewFu, "" do
......include YourName::NameOfYourCompany::NewFu
.
......before do
......end
.
......it "should should say hello world" do
........hello_world
.....end
.
.end

The autotest should have passed on the tests and you should see "hello world" somewhere in the output.

######## To Be Continued.....
Further documentation.
Understanding and building plugins - Part I
Understanding and building plugins - Part II
Creating Plugins Manual
Autotesting while writing Rails Plugins

Montag, 1. September 2008

Rspec Helper Extention

Additional Helper Methods (except, with, only) in spec_helper.rb file in project_folder/spec/

class Hash

# filter key out of a hash
# {:a=>1, :b=> 2, :c=> 3}.except(:a)
# results of hash after call {:b=> 2, :c=> 3 }

def except(*keys)
self.reject { |k,v| keys.include?(k || k.to_sym) }
end

# override some keys with a new value
# {:a=>1, :b=> 2, :c=> 3}.with(:a => 4)
# results of hash after call {:a => 4, :b=> 2, c: => 3 }
def with(overrides = {})
self.merge overrides
end

# return a hash with only the pairs identified by the +keys+
# { :a=>1, :b=>2, :c=>3}.only(:a)
# results of hash after call {:a=>1}
def only(*keys)
self.reject { |k,v| !keys.include?(k || k.to_sym ) }
end

end

Samstag, 30. August 2008

Setting the Test, Production, Development Environment

>export RAILS_ENV=test
>export RAILS_ENV=development
>export RAILS_ENV=production


RSpec CheatSheet



















>rake -T spec (output of the available rake tasks for rspec)
>ruby script/spec -h (output availble plugin rspec options)
>ruby script/generate (shows the rspec generators that replace the normal rails generators)
(i.e. ruby script/generate rspec_scaffold will show the available options)
>rake doc:plugins (generate the rspec documentation in doc/plugins/rspec-rails/index.html)
>rake spec (sync the development environement with the test environment before running autotest)
>autotest (starts the background testing)

IMPORTANT: Set the test rspec it set up to work in the test environment, so make sure it has been set
Also see extention spec helper methods post

Git CheatSheet















.gitignore contains the ignore files (add *.log, .DS_Store, config/database.yml)
>git init
>git add .
>git add "file name"
>git status
>git --global user.name "name"
>git --global user.email "email"
>git --global apply.whitespace nowarn
>git commit -m "message describing this commit" or git commit -v (shows you the diffs done and lets you write your commit mesage)
>git commit -a (commit all files that have been changed)
>git commit -a -v (commit all files and show diffs that have been changed)
>git log (give ascii log with messages)
>git log --stat (ascii output graph of the file changes with + and -)
>git log --p (see the diffs of the files)
>gitk (launch a visual tool of the git log). >gitk & to run in the background
>gitk -all (all local and remote branches)

>git branch (show the current branches)
>git branch --color (shows local and remote branches in color)
>git branch "name of branch" (creates a new branch)
>git branch -a (shows all local and remote branches)
>git checkout "name of branch" (to work on the named branch)

>git rebase "name of another branch" (get current changes from another branch into my working branch)
>git diff "branch 1" "branch2" (show the diffs of 2 branches) or pipe to TextMate with git diff "branch1" "branch2" | mate
>git merge branch (merges branch into current branch)
>git reset --hard ORIG_HEAD (revert the merge)
>git stash "message" (save current status of work to a "clipboard")
>git stash list (show the contents of the clipboard)
>git stash apply (bring the status in the clipboard)
>git branch -d branchname (delete a previously merged branch)
>git branch -D branchname (delete a non merged branch)
>git stash clear (clearsout the stach clipboard)

Repositories
copy project to another machine (cp -r or scp -r)
>git clone remotemachineurl (gets a copy of the remote repository from the remote machine)
>git fetch (get a copy of all objects from the remote machine - don't merge with local machine)
>git pull (syncronizes fetches changes from the remote machine with the local machine with the branch I am currently in)
>git push (syncronize local changes back to the remote machine)
>git merge (local merging of 2 branches)
>git remote show name_of_repository (shows some info on the branches in the remote repository)

Setup New Rails Project

  1. Create a new project with: >rails name_of_project, then: >cd name_of_project
  2. Optionally if using other database than Sqlite: > rake db:create:all
  3. Install RSpec Plugin & Framework. Refer to the latest instructions.
  4. Run the RSpec generator to create framework: >ruby script/generate rspec
  5. Create latest plugin documents on local drive with: rake doc:plugins. Location of documentation is "name_of_project/doc/plugins/respec-rails/index.html. Open directly in browser with: open -a Firefox doc/plugins/rspec_on_rails/index.html. Or open index.html
  6. Install and run RSpec plugin framework if needed
  7. Create the git repository with a cd to the "name_of_project" directory and then:
>git config --global user.name "your name"
>git config --global user.email "your mail@provider"
>git config --global apply.whitespace nowarn

to check the settings see .gitconfig or: >git config --list

>git init (creates local repository and the .git directory)

create a .gitignore file and add file to ignore
*.log
database.yml
db/schema.*
.DS_Store

>git add . (add all file and contents to firstime checkin)
>git commit -m "first commit"
>git status (check the repos)

see git cheatsheet for more

Setup Rails 2.1 on Mac Leopard

A version of rails and gem is already installed on the mac so we will update and expand on this installation as follows
  1. Get and Install TextMate
  2. Get and Download MacPorts - Leopard (universal). After the download and installation, edit or add to .bash_profile file the following: export PATH="/opt/local/bin:/opt/local/sbin:$PATH" (see here for more details)
  3. Update macports from the command line terminal with: >sudo port selfupdate. NOTE: I had a problem with awk not being found during the installation. This was solved by running the installation again.
  4. Install Git and Svn integration as follows: >sudo port install git-core +doc +svn
  5. Update gems with: >sudo gem update
  6. Install Rspec gem with: > sudo gem install rspec
  7. Install Zentest with: >sudi gem install ZenTest. You don't need to install the gem if you are only using rails. Zentest enables autotesting in the background.
  8. Install Rspec TextMate bundle specifically for rails supporting development: cd to the TextMate Bundles directory, i.e. > cd ~/Library/Appliction\Support/TextMate/Bundles. Then: > git git clone git://github.com/dchelimsky/rspec-tmbundle.git RSpec.tmbundle

Samstag, 12. Juli 2008

composed_of

class CurrencyRate < ActiveRecord::Base
composed_of :country_rate, :mapping => [%w(rate c_rate) , %w(currency c_currency)]
end

composed_of :value_object_name, :mapping =>
[%w(db_column_name_1 @instance_var_name_1)
%w(db_column_name_2 @instance_var_name_2)]

important: composed_of gives the class object CurrencyRate 2 new methods,
country_rate and country_rate=
the order of the mapping determines the order in which country_rate= receives its values and how the values will be mapped to the database table.


class CountryRate #this is the value object aggregated by CurrencyRate
attr_accessor :c_rate, :c_currency

def initialize(rate,currency="USD")
@c_rate, @c_currency=rate,currency
end
end

class CreateCurrencyRates < ActiveRecord::Migration #This is the table
def self.up
create_table :currency_rates do |t|
t.string :base_currency
t.string :currency
t.float :rate

t.timestamps
end
end

def self.down
drop_table :currency_rates
end
end

######### How it is used

cur=CurrencyRate.new(:base_currency =>"DKK")
cur.country_rate=CountryRate.new(12.4 , "YPN")
cur.save

######## What happens

cur=CurrencyRate.find(:first) # lets find a CurrencyRate object to change
# direct access methods have been stripped
cur.rate=123 # <- undefined method
cur.country_rate.rate=123 # <- no method error
cur.country_rate.c_rate=123 # <- can' modify frozen object

####The correct way to access is as follows

cur.base_currency="YPN"
cur.country_rate=CountryRate.new(345,"PLN")
cur.save # now the

#####before, the database looks like this

id base_currency rate currency
1 DKK 12.4 YPN

####after, it looks like this

id base_currency rate currency
1 YPN 345.0 PLN


Just for claritys sake.

CurrencyRate is a class with one instance var base_currency
CountryRate is a class with two instance vars c_rate and c_currency

with the composed_of method CountryRate has become a value object.
Value Objects: equality is determined by value - (represented by their value)
Entity Objects: equality is determined by identity - (represented by their primary keys)

Donnerstag, 10. Juli 2008

Modeling Rails

Modeling Rails.

Basically, objects can connect to other objects in 3 different ways.
1. By relationship (i.e. person has one favorite book # person belongs_to favorite_book)
2. By inheritance (i.e. author is a person # class Author < Person
3. By Aggregation (i.e Invoice contains a list of items(objects) that have been aggrigated from other objects. composed_of :item :model => "Book"

When writing in rails model the application first.

1. map out the objects & their attributes for the application (i.e)
Customers : first_name, last_name, address
Books : author, title, price, EAN number
Invoice : customer, invoice_number, book

2. then map out the model connections
Customers (1---------n) Invoices
Customer (1---------1) Favorite_book
Invoice (1---------.) Books (invoice aggregates and copies the attributes of a book when added to an order).

3. Then think about how the objects and relationships can be mapped to the database (through active record).
i.e. which tables have which columns and how the models relate to each other - belongs_to, has_many, has_many_and_belongs_to, composed_of

Mittwoch, 9. Juli 2008

Rails Mapping Routes


Mapping Routes Examples

Mapping Objects on Rails

Mapping Objects Examples

Model Code Snippets

def Order < ActiveRecord::Base
has_many :line_items
belongs_to :customer # there's a column "customer_id" in the db table
end

def LineItem < ActiveRecord::Base
belongs_to :order # there's a column "order_id" in the db table
end

def Customer < ActiveRecord::Base
has_many :orders
has_one :address
end

def Address < ActiveRecord::Base
belongs_to :customer
end

belongs_to :some_model,
:class_name => 'MyClass', # specifies other class name
:foreign_key => 'my_real_id', # and primary key
:conditions => 'column = 0' # only finds when this condition met

has_one :some_model,
# as belongs_to and additionally:
:dependent => :destroy # deletes associated object
:order => 'name ASC' # SQL fragment for sorting

has_many :some_model
# as has_one and additionally:
:dependent => :destroy # deletes all dependent data
# calling each objects destroy
:dependent => :delete_all # deletes all dependent data
# without calling the destroy methods
:dependent => :nullify # set association to null, not
# destroying objects
:group => 'name' # adds GROUP BY fragment
:finder_sql => 'select ....' # instead of the Rails finders
:counter_sql => 'select ...' # instead of the Rails counters


validates_presence_of :firstname, :lastname # must be filled out

validates_length_of :password,
:minimum => 8 # more than 8 characters
:maximum => 16 # shorter than 16 characters
:in => 8..16 # between 8 and 16 characters
:too_short => 'way too short'
:too_long => 'way to long'

validates_acceptance_of :eula # Must accept a condition
:accept => 'Y' # default: 1 (ideal for a checkbox)

validates_confirmation_of :password
# the fields password and password_confirmation must match

validates_uniqueness_of :user_name # user_name has to be unique
:scope => 'account_id' # Condition:
# account_id = user.account_id

validates_format_of :email # field must match a regular expression
:with => /^(+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i

validates_numericality_of :value # value is numeric
:only_integer => true
:allow_nil => true

validates_inclusion_of :gender, # value is in enumeration
:in => %w( m, f )

validates_exclusion_of :age # value is not in Enumeration
:in => 13..19 # don't want any teenagers

validates_associated :relation
# validates that the associated object is valid

Options for all validations above:
:message => 'my own errormessage' # eigene Fehlermeldung
:on => :create # or :update (validates only then)
:if => ... # call method oder Proc

Dienstag, 8. Juli 2008

ActiveRecord::Base

These are the public instance methods available for the model classes.

Model Methods

<
<=
<=>
==
===
=~
>
>=
__id__
__send__
`
abstract_class
abstract_class=
abstract_class?
accessible_attributes
active_connection_name
active_connections
acts_like?
add_observer
after_create
after_create_callback_chain
after_destroy
after_destroy_callback_chain
after_find
after_find_callback_chain
after_initialize
after_initialize_callback_chain
after_save
after_save_callback_chain
after_update
after_update_callback_chain
after_validation
after_validation_callback_chain
after_validation_on_create
after_validation_on_create_callback_chain
after_validation_on_update
after_validation_on_update_callback_chain
aggregate_mapping
alias_attribute
alias_method_chain
all
allocate
allow_concurrency
allow_concurrency=
ancestors
as_load_path
attr_accessible
attr_accessor_with_default
attr_internal
attr_internal_accessor
attr_internal_naming_format
attr_internal_naming_format=
attr_internal_reader
attr_internal_writer
attr_protected
attr_readonly
attribute_method_suffix
attribute_types_cached_by_default
attribute_types_cached_by_default=
autoload
autoload?
average
b64encode
base_class
before_create
before_create_callback_chain
before_destroy
before_destroy_callback_chain
before_save
before_save_callback_chain
before_update
before_update_callback_chain
before_validation
before_validation_callback_chain
before_validation_on_create
before_validation_on_create_callback_chain
before_validation_on_update
before_validation_on_update_callback_chain
belongs_to
benchmark
blank?
breakpoint
cache
cache_attribute?
cache_attributes
cached_attributes
calculate
cattr_accessor
cattr_reader
cattr_writer
changed
changed?
class
class_eval
class_inheritable_accessor
class_inheritable_array
class_inheritable_array_writer
class_inheritable_hash
class_inheritable_hash_writer
class_inheritable_reader
class_inheritable_writer
class_name
class_name_of_active_record_descendant
class_of_active_record_descendant
class_variable_defined?
class_variables
clear_active_connection_name
clear_active_connections!
clear_reloadable_connections!
clone
colorize_logging
colorize_logging=
column_methods_hash
column_names
columns
columns_hash
composed_of
compute_type
configurations
configurations=
connected?
connection
connection=
const_defined?
const_get
const_missing
const_set
constants
construct_calculation_sql
construct_count_options_from_args
content_columns
copy_instance_variables_from
count
count_by_sql
count_observers
create
create!
create_reflection
current_scoped_methods
daemonize
dclone
debugger
decode64
decode_b
decrement_counter
default_timezone
default_timezone=
define_attribute_methods
define_callbacks
define_read_methods
delegate
delete
delete_all
delete_observer
delete_observers
deprecate
deprecated_method_warning
deprecation_horizon
descends_from_active_record?
destroy
destroy_all
display
dup
duplicable?
enable_warnings
encode64
encode_quoted_value
enum_for
eql?
equal?
establish_connection
execute_grouped_calculation
execute_simple_calculation
exists?
expand_hash_conditions_for_aggregates
expand_range_bind_variables
extend
extend_with_included_modules_from
extended_by
find
find_by_sql
find_hidden_method
finder_needs_type_condition?
first
freeze
frozen?
gem
generated_methods
generated_methods?
get_primary_key
has_and_belongs_to_many
has_many
has_one
hash
human_attribute_name
id
include?
include_root_in_json
include_root_in_json=
included_in_classes
included_modules
increment_counter
inheritable_attributes
inheritance_column
inheritance_column=
inherited
inspect
instance_eval
instance_exec
instance_method
instance_method_already_implemented?
instance_methods
instance_of?
instance_values
instance_variable_defined?
instance_variable_get
instance_variable_names
instance_variable_set
instance_variables
instantiate_observers
is_a?
json_class_name
kind_of?
last
load
local_constant_names
local_constants
lock_optimistically
lock_optimistically=
locking_column
locking_column=
locking_enabled?
log_connections
logger
logger=
match_attribute_method?
mattr_accessor
mattr_reader
mattr_writer
maximum
method
method_added
method_defined?
methods
minimum
module_eval
mysql_connection
name
named_scope
new
nil?
notify_observers
object_id
observers
observers=
parent
parents
partial_updates
partial_updates=
partial_updates?
pluralize_table_names
pluralize_table_names=
preload_associations
primary_key
primary_key=
primary_key_prefix_type
primary_key_prefix_type=
private_class_method
private_instance_methods
private_method_defined?
private_methods
protected_attributes
protected_instance_methods
protected_method_defined?
protected_methods
public_class_method
public_instance_methods
public_method_defined?
public_methods
quote_bound_value
quote_value
quoted_locking_column
quoted_table_name
rails_original_const_missing
raise_if_bind_arity_mismatch
read_inheritable_attribute
readonly_attributes
record_timestamps
record_timestamps=
reflect_on_aggregation
reflect_on_all_aggregations
reflect_on_all_associations
reflect_on_association
reflections
remove_class
remove_connection
remove_subclasses
remove_subclasses_of
replace_bind_variables
replace_named_bind_variables
require
require_association
require_dependency
require_library_or_gem
require_mysql
require_or_load
reset_column_information
reset_column_information_and_inheritable_attributes_for_all_subclasses
reset_inheritable_attributes
reset_locking_column
reset_primary_key
reset_sequence_name
reset_subclasses
reset_table_name
respond_to?
retrieve_connection
returning
sanitize
sanitize_conditions
sanitize_sql
sanitize_sql_array
sanitize_sql_for_assignment
sanitize_sql_for_conditions
sanitize_sql_hash
sanitize_sql_hash_for_assignment
sanitize_sql_hash_for_conditions
schema_format
schema_format=
scope
scoped
scoped?
scoped_methods
scopes
send
send!
sequence_name
sequence_name=
serialize
serialized_attributes
set_inheritance_column
set_locking_column
set_primary_key
set_readonly_option!
set_sequence_name
set_table_name
silence
silence_stderr
silence_stream
silence_warnings
single_threaded_active_connections
single_threaded_scoped_methods
singleton_methods
skip_time_zone_conversion_for_attributes
skip_time_zone_conversion_for_attributes=
sti_name
store_full_sti_class
store_full_sti_class=
store_full_sti_class?
subclasses
subclasses_of
sum
superclass
superclass_delegating_accessor
superclass_delegating_reader
superclass_delegating_writer
suppress
table_exists?
table_name
table_name=
table_name_prefix
table_name_prefix=
table_name_suffix
table_name_suffix=
taguri
taguri=
taint
tainted?
thread_safe_active_connections
thread_safe_scoped_methods
time_zone_aware_attributes
time_zone_aware_attributes=
to_a
to_enum
to_json
to_param
to_query
to_s
to_yaml
to_yaml_properties
to_yaml_style
transaction
type
uncached
unloadable
untaint
update
update_all
update_counters
update_counters_with_lock
update_counters_without_lock
validate
validate_callback_chain
validate_find_options
validate_on_create
validate_on_create_callback_chain
validate_on_update
validate_on_update_callback_chain
validates_acceptance_of
validates_associated
validates_confirmation_of
validates_each
validates_exclusion_of
validates_format_of
validates_inclusion_of
validates_length_of
validates_numericality_of
validates_presence_of
validates_size_of
validates_uniqueness_of
verification_timeout
verification_timeout=
verify_active_connections!
with_exclusive_scope
with_options
with_scope
write_inheritable_array
write_inheritable_attribute
write_inheritable_hash
yaml_as
yaml_tag_class_name
yaml_tag_read_class
yaml_tag_subclasses?

ActionView Base

These are the public instance methods available for view (i.e. when templates are being rendered).

View Methods

<
<=
<=>
==
===
=~
>
>=
__id__
__send__
`
acts_like?
alias_attribute
alias_method_chain
allocate
ancestors
as_load_path
attr_accessor_with_default
attr_internal
attr_internal_accessor
attr_internal_naming_format
attr_internal_naming_format=
attr_internal_reader
attr_internal_writer
autoload
autoload?
b64encode
blank?
breakpoint
cache_template_extensions=
cache_template_loading
cache_template_loading=
cattr_accessor
cattr_reader
cattr_writer
class
class_eval
class_inheritable_accessor
class_inheritable_array
class_inheritable_array_writer
class_inheritable_hash
class_inheritable_hash_writer
class_inheritable_reader
class_inheritable_writer
class_variable_defined?
class_variables
clone
computed_public_paths
const_defined?
const_get
const_missing
const_set
constants
copy_instance_variables_from
daemonize
dclone
debug_rjs
debug_rjs=
debugger
decode64
decode_b
default_form_builder
default_form_builder=
delegate
deprecate
deprecated_method_warning
deprecation_horizon
display
dup
duplicable?
enable_warnings
encode64
enum_for
eql?
equal?
erb_trim_mode
erb_trim_mode=
erb_variable
erb_variable=
extend
extend_with_included_modules_from
extended_by
field_error_proc
field_error_proc=
find_hidden_method
freeze
frozen?
full_sanitizer
full_sanitizer=
gem
hash
helper_modules
id
include?
included_in_classes
included_modules
inheritable_attributes
inspect
instance_eval
instance_exec
instance_method
instance_methods
instance_of?
instance_values
instance_variable_defined?
instance_variable_get
instance_variable_names
instance_variable_set
instance_variables
is_a?
kind_of?
link_sanitizer
link_sanitizer=
load
local_constant_names
local_constants
mattr_accessor
mattr_reader
mattr_writer
method
method_added
method_defined?
method_names
method_names=
methods
module_eval
name
new
nil?
object_id
parent
parents
private_class_method
private_instance_methods
private_method_defined?
private_methods
protected_instance_methods
protected_method_defined?
protected_methods
public_class_method
public_instance_methods
public_method_defined?
public_methods
rails_original_const_missing
read_inheritable_attribute
remove_class
remove_subclasses
remove_subclasses_of
require
require_association
require_dependency
require_library_or_gem
require_or_load
reset_inheritable_attributes
respond_to?
returning
sanitized_allowed_attributes
sanitized_allowed_attributes=
sanitized_allowed_css_keywords
sanitized_allowed_css_keywords=
sanitized_allowed_css_properties
sanitized_allowed_css_properties=
sanitized_allowed_protocols
sanitized_allowed_protocols=
sanitized_allowed_tags
sanitized_allowed_tags=
sanitized_bad_tags
sanitized_bad_tags=
sanitized_protocol_separator
sanitized_protocol_separator=
sanitized_shorthand_css_properties
sanitized_shorthand_css_properties=
sanitized_uri_attributes
sanitized_uri_attributes=
send
send!
silence_stderr
silence_stream
silence_warnings
singleton_methods
subclasses
subclasses_of
superclass
superclass_delegating_accessor
superclass_delegating_reader
superclass_delegating_writer
suppress
taguri
taguri=
taint
tainted?
to_a
to_enum
to_json
to_param
to_query
to_s
to_yaml
to_yaml_properties
to_yaml_style
type
unloadable
untaint
white_list_sanitizer
white_list_sanitizer=
with_options
write_inheritable_array
write_inheritable_attribute
write_inheritable_hash
yaml_as
yaml_tag_class_name
yaml_tag_read_class
yaml_tag_subclasses?

ApplicationController

These are the ancestors of the ApplicationController (i.e rails controller classes) and the available public instance methods. This as least helps me to understand the range of methods available which makes the API much more understandable.

Controller Methods

<
<=
<=>
==
===
=~
>
>=
__id__
__send__
`
action_methods
acts_like?
add_template_helper
after_filter
after_filters
alias_attribute
alias_method_chain
allocate
allow_concurrency
allow_concurrency=
allow_forgery_protection
allow_forgery_protection=
ancestors
append_after_filter
append_around_filter
append_before_filter
append_view_path
around_filter
as_load_path
asset_host
asset_host=
attr_accessor_with_default
attr_internal
attr_internal_accessor
attr_internal_naming_format
attr_internal_naming_format=
attr_internal_reader
attr_internal_writer
autoload
autoload?
b64encode
before_filter
before_filters
benchmark
blank?
breakpoint
cache_configured?
cache_page
cache_store
cache_store=
cache_sweeper
cached_session_options
caches_action
caches_page
cattr_accessor
cattr_reader
cattr_writer
class
class_eval
class_inheritable_accessor
class_inheritable_array
class_inheritable_array_writer
class_inheritable_hash
class_inheritable_hash_writer
class_inheritable_reader
class_inheritable_writer
class_variable_defined?
class_variables
clone
consider_all_requests_local
consider_all_requests_local=
const_defined?
const_get
const_missing
const_set
constants
controller_class_name
controller_name
controller_path
copy_instance_variables_from
daemonize
dclone
debug_routes
debug_routes=
debugger
decode64
decode_b
default_charset
default_charset=
default_layout
delegate
deprecate
deprecated_method_warning
deprecation_horizon
display
dup
duplicable?
enable_warnings
encode64
enum_for
eql?
equal?
exempt_from_layout
expire_page
extend
extend_with_included_modules_from
extended_by
filter_chain
filter_parameter_logging
find_hidden_method
fragment_cache_store
fragment_cache_store=
freeze
frozen?
gem
hash
helper
helper_attr
helper_method
helpers
hidden_actions
hide_action
id
include?
included_in_classes
included_modules
inheritable_attributes
inspect
instance_eval
instance_exec
instance_method
instance_methods
instance_of?
instance_values
instance_variable_defined?
instance_variable_get
instance_variable_names
instance_variable_set
instance_variables
is_a?
kind_of?
layout
layout_conditions
layout_list
load
local_constant_names
local_constants
logger
logger=
master_helper_module
master_helper_module=
mattr_accessor
mattr_reader
mattr_writer
method
method_added
method_defined?
methods
module_eval
name
new
nil?
object_id
optimise_named_routes
optimise_named_routes=
page_cache_directory
page_cache_directory=
page_cache_extension
page_cache_extension=
param_parsers
param_parsers=
parent
parents
perform_caching
perform_caching=
prepend_after_filter
prepend_around_filter
prepend_before_filter
prepend_view_path
private_class_method
private_instance_methods
private_method_defined?
private_methods
process
process_cgi
process_with_components
process_with_exception
protect_from_forgery
protected_instance_methods
protected_method_defined?
protected_methods
public_class_method
public_instance_methods
public_method_defined?
public_methods
rails_original_const_missing
read_inheritable_attribute
remove_class
remove_subclasses
remove_subclasses_of
request_forgery_protection_options
request_forgery_protection_options=
request_forgery_protection_token
request_forgery_protection_token=
require
require_association
require_dependency
require_library_or_gem
require_or_load
rescue_from
rescue_handlers
rescue_handlers=
rescue_responses
rescue_responses=
rescue_templates
rescue_templates=
reset_inheritable_attributes
resource_action_separator
resource_action_separator=
resources_path_names
resources_path_names=
respond_to?
returning
send
send!
session
session=
session_options
session_options_for
session_store
session_store=
silence
silence_stderr
silence_stream
silence_warnings
singleton_methods
skip_after_filter
skip_before_filter
skip_filter
subclasses
subclasses_of
superclass
superclass_delegating_accessor
superclass_delegating_reader
superclass_delegating_writer
suppress
taguri
taguri=
taint
tainted?
to_a
to_enum
to_json
to_param
to_query
to_s
to_yaml
to_yaml_properties
to_yaml_style
type
unloadable
untaint
verify
view_paths
view_paths=
with_options
write_inheritable_array
write_inheritable_attribute
write_inheritable_hash
yaml_as
yaml_tag_class_name
yaml_tag_read_class
yaml_tag_subclasses?

Donnerstag, 26. Juni 2008

named_scope

in the *.rb models

Class Profile << ActiveRecord::Base
belongs_to: user
belongs_to: team
named_scope :captain, :conditions => { :role => "captain" }
named_scope :liverpool, :include :team, :conditions => { 'teams.name' => 'liverpool' }
end

This allows following:

user.profile.liverpool #-> finds all user profiles that are in the team liverpool
user.profile.captain #-> finds all user profiles that have the role of captain.

Methods, Calls, Blocks, Closures & Lambda

Excellent excellent article!!

http://en.wikibooks.org/wiki/Ruby_Programming/Syntax/Method_Calls

Dienstag, 24. Juni 2008

STUCK things

Associations.
==========

What i want to do....

current_user.following_users.messages

This should deliver a bunch of messages from all the users that the current user is following (a la twitter).

I can't get it to work for the life of me.

################################Here the migrations.

User

create_table "users", :force => true do |t|
t.column :login, :string
t.column :email, :string
t.column :crypted_password, :string, :limit => 40
t.column :salt, :string, :limit => 40
t.column :created_at, :datetime
t.column :updated_at, :datetime
t.column :remember_token, :string
t.column :remember_token_expires_at, :datetime
t.column :activation_code, :string, :limit => 40
t.column :activated_at, :datetime
end


Message

create_table :messages do |t|
t.string :message
t.integer :user_id
t.integer :movie_id
t.timestamps
end


Following

create_table :followings do |t|
t.integer :follower_user_id
t.integer :following_user_id

t.timestamps
end

#############################Here the Models

User

class User < foreign_key =""> :following_user_id, :class_name => "Following"
has_many :follower_users,:foreign_key => :follower_user_id, :class_name => "Following"
has_many :messages
has_many :messages, :through => :follower_users,:foreign_key => :follower_user_id, :class_name => "Following"
has_many :movies, :through => :messages

Message

class Message < foreign_key =""> :following_user_id, :class_name => "Following"
# has_many :follower_users,:foreign_key => :follower_user_id, :class_name => "Following"
end

Following

class Following < foreign_key =""> :follower_user_id, :class_name => "User" #id of the user that is following
belongs_to :following_user, :foreign_key => :following_user_id, :class_name => "User" #id of the user that is being followed
end


+++++++++++++++++++++ my solution so far

@user=User.find_by_id(params[:user_id])
@following_users=@user.followings.each { |follow| follow.user_id }
@messages=Message.find_all_by_user_id(@following_users)

Refactoring
=========

def get_page_count
results = @doc.search("//td[@class='resultCount']/").first.to_s.gsub(/\./,"")
tmp_array=results.scan(/(\d+)-(\d+).*?(\d+)/)
myarray=tmp_array[0]
@max_pages_in_category = 1
if !myarray.nil?
@max_pages_in_category= (myarray[2].to_i / 12) # total number of items / itmes on a page
if (myarray[2].to_i % 12) != 0 then @max_pages_in_category+=1 end
@total_articles_in_category=myarray[2];
end
end


def render_products
titles = @doc.search("//span[@class='srTitle']/")
titles.each do |title|
print "."
string=title.to_s
string.gsub!(/\(.+?\)/,"")
string.gsub!(/\[.+?\]/,"")
if @data_file!=0 : @data_file.puts @tags+":"+string end
end
end


Montag, 23. Juni 2008

Form_for nested

when using nested controllers where forms in the views need to call a nested controller too:

<% form_for([@user, @movie]) do |f| %>
...
<% end %>


This will call the :controller => :movie with the :action => post with the :user_id => @user.id

Freitag, 20. Juni 2008

Model Relationships - has_many belongs_to

ModelOne
has_many :model_twos
has_many :model_threes, :through :model_two

ModelTwo
belongs_to :model_one
belongs_to :model_three

ModelThree
has_many :model_twos
has_many :model_ones, :through :model_two

Rake Scaffold

ruby script/generate scaffold SingularModelName data_field_name:type -c

The -c adds the file generated to the svn repository.

Auto Complete Related Models

Here is an auto_complete example that works accross 2 related models:

movie
has_many :messages

messages
belongs_to :movie

This went in the messages new view.
============================
<%= text_field_with_auto_complete :movie, :movie_name, {:size => 50}, {:url => formatted_movies_path(:js), :method => :get, :param_name => 'search'} %>

as you cannot use the regular auto_complete_for helper for auto complete across models the text_filed_with_auto_complete needs to have a few more things added to it.

:movie is the model name for the auto complete
:movie_name will contain the input from the user
The first {} contains the options for the input field
The second {} contains the options for the java script

in the first {} the field size is set to 50 with :size=>50
in the second {} the
:url tells the auto complete where to go to get its information to give back to the client. In this case its the path to the index function of the movie controller. (:js) means java script is the format to pass around
:method make rails get information rather then post information (which normally happens with the information from an input field)
:param_name set the name of the params hash key with the information being typed into the field.

This was how the messages controller handled the create
===========================================
def create
@message = Message.new(params[:message])
@message.movie=Movie.find_or_create_by_title(:title=> params[:movie][:movie_name])
@message.save
end


This is what happened on the movie index method
======================================
def index
@movies = Movie.find(:all, :limit => 20, :conditions => ['title LIKE?', "%#{params[:search]}%"])

respond_to do |format|
format.html # index.html.erb
format.js #{ render :html => @movies }
format.xml { render :xml => @movies }
end
end

as you can see in the above the index.js.erb file will be rendered when java script is calling this controller method.

This is what the index.js.erb file looks like
================================

<%= auto_complete_result @movies, :title %>

This is a help method from auto complete which renders back the title value for the objects contained in the @movies instance.

!!!!DONT FORGET to add the java script librarys in the layout.
<%= javascript_include_tag :defaults %>

One last thing: Here is the CSS for the auto_complete to add the CSS being used for model so that the defaults can be overridden.

.auto_complete {
position:absolute;
/*width:250; */
overflow: hidden;
white-space: nowrap;
background-color:white;
border:1px solid #888;
margin:0px;
padding:0px;
color: black;
}

.auto_complete ul {
list-style-type: none;
margin:0px;
padding:0px;
color: black;
}

.auto_complete ul li.selected
{
background-color: #fff; /* #bbf; */
color: black;
}

.auto_complete ul li {
list-style-type: none;
display:block;
margin:0;
padding:2px;
height:16px;
color: black;
}

file upload

This file upload form was made to upload a , delimited text file.


<% form_for(@category_movie, :html => { :multipart => true }) do |f| -%>



<%= file_field_tag :dvd_data %>

<%= submit_tag 'Create' %>

<% end -%>

From file to DB through Controller

This method reads data from an uploaded file in a , delimited file and stores it in the database in the movies, categories and category_movies(join table).

category name 1, category name 2, ...., category name x: movie title

def create

while (line=params[:dvd_data].gets)
title=line.scan(/ROOT:.*/).to_s.gsub(/ROOT:/,"")
categories=line.gsub(/ROOT:.*/,"").scan(/.+?,/)
categories.each do |category|
category.gsub!(/,/,"")
the_category = Category.find_or_create_by_name(:name => category)
the_movie= Movie.find_or_create_by_title(:title => title.to_s)
CategoryMovie.find_or_create_by_category_id_and_movie_id(:category_id =>the_category.id, :movie_id=> the_movie.id)
end
end


respond_to do |format|
flash[:notice] = 'DataBase Updated With DVD titles and Categories'
format.html { redirect_to(category_movies_path) }
format.xml { render :xml => @category_movie, :status => :created, :location => @category_movie }
end
end

Donnerstag, 22. Mai 2008

Traps falls installing things, addons and packages

It turns out that using preconfigured binaries and packages are waste of time.
For example. i install ruby using:

useraccount> pfexec pkg install ruby-dev

The package was compiled on the SUN cc compiler - which is fine, but.....
the setup.rb file of the ruby system has all the environment variables set from the machine it was compiled on - and not mine. Editing that file by hand to adapt the environment to my machine is a night mare.

The RMagick gem and for that matter the source code both look at the environment in the setup.rb file and because nothing in there is relevant to my machine the install fails.

useraccount> pfexec uninstall ruby-dev
useraccount> su
superuseraccount> pfexec rm -r /ruby

So the only way to do this properly is uninstall the ruby pkg, get rid of the installation from my file system, down load the source and compile it again.

useraccount> cd /export/home/tmp
useraccount>pfexec wget ftp://ftp.ruby-lang.org/pub/ruby/1.8/ruby-1.8.6-p110.tar.bz2
useraccount>pfexec bunzip2 -dc ruby-1.8.6-p110.tar.bz2 | tar xf -

Using ruby setup.rb

This is a great place to read about it

Mittwoch, 21. Mai 2008

Setting up sendmail

according to the man pages sendmail does not let you send mails outside your domain unless you allow it to.

useraccount> svccfg -s svc:/network/smtp:sendmail setprop config/local_only = false
useraccount> svcadm refresh svc:/network/smtp:sendmail
useraccount> svcadm restart svc:/network/smtp:sendmail

testit

useraccount> sendmail someone@domain.com

Dienstag, 20. Mai 2008

Installing RMagick and ImageMagick

OK this took a day to find out.
RMagick wraps around ImageMagick so you need both of them.
To install ImageMagic you need perl - which is fine but you won't be able to install (configure and make) if perl has been compiled with a c compiler from sun. It throws out -KPIC for gcc and it should send gcc a -fPIC when compiling.

So move rename perl link in the /usr/bin and the the perl root directory wherever that might be forexample /perl

get the stable perl source code from perl.com and download it
useraccount> pfexec tar xvf perl_download
useraccount> pfexec perl_download
useraccount> pfexec ./Configure
useraccount> pfexec make
useraccount> pfexec make test
useraccount> pfexec make install

perl should now be in /opt/bin/perl with a link to it from /usr/bin

Once you have done that download ImageMagick source files
useraccount> pfexec tar xvf ImageMagick
useraccount> cd ImageMagick
useraccount> pfexec ./configure --disable-static --with-modules --without-perl --without-magick-plus-plus --with-quantum-depth=8 CC=gcc
useraccount> pfexec make
useraccount> pfexec make install

ImageMagick should now be in /usr/local/bin

Then test it with
useraccount> /usr/local/bin/convert logo: logo.gif

I did most of the above based on the info here and here