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?