flag_shih_tzu 0.3.8 → 0.3.9

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ NjJlYmRjNDVjNTUxMzdiMjJkMzkwYTRkNDAzMDZlMDIzZTI5OWQ4Ng==
5
+ data.tar.gz: !binary |-
6
+ ZTQ5ZDJjMGY2OTQ4ZjcyYThlMDgzYTlhZDllYjBkZDY2YWEwMzI5Nw==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ NDdmNDM2OGVhNTU2MTQ4YmY2YTgzZWFkYjRlMDgwOWNhZTBiN2MxY2ViZjJl
10
+ ODNjMDQwMzllYjg4NDA5YWEzYWQzNDMxYzFjZmM3YTcwMzM1YTMzYjNkYzJl
11
+ YzZjNjUzOTEwNDg3M2RmZWMwNmZiZDUyMDE5OGQ1YmQ5MzUyN2M=
12
+ data.tar.gz: !binary |-
13
+ YjZjYWU2MDUzOWYxYjNlYzdmODVlYTk5MDgyMjg3MjU2YjYxYWZiNTQ0N2Qw
14
+ NjUzZmI2MDI1M2U1MjliYzc1OGViMzE1MjI4MjhjMzE2YmUwMDJhMTZhY2Fi
15
+ ZGFkODUwMjQ0MzZlYjljMGEyYzJmN2U2YTY3OTE5YTg0MmJhZmM=
data/.gitignore CHANGED
@@ -2,12 +2,10 @@ test/debug.log
2
2
  test/flag_shih_tzu_plugin.sqlite3.db
3
3
  coverage
4
4
  .idea
5
- .idea/*
6
- .idea/**/*
7
5
  *.gem
8
6
  .bundle
9
7
  Gemfile.lock
