cainlevy / semantic-attributes
- Source
- Commits
- Network (4)
- Issues (0)
- Downloads (0)
- Wiki (1)
- Graphs
-
Branch:
master
semantic-attributes / gist.rdoc
| 0b163757 » | cainlevy | 2008-10-07 | 1 | ==Describing | |
| 2 | |||||
| 3 | Format: | ||||
| 4 | |||||
| 5 | #{attribute_name}_#{verb}_#{required}?_#{predicate}(options = {}) | ||||
| 6 | |||||
| 7 | Example: | ||||
| 8 | |||||
| 9 | class Post < ActiveRecord::Base | ||||
| 10 | belongs_to :author | ||||
| 11 | |||||
| 12 | title_is_required | ||||
| 13 | author_is_a_required_association | ||||
| 14 | body_has_length :below => 256 | ||||
| 15 | end | ||||
| 16 | |||||
| 17 | ==Predicates | ||||
| 18 | |||||
| 19 | ===aliased | ||||
| 20 | Use when the attribute may only contain certain values, but those values have human labels. | ||||
| 21 | |||||
| 22 | Example: | ||||
| 23 | |||||
| 24 | class User < ActiveRecord::Base | ||||
| 25 | classification_is_aliased :options => { | ||||
| 26 | 1 => "user", | ||||
| 27 | 2 => "admin", | ||||
| 28 | 3 => "superadmin" | ||||
| 29 | } | ||||
| 30 | end | ||||
| 31 | |||||
| 32 | ===association | ||||
| 33 | Use when an association has a minimum or maximum number of records, or when you need to require that it exists. Note that it's ok for two records to require each other -- there won't be any infinitely recursive validation problems. | ||||
| 34 | |||||
| 35 | Example: | ||||
| 36 | |||||
| 37 | class User < ActiveRecord::Base | ||||
| 38 | has_many :quotes | ||||
| 39 | |||||
| 40 | quotes_is_an_association :max => 3 | ||||
| 41 | end | ||||
| 42 | |||||
| 43 | class Quote < ActiveRecord::Base | ||||
| 44 | belongs_to :user | ||||
| 45 | |||||
| 46 | user_is_a_required_association | ||||
| 47 | end | ||||
| 48 | |||||
| 49 | ===blacklisted | ||||
| 50 | Use when you need to make sure some value is NOT saved. Maybe you've reserved some for yourself? | ||||
| 51 | |||||
| a7280506 » | cainlevy | 2009-01-20 | 52 | By default this is not case sensitive. Which means that by default this assumes you only have strings. If you need to blacklist other data types, set :case_sensitive => false. | |
| 53 | |||||
| 0b163757 » | cainlevy | 2008-10-07 | 54 | Example: | |
| 55 | |||||
| 56 | class User < ActiveRecord::Base | ||||
| a7280506 » | cainlevy | 2009-01-20 | 57 | username_is_blacklisted :restricted => %w(admin superadmin god user anonymous) | |
| 0b163757 » | cainlevy | 2008-10-07 | 58 | end | |
| 59 | |||||
| 60 | ===domain | ||||
| 61 | Use when you need to capture a domain name, without protocol or path information. | ||||
| 62 | |||||
| 63 | Example: | ||||
| 64 | |||||
| 65 | class Account < ActiveRecord::Base | ||||
| 66 | cname_is_domain | ||||
| 67 | end | ||||
| 68 | |||||
| 69 | |||||
| 70 | Use when you want to eliminate malformed email addresses. This will _not_ ensure deliverability -- that requires a field test. | ||||
| 71 | |||||
| 72 | Example: | ||||
| 73 | |||||
| 74 | class User < ActiveRecord::Base | ||||
| 75 | email_address_is_email | ||||
| 76 | end | ||||
| 77 | |||||
| 78 | ===enumerated aka whitelisted | ||||
| 79 | Use when you want to limit the values a field may have. Useful for constraining polymorphic associations! Note that because of how required-ness is handled, if a field is empty this predicate will not be evaluated. | ||||
| 80 | |||||
| 806c2187 » | cainlevy | 2009-01-07 | 81 | Note that this predicate implies required-ness. | |
| 82 | |||||
| 0b163757 » | cainlevy | 2008-10-07 | 83 | Example: | |
| 84 | |||||
| 85 | class Favorite < ActiveRecord::Base | ||||
| 86 | belongs_to :favoritable, :polymorphic => true | ||||
| 87 | |||||
| 88 | # only allow favoriting of a User or Project | ||||
| 89 | favoritable_type_is_enumerated :options => %w(User Project) | ||||
| 90 | end | ||||
| 91 | |||||
| 92 | ===hex_color | ||||
| 93 | Use when you need to capture hex colors. Useful for theming! All colors will be stored in the database with a leading pound sign, expanded to the full six character size (e.g. "a1e" becomes "#aa11ee"). | ||||
| 94 | |||||
| 95 | Example: | ||||
| 96 | |||||
| 97 | class Account < ActiveRecord::Base | ||||
| 98 | background_is_hex_color | ||||
| 99 | end | ||||
| 100 | |||||
| 99c4a4ba » | cainlevy | 2008-11-18 | 101 | ===length aka size | |
| 102 | Use when you need to set an upper or lower boundary on the length of a field. Note that this also works on arrays and hashes. | ||||
| 0b163757 » | cainlevy | 2008-10-07 | 103 | ||
| 104 | Example: | ||||
| 105 | |||||
| 106 | class User < ActiveRecord::Base | ||||
| 107 | username_has_length :range => 3..20 | ||||
| 108 | # the following are identical: | ||||
| 109 | password_has_length :above => 3 | ||||
| 110 | password_has_length :above => 4, :exactly => true | ||||
| 111 | end | ||||
| 112 | |||||
| 113 | ===number | ||||
| 114 | Use when you have a numeric field that needs to be constrained on the number line. | ||||
| 115 | |||||
| 116 | Example: | ||||
| 117 | |||||
| 118 | class Auction < ActiveRecord::Base | ||||
| 119 | buyout_is_number :integer => true | ||||
| 7f66dbbb » | cainlevy | 2008-12-03 | 120 | bid_increment_is_number :at_least => 5 | |
| 0b163757 » | cainlevy | 2008-10-07 | 121 | quantity_is_number :range => 1..10 | |
| 122 | end | ||||
| 123 | |||||
| 124 | ===pattern | ||||
| 125 | Use when you need to define a regular expression pattern for a field. Actually, DON'T USE THIS. Instead, extend it and create a new predicate! | ||||
| 126 | |||||
| 127 | ===phone_number | ||||
| 128 | Use when you want to validate phone numbers against a formal numbering plan. Currently only supports NANP (North American Numbering Plan), which uses the +1 prefix. This predicate is smart enough to exclude the bogus 555-01xx numbers. | ||||
| 129 | |||||
| 130 | If you use Semantic Attributes in an international application before I do, please help by contributing back to this predicate. | ||||
| 131 | |||||
| 132 | Example: | ||||
| 133 | |||||
| 134 | class User < ActiveRecord::Base | ||||
| 135 | mobile_is_a_phone_number | ||||
| 136 | end | ||||
| 137 | |||||
| 138 | ===required | ||||
| 139 | Use when you simple need a field to be required. Note that if the field has any other semantics, you should add required-ness to those! | ||||
| 140 | |||||
| 141 | Example: | ||||
| 142 | |||||
| 143 | class User < ActiveRecord::Base | ||||
| 144 | password_is_required | ||||
| 145 | end | ||||
| 146 | |||||
| 147 | ===same_as | ||||
| 148 | Use when you need some attribute to be the same as another attribute, aka this-is-how-you-do-password-confirmation. | ||||
| 149 | |||||
| 150 | Example: | ||||
| 151 | |||||
| 152 | class User < ActiveRecord::Base | ||||
| 153 | password_confirmation_is_same_as :method => :password | ||||
| 154 | end | ||||
| 155 | |||||
| 156 | ===time | ||||
| 55162668 » | cainlevy | 2009-02-06 | 157 | Use when you have a time field that needs to be constrained on the timeline. You may set your constraint either absolutely (e.g. after Jan 1, 2005) or relatively (e.g. no older than 5 minutes from now). | |
| 0b163757 » | cainlevy | 2008-10-07 | 158 | ||
| 55162668 » | cainlevy | 2009-02-06 | 159 | Example: | |
| 160 | |||||
| 161 | class Project < ActiveRecord::Base | ||||
| 162 | # this deadline must be after Jan 1, 2005 | ||||
| 163 | deadline_is_time :after => Time.parse("2005-01-01 00:00:00") | ||||
| 164 | end | ||||
| 165 | |||||
| 166 | class Project < ActiveRecord::Base | ||||
| 167 | # this deadline must be no older than 5 days and no further in the future than 1 week, as of the time of validation. | ||||
| 168 | deadline_is_time :distance => (-5.days)..(1.week) | ||||
| 169 | end | ||||
| 0b163757 » | cainlevy | 2008-10-07 | 170 | ||
| 171 | ===unique | ||||
| 172 | Use when you need an attribute to be unique, possibly in the scope of some other attributes. By default this is not case sensitive. | ||||
| 173 | |||||
| 174 | Example: | ||||
| 175 | |||||
| 176 | class User < ActiveRecord::Base | ||||
| 177 | email_is_unique :scope => [:account_id] | ||||
| 178 | end | ||||
| 179 | |||||
| 180 | ===url | ||||
| 181 | Use when you have url. Please, use it! URLs can be complex. You may constrain your url to a list of domains, schemes, or ports. You may allow or disallow ip addresses. | ||||
| 182 | |||||
| 183 | Example: | ||||
| 184 | |||||
| 185 | class User < ActiveRecord::Base | ||||
| 186 | homepage_is_url :domain => %w(com net biz info edu) | ||||
| 187 | backup_is_url :schemes => %w(https), :ports => [443], :implied_scheme => 'https' | ||||
| 188 | end | ||||
| 189 | |||||
| 190 | ===usa_state | ||||
| 191 | Use when you have a USA state (or territory). Stores all states using USPS abbreviation. | ||||
| 192 | |||||
| 193 | Example: | ||||
| 194 | |||||
| 195 | class Address < ActiveRecord::Base | ||||
| 196 | state_is_a_usa_state :with_territories => true | ||||
| 197 | end | ||||
| 198 | |||||
| 199 | ===usa_zip_code | ||||
| 200 | Use when you have a USA postal code, possibly with the extended +4 syntax. | ||||
| 201 | |||||
| 202 | Example: | ||||
| 203 | |||||
| 204 | class Address < ActiveRecord::Base | ||||
| 205 | # :extended may be any of :allowed, :required, or false (default) | ||||
| 206 | postal_code_is_a_usa_zip_code :extended => :allowed | ||||
| 207 | end | ||||
| 208 | |||||