10
8
  gemfiles/*.lock
11
9
  pkg/*
12
10
  rdoc/*
13
- /.rvmrc
11
+ .rvmrc
@@ -16,4 +16,4 @@ matrix:
16
16
  - rvm: 1.8.7
17
17
  gemfile: gemfiles/Gemfile.activerecord-4.0.x
18
18
  - rvm: 1.9.2
19
- gemfile: gemfiles/Gemfile.activerecord-4.0.x
19
+ gemfile: gemfiles/Gemfile.activerecord-4.0.x
data/CHANGELOG CHANGED
@@ -1,3 +1,14 @@
1
+ Version 0.3.10 - NOV.26.2013
2
+ * Can run tests without coverage by specifying NOCOVER=true by Peter Boling
3
+ * Improved test coverage by Peter Boling
4
+ * Improved documentation by Peter Boling
5
+ * Readme converted to Markdown by Peter Boling
6
+
7
+ Version 0.3.9 - NOV.25.2013
8
+ * Removed runtime dependency on active record and active support by Peter Boling
9
+ * Fixed Coveralls Configuration by Peter Boling
10
+ * Improved Readme by Peter Boling
11
+
1
12
  Version 0.3.8 - NOV.24.2013
2
13
  * Improved Readme / Documentation by Peter Boling
3
14
  * Added Badges by Peter Boling
data/LICENSE ADDED
@@ -0,0 +1,23 @@
1
+ Copyright (c) 2012-3 {Peter Boling}[http://www.railsbling.com/]
2
+ Copyright (c) 2011 {XING AG}[http://www.xing.com/]
3
+
4
+ MIT License
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining
7
+ a copy of this software and associated documentation files (the
8
+ "Software"), to deal in the Software without restriction, including
9
+ without limitation the rights to use, copy, modify, merge, publish,
10
+ distribute, sublicense, and/or sell copies of the Software, and to
11
+ permit persons to whom the Software is furnished to do so, subject to
12
+ the following conditions:
13
+
14
+ The above copyright notice and this permission notice shall be
15
+ included in all copies or substantial portions of the Software.
16
+
17
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,505 @@
1
+ # FlagShihTzu
2
+
3
+ Bit fields for ActiveRecord
4
+
5
+ | Project | Sanitize Email |
6
+ |------------------------ | ----------------- |
7
+ | gem name | flag_shih_tzu |
8
+ | license | MIT |
9
+ | version | [![Gem Version](https://badge.fury.io/rb/flag_shih_tzu.png)](http://badge.fury.io/rb/flag_shih_tzu) |
10
+ | dependencies | [![Dependency Status](https://gemnasium.com/pboling/flag_shih_tzu.png)](https://gemnasium.com/pboling/flag_shih_tzu) |
11
+ | code quality | [![Code Climate](https://codeclimate.com/github/pboling/flag_shih_tzu.png)](https://codeclimate.com/github/pboling/flag_shih_tzu) |
12
+ | continuous integration | [![Build Status](https://secure.travis-ci.org/pboling/flag_shih_tzu.png?branch=master)](https://travis-ci.org/pboling/flag_shih_tzu) |
13
+ | test coverage | [![Coverage Status](https://coveralls.io/repos/pboling/flag_shih_tzu/badge.png)](https://coveralls.io/r/pboling/flag_shih_tzu) |
14
+ | homepage | [https://github.com/pboling/flag_shih_tzu][homepage] |
15
+ | documentation | [http://rdoc.info/github/pboling/flag_shih_tzu/frames][documentation] |
16
+ | author | [Peter Boling](https://coderbits.com/pboling) |
17
+ | Spread ~♡ⓛⓞⓥⓔ♡~ | [![Endorse Me](https://api.coderwall.com/pboling/endorsecount.png)](http://coderwall.com/pboling) |
18
+
19
+ ## Summary
20
+
21
+ An extension for [ActiveRecord](https://rubygems.org/gems/activerecord)
22
+ to store a collection of boolean attributes in a single integer column
23
+ as a [bit field][bit_field].
24
+
25
+ This gem lets you use a single integer column in an ActiveRecord model
26
+ to store a collection of boolean attributes (flags). Each flag can be used
27
+ almost in the same way you would use any boolean attribute on an
28
+ ActiveRecord object.
29
+
30
+ The benefits:
31
+
32
+ * No migrations needed for new boolean attributes. This helps a lot
33
+ if you have very large db-tables, on which you want to avoid `ALTER TABLE`
34
+ whenever possible.
35
+ * Only the one integer column needs to be indexed.
36
+ * [Bitwise Operations][bitwise_operation] are fast!
37
+
38
+ Using FlagShihTzu, you can add new boolean attributes whenever you want,
39
+ without needing any migration. Just add a new flag to the `has_flags` call.
40
+
41
+ What is a ["Shih Tzu"](http://en.wikipedia.org/wiki/Shih_Tzu)?
42
+
43
+
44
+ ## Prerequisites
45
+
46
+ The gem is actively being tested with:
47
+
48
+ * MySQL, PostgreSQL and SQLite3 databases
49
+ * ActiveRecord versions 2.3.x, 3.0.x, 3.1.x, 3.2.x
50
+ * Ruby 1.8.7, 1.9.2, 1.9.3, and 2.0.0 (see .travis.yml for the matrix)
51
+
52
+
53
+ ## Installation
54
+
55
+ ### Rails 2.x
56
+
57
+ In environment.rb:
58
+
59
+ config.gem 'flag_shih_tzu'
60
+
61
+ Then:
62
+
63
+ $ rake gems:install # use sudo if necessary
64
+
65
+ ### Rails 3
66
+
67
+ In Gemfile:
68
+
69
+ gem 'flag_shih_tzu'
70
+
71
+ Then:
72
+
73
+ $ bundle install
74
+
75
+
76
+ ## Usage
77
+
78
+ FlagShihTzu assumes that your ActiveRecord model already has an [integer field][bit_field]
79
+ to store the flags, which should be defined to not allow `NULL` values and
80
+ should have a default value of `0`.
81
+
82
+ ### Defaults (Important)
83
+
84
+ * Due to the default of `0`, *all flags* are initially set to "false").
85
+ * For a default of true it will probably be easier in the long run to negate the flag's meaning / name.
86
+ ** Such as `switched_on` => `switched_off`
87
+ * If you **really** want a different, non-zero, default value for a flag column, proceed *adroitly* with a different sql default for the flag column.
88
+
89
+ ### Database Migration
90
+
91
+ I like to document the intent of the `flags` column in the migration when I can...
92
+
93
+ change_table :spaceships do |t|
94
+ t.integer :flags, :null => false, :default => 0 # flag_shih_tzu-managed bit field
95
+ # Effective booleans which will be stored on the flags column:
96
+ # t.boolean :warpdrive
97
+ # t.boolean :shields
98
+ # t.boolean :electrolytes
99
+ end
100
+
101
+ ### Adding to the Model
102
+
103
+ class Spaceship < ActiveRecord::Base
104
+ include FlagShihTzu
105
+
106
+ has_flags 1 => :warpdrive,
107
+ 2 => :shields,
108
+ 3 => :electrolytes
109
+ end
110
+
111
+ `has_flags` takes a hash. The keys must be positive integers and represent
112
+ the position of the bit being used to enable or disable the flag.
113
+ **The keys must not be changed once in use, or you will get incorrect results.**
114
+ That is why the plugin forces you to set them explicitly.
115
+ The values are symbols for the flags being created.
116
+
117
+
118
+ ### Bit Fields: How it stores the values
119
+
120
+ As said, FlagShihTzu uses a single integer column to store the values for all
121
+ the defined flags as a [bit field][bitfield].
122
+
123
+ The bit position of a flag corresponds to the given key.
124
+
125
+ This way, we can use [bitwise operators][bit_operation] on the stored integer value to set, unset
126
+ and check individual flags.
127
+
128
+ `---+---+---+ +---+---+---`
129
+ | | | | | | | |
130
+ Bit position | 3 | 2 | 1 | | 3 | 2 | 1 |
131
+ (flag key) | | | | | | | |
132
+ `---+---+---+ +---+---+---`
133
+ | | | | | | | |
134
+ Bit value | 4 | 2 | 1 | | 4 | 2 | 1 |
135
+ | | | | | | | |
136
+ `---+---+---+ +---+---+---`
137
+ | e | s | w | | e | s | w |
138
+ | l | h | a | | l | h | a |
139
+ | e | i | r | | e | i | r |
140
+ | c | e | p | | c | e | p |
141
+ | t | l | d | | t | l | d |
142
+ | r | d | r | | r | d | r |
143
+ | o | s | i | | o | s | i |
144
+ | l | | v | | l | | v |
145
+ | y | | e | | y | | e |
146
+ | t | | | | t | | |
147
+ | e | | | | e | | |
148
+ | s | | | | s | | |
149
+ `---+---+---+ +---+---+---`
150
+ | 1 | 1 | 0 | = 4 ` 2 = 6 | 1 | 0 | 1 | = 4 ` 1 = 5
151
+ `---+---+---+ +---+---+---`
152
+
153
+ Read more about [bit fields][bit_field] here: http://en.wikipedia.org/wiki/Bit_field
154
+
155
+
156
+ ### Using a custom column name
157
+
158
+ The default column name to store the flags is `flags`, but you can provide a
159
+ custom column name using the `:column` option. This allows you to use
160
+ different columns for separate flags:
161
+
162
+ has_flags 1 => :warpdrive,
163
+ 2 => :shields,
164
+ 3 => :electrolytes,
165
+ :column => 'features'
166
+
167
+ has_flags 1 => :spock,
168
+ 2 => :scott,
169
+ 3 => :kirk,
170
+ :column => 'crew'
171
+
172
+
173
+ ### Generated boolean patterned instance methods
174
+
175
+ Calling `has_flags`, as shown above on the 'features' column, creates the following instance methods
176
+ on Spaceship:
177
+
178
+ Spaceship#warpdrive
179
+ Spaceship#warpdrive?
180
+ Spaceship#warpdrive=
181
+ Spaceship#warpdrive_changed?
182
+ Spaceship#all_warpdrives
183
+ Spaceship#selected_warpdrives
184
+ Spaceship#select_all_warpdrives
185
+ Spaceship#unselect_all_warpdrives
186
+ Spaceship#selected_warpdrives=
187
+ Spaceship#has_warpdrive?
188
+
189
+ Spaceship#shields
190
+ Spaceship#shields?
191
+ Spaceship#shields=
192
+ Spaceship#shields_changed?
193
+ Spaceship#all_shields
194
+ Spaceship#selected_shields
195
+ Spaceship#select_all_shields
196
+ Spaceship#unselect_all_shields
197
+ Spaceship#selected_shields=
198
+ Spaceship#has_shield?
199
+
200
+ Spaceship#electrolytes
201
+ Spaceship#electrolytes?
202
+ Spaceship#electrolytes=
203
+ Spaceship#electrolytes_changed?
204
+ Spaceship#all_electrolytes
205
+ Spaceship#selected_electrolytes
206
+ Spaceship#select_all_electrolytes
207
+ Spaceship#unselect_all_electrolytes
208
+ Spaceship#selected_electrolytes=
209
+ Spaceship#has_electrolyte?
210
+
211
+
212
+ ### Callbacks and Validations
213
+
214
+ Optionally, you can set the `:bang_methods` option to true to also define the bang methods:
215
+
216
+ Spaceship#electrolytes! # will save the bitwise equivalent of electrolytes = true on the record
217
+ Spaceship#not_electrolytes! # will save the bitwise equivalent of electrolytes = false on the record
218
+
219
+ which respectively enables or disables the electrolytes flag.
220
+
221
+ The `:bang_methods` does not save the records to the database, meaning it *cannot* engage validations and callbacks.
222
+
223
+ Alternatively, if you do want to *save a flag* to the database, while still avoiding validations and callbacks, use `update_flag!` which:
224
+
225
+ * sets a flag on a database record without triggering callbacks or validations
226
+ * optionally syncs the ruby instance with new flag value, by default it does not.
227
+
228
+
229
+ Example:
230
+
231
+ update_flag!(flag_name, flag_value, update_instance = false)
232
+
233
+
234
+ ### Generated class methods
235
+
236
+ Calling `has_flags` as shown above creates the following class methods
237
+ on Spaceship:
238
+
239
+ Spaceship.flag_columns # [:features, :crew]
240
+
241
+
242
+ ### Generated named scopes
243
+
244
+ The following named scopes become available:
245
+
246
+ Spaceship.warpdrive # :conditions => "(spaceships.flags in (1,3,5,7))"
247
+ Spaceship.not_warpdrive # :conditions => "(spaceships.flags not in (1,3,5,7))"
248
+ Spaceship.shields # :conditions => "(spaceships.flags in (2,3,6,7))"
249
+ Spaceship.not_shields # :conditions => "(spaceships.flags not in (2,3,6,7))"
250
+ Spaceship.electrolytes # :conditions => "(spaceships.flags in (4,5,6,7))"
251
+ Spaceship.not_electrolytes # :conditions => "(spaceships.flags not in (4,5,6,7))"
252
+
253
+ If you do not want the named scopes to be defined, set the
254
+ `:named_scopes` option to false when calling `has_flags`:
255
+
256
+ has_flags 1 => :warpdrive, 2 => :shields, 3 => :electrolytes, :named_scopes => false
257
+
258
+ In a Rails 3+ application, FlagShihTzu will use `scope` internally to generate
259
+ the scopes. The option on `has_flags` is still named `:named_scopes` however.
260
+
261
+
262
+ ### Examples for using the generated methods
263
+
264
+ enterprise = Spaceship.new
265
+ enterprise.warpdrive = true
266
+ enterprise.shields = true
267
+ enterprise.electrolytes = false
268
+ enterprise.save
269
+
270
+ if enterprise.shields?
271
+ # ...
272
+ end
273
+
274
+ Spaceship.warpdrive.find(:all)
275
+ Spaceship.not_electrolytes.count
276
+
277
+
278
+ ### Support for manually building conditions
279
+
280
+ The following class methods may support you when manually building
281
+ ActiveRecord conditions:
282
+
283
+ Spaceship.warpdrive_condition # "(spaceships.flags in (1,3,5,7))"
284
+ Spaceship.not_warpdrive_condition # "(spaceships.flags not in (1,3,5,7))"
285
+ Spaceship.shields_condition # "(spaceships.flags in (2,3,6,7))"
286
+ Spaceship.not_shields_condition # "(spaceships.flags not in (2,3,6,7))"
287
+ Spaceship.electrolytes_condition # "(spaceships.flags in (4,5,6,7))"
288
+ Spaceship.not_electrolytes_condition # "(spaceships.flags not in (4,5,6,7))"
289
+
290
+ These methods also accept a `:table_alias` option that can be used when
291
+ generating SQL that references the same table more than once:
292
+
293
+ Spaceship.shields_condition(:table_alias => 'evil_spaceships') # "(evil_spaceships.flags in (2,3,6,7))"
294
+
295
+
296
+ ### Choosing a query mode
297
+
298
+ While the default way of building the SQL conditions uses an `IN()` list
299
+ (as shown above), this approach will not work well for a high number of flags,
300
+ as the value list for `IN()` grows.
301
+
302
+ For MySQL, depending on your MySQL settings, this can even hit the
303
+ `max_allowed_packet` limit with the generated query, or the similar query length maximum for PostgreSQL.
304
+
305
+ In this case, consider changing the flag query mode to `:bit_operator`
306
+ instead of `:in_list`, like so:
307
+
308
+ has_flags 1 => :warpdrive,
309
+ 2 => :shields,
310
+ :flag_query_mode => :bit_operator
311
+
312
+ This will modify the generated condition and named_scope methods to use bit
313
+ operators in the SQL instead of an `IN()` list:
314
+
315
+ Spaceship.warpdrive_condition # "(spaceships.flags & 1 = 1)",
316
+ Spaceship.not_warpdrive_condition # "(spaceships.flags & 1 = 0)",
317
+ Spaceship.shields_condition # "(spaceships.flags & 2 = 2)",
318
+ Spaceship.not_shields_condition # "(spaceships.flags & 2 = 0)",
319
+
320
+ Spaceship.warpdrive # :conditions => "(spaceships.flags & 1 = 1)"
321
+ Spaceship.not_warpdrive # :conditions => "(spaceships.flags & 1 = 0)"
322
+ Spaceship.shields # :conditions => "(spaceships.flags & 2 = 2)"
323
+ Spaceship.not_shields # :conditions => "(spaceships.flags & 2 = 0)"
324
+
325
+ The drawback is that due to the [bitwise operation][bitwise_operation] being done on the SQL side,
326
+ this query can not use an index on the flags column.
327
+
328
+ ### Updating flag column by raw sql
329
+
330
+ If you need to do mass updates without initializing object for each row, you can
331
+ use `#set_flag_sql` method on your class. Example:
332
+
333
+ Spaceship.set_flag_sql(:warpdrive, true) # "flags = flags | 1"
334
+ Spaceship.set_flag_sql(:shields, false) # "flags = flags & ~2"
335
+
336
+ And then use it in:
337
+
338
+ Spaceship.update_all Spaceship.set_flag_sql(:shields, false)
339
+
340
+ Beware that using multiple flag manipulation sql statements in the same query
341
+ probably will not have the desired effect (at least on sqlite3, not tested
342
+ on other databases), so you *should not* do this:
343
+
344
+ Spaceship.update_all "#{Spaceship.set_flag_sql(:shields, false)},#{
345
+ Spaceship.set_flag_sql(:warpdrive, true)}"
346
+
347
+ General rule of thumb: issue only one flag update per update statement.
348
+
349
+ ### Skipping flag column check
350
+
351
+ By default when you call has_flags in your code it will automatically check
352
+ your database to see if you have correct column defined.
353
+
354
+ Sometimes this may not be a wanted behaviour (e.g. when loading model without
355
+ database connection established) so you can set `:check_for_column` option to
356
+ false to avoid it.
357
+
358
+ has_flags 1 => :warpdrive,
359
+ 2 => :shields,
360
+ :check_for_column => false
361
+
362
+
363
+ ## Running the gem tests
364
+
365
+ First, make sure all required gems are installed:
366
+
367
+ $ bundle install
368
+
369
+ The default rake test task will run the tests against the currently locked
370
+ ActiveRecord version (see `Gemfile.lock`):
371
+
372
+ $ NOCOVER=true bundle exec rake test
373
+
374
+ If you want to run the tests against all supported ActiveRecord versions:
375
+
376
+ * you will need to use ruby 1.9.3 as it is the only version of ruby that bridges the gap between rails 2.3 and rails 4.0
377
+ * you may need to run each bundle once:
378
+
379
+
380
+ $ BUNDLE_GEMFILE='gemfiles/Gemfile.activerecord-2.3.x' bundle --quiet
381
+ $ BUNDLE_GEMFILE='gemfiles/Gemfile.activerecord-3.0.x' bundle --quiet
382
+ $ BUNDLE_GEMFILE='gemfiles/Gemfile.activerecord-3.1.x' bundle --quiet
383
+ $ BUNDLE_GEMFILE='gemfiles/Gemfile.activerecord-3.2.x' bundle --quiet
384
+ $ BUNDLE_GEMFILE='gemfiles/Gemfile.activerecord-4.0.x' bundle --quiet
385
+
386
+ Then just:
387
+
388
+ $ NOCOVER=true bundle exec rake test:all
389
+
390
+ This will internally use bundler to load specific ActiveRecord versions
391
+ before executing the tests (see `gemfiles/`), e.g.:
392
+
393
+ $ NOCOVER=true BUNDLE_GEMFILE='gemfiles/Gemfile.activerecord-3.1.x' bundle exec rake test
394
+
395
+ All tests will use an in-memory sqlite database by default.
396
+ If you want to use a different database, see `test/database.yml`,
397
+ install the required adapter gem and use the DB environment variable to
398
+ specify which config from `test/database.yml` to use, e.g.:
399
+
400
+ $ NOCOVER=true DB=mysql bundle exec rake
401
+
402
+
403
+ ## Authors
404
+
405
+ [Peter Boling](http://github.com/pboling),
406
+ [Patryk Peszko](http://github.com/ppeszko),
407
+ [Sebastian Roebke](http://github.com/boosty),
408
+ [David Anderson](http://github.com/alpinegizmo),
409
+ [Tim Payton](http://github.com/dizzy42)
410
+ and a helpful group of
411
+ [contributors](https://github.com/pboling/flag_shih_tzu/contributors).
412
+ Thanks!
413
+
414
+ Find out more about Peter Boling's work
415
+ [RailsBling.com](http://railsbling.com/).
416
+
417
+ Find out more about XING
418
+ [Devblog](http://devblog.xing.com/).
419
+
420
+
421
+ ## How you can help!
422
+
423
+ Take a look at the `reek` list, which is the file called `REEK`, and stat fixing things. Once you complete a change, run the tests. See "Running the gem tests".
424
+
425
+ If the tests pass refresh the `reek` list:
426
+
427
+ bundle exec rake reek > REEK
428
+
429
+ Follow the instructions for "Contributing" below.
430
+
431
+
432
+ ## Contributing
433
+
434
+ 1. Fork it
435
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
436
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
437
+ 4. Push to the branch (`git push origin my-new-feature`)
438
+ 5. Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
439
+ 6. Create new Pull Request
440
+
441
+
442
+ ## Versioning
443
+
444
+ This library aims to adhere to [Semantic Versioning 2.0.0](http://semver.org/).
445
+ Violations of this scheme should be reported as bugs. Specifically,
446
+ if a minor or patch version is released that breaks backward
447
+ compatibility, a new version should be immediately released that
448
+ restores compatibility. Breaking changes to the public API will
449
+ only be introduced with new major versions.
450
+
451
+ As a result of this policy, you can (and should) specify a
452
+ dependency on this gem using the [Pessimistic Version Constraint](http://docs.rubygems.org/read/chapter/16#page74) with two digits of precision.
453
+
454
+ For example:
455
+
456
+ spec.add_dependency 'flag_shih_tzu', '~> 4.0'
457
+
458
+
459
+ ## 2012 Change of Ownership and 0.3.X Release Notes
460
+
461
+ FlagShihTzu was originally a [XING AG][http://www.xing.com/] project. [Peter Boling](http://peterboling.com) was a long time contributor and watcher of the project.
462
+ In September 2012 XING transferred ownership of the project to Peter Boling. Peter Boling had been maintaining a
463
+ fork with extended capabilities. These additional features become a part of the 0.3 line. The 0.2 line of the gem will
464
+ remain true to XING's original. The 0.3 line aims to maintain complete parity and compatibility with XING's original as
465
+ well. I will continue to monitor other forks for original ideas and improvements. Pull requests are welcome, but please
466
+ rebase your work onto the current master to make integration easier.
467
+
468
+ More information on the changes for 0.3.X: [pboling/flag_shih_tzu/wiki/Changes-for-0.3.x](https://github.com/pboling/flag_shih_tzu/wiki/Changes-for-0.3.x)
469
+
470
+
471
+ ## License
472
+
473
+ MIT License
474
+
475
+ Copyright (c) 2012-3 [Peter Boling][peterboling] of [RailsBling.com][railsbling]
476
+
477
+ Copyright (c) 2011 [XING AG](http://www.xing.com/)
478
+
479
+ Permission is hereby granted, free of charge, to any person obtaining
480
+ a copy of this software and associated documentation files (the
481
+ "Software"), to deal in the Software without restriction, including
482
+ without limitation the rights to use, copy, modify, merge, publish,
483
+ distribute, sublicense, and/or sell copies of the Software, and to
484
+ permit persons to whom the Software is furnished to do so, subject to
485
+ the following conditions:
486
+
487
+ The above copyright notice and this permission notice shall be
488
+ included in all copies or substantial portions of the Software.
489
+
490
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
491
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
492
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
493
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
494
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
495
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
496
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
497
+
498
+ [semver]: http://semver.org/
499
+ [pvc]: http://docs.rubygems.org/read/chapter/16#page74
500
+ [railsbling]: http://www.railsbling.com
501
+ [peterboling]: http://www.peterboling.com
502
+ [documentation]: http://rdoc.info/github/pboling/flag_shih_tzu/frames
503
+ [homepage]: https://github.com/pboling/flag_shih_tzu
504
+ [bit_field]: http://en.wikipedia.org/wiki/Bit_field
505
+ [bitwise_operation]: http://en.wikipedia.org/wiki/Bitwise_operation