txprails 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,191 @@
1
+ #include "ruby.h"
2
+ #include "txparse.h"
3
+
4
+ //---------------------------------------------------------------------------
5
+ const string TXPDictSpaces = " \t\r\n";
6
+ const string TXPDictWordLim = " \t\r\n,<>/=";
7
+ const string TXPDictSingleQuote = "'";
8
+ const string TXPDictDoubleQuote = "\"";
9
+
10
+ string txp_domain_str = "dmstk";
11
+
12
+ //---------------------------------------------------------------------------
13
+ static bool txp_isspace(string::const_iterator iter)
14
+ {
15
+ return find(TXPDictSpaces.begin(), TXPDictSpaces.end(), *iter) != TXPDictSpaces.end();
16
+ }
17
+
18
+ //---------------------------------------------------------------------------
19
+ static bool txp_valid_chars(
20
+ string::const_iterator iter,
21
+ string::const_iterator end
22
+ )
23
+ {
24
+ if (*iter == '/') { iter++; end++; }
25
+ for (; iter != end; ++iter) {
26
+ if (::isspace(*iter)) return false;
27
+ if (*iter == ':') return true;
28
+ if (!::isalpha(*iter)) return false;
29
+ }
30
+ return false; // No se encontró los dos puntos...
31
+ }
32
+
33
+ //---------------------------------------------------------------------------
34
+ string::const_iterator txp_find_tag(
35
+ string::const_iterator iter,
36
+ string::const_iterator end
37
+ )
38
+ {
39
+ // Encontramos un TAG de plantilla cuando tengamos "<" + [a-z]{3} + ":"
40
+ // O también cuando tengamos "</" ya que es de cierre...
41
+ while (iter != end) {
42
+ if ((*iter == '<') && (end - iter > 5) && txp_valid_chars(iter+1, iter+7))
43
+ return iter;
44
+ ++iter;
45
+ }
46
+ return iter;
47
+ }
48
+
49
+ //---------------------------------------------------------------------------
50
+ string::const_iterator txp_find_close(
51
+ string::const_iterator iter,
52
+ string::const_iterator end
53
+ )
54
+ {
55
+ // Encontramos un final de TAG cuando tengamos ">"
56
+ for (; iter != end; ++iter) {
57
+ if (*iter == '>') return iter+1;
58
+ }
59
+ return iter;
60
+ }
61
+
62
+ //---------------------------------------------------------------------------
63
+ string::const_iterator txp_find_par(
64
+ string::const_iterator begin,
65
+ string::const_iterator end,
66
+ VALUE tag
67
+ )
68
+ {
69
+ // TODO:
70
+ // Tenemos que hacer el mismo recorrido a partir de "begin" que en el
71
+ // bucle de parsing, pero esta vez sólo para encontrar un tag coincidente
72
+ // con el que nos pasan... Todo esto no es más que una prueba, habría que
73
+ // hacer un algoritmo más "robusto" para esto (Por ejemplo con pilas para
74
+ // encontrar un tag balanceado, ahora no pueden estar anidados.)
75
+
76
+ string::const_iterator old;
77
+
78
+ while (begin != end) {
79
+ begin = txp_find_tag(begin, end);
80
+ if (begin != end) {
81
+ // Estamos en un tag...
82
+ old = begin;
83
+ begin = txp_find_close(begin, end);
84
+ if (begin != end) {
85
+ VALUE tag_txt = rb_str_new2(string(old, begin).c_str());
86
+ VALUE new_tag = rb_class_new_instance(1, &tag_txt, rb_const_get(mTXParse, rb_intern("Tag")));
87
+ /*
88
+ printf(":::: SEARCHING PAR (D:'%s' vs '%s', N:'%s' vs. '%s')\n"
89
+ , RSTRING(rb_iv_get(tag, "@domain"))->ptr
90
+ , RSTRING(rb_iv_get(new_tag, "@domain"))->ptr
91
+ , RSTRING(rb_iv_get(tag, "@name"))->ptr
92
+ , RSTRING(rb_iv_get(new_tag, "@name"))->ptr
93
+ );
94
+ */
95
+
96
+ // Vale, comprobamos que el tag se llama igual...
97
+ if (!rb_str_cmp(rb_iv_get(tag, "@domain"), rb_iv_get(new_tag, "@domain")) &&
98
+ !rb_str_cmp(rb_iv_get(tag, "@name"), rb_iv_get(new_tag, "@name"))) {
99
+ // printf(":::: FOUND!!!\n");
100
+
101
+ // Es el mismo TAG... ¿Es de cierre?
102
+ if (rb_iv_get(new_tag, "@is_close") == Qtrue) {
103
+ // printf(":::: New Tag is CLOSE\n");
104
+ // printf(":::: DBG: [%s]\n", string(old, end).c_str());
105
+ return old;
106
+ }
107
+ }
108
+ }
109
+ }
110
+ }
111
+ return end; // What else?
112
+ }
113
+
114
+
115
+ #define DEBUG_POS(str, pos) \
116
+ {\
117
+ string strdebug = string(str.size(), ' '); \
118
+ strdebug[pos] = '$'; \
119
+ printf("|%s|\n", str.c_str()); \
120
+ printf("|%s|\n", strdebug.c_str()); \
121
+ }
122
+
123
+ //---------------------------------------------------------------------------
124
+ void txp_parse_tag(const string tag, string &domain, string &name, map<string, string> &attrs, bool &close)
125
+ {
126
+ string::size_type pos = 0, pos2;
127
+
128
+ if ((tag.size() == 0) || (tag[pos++] != '<')) {
129
+ rb_raise(rb_eSyntaxError, "Tag should begin with '<'");
130
+ // rb_raise no retorna...
131
+ }
132
+
133
+ if (tag[pos] == '/') {
134
+ close = true;
135
+ pos++;
136
+ }
137
+
138
+ pos2 = tag.find_first_of(":/> \t\r\n", pos);
139
+ if ((pos2 == string::npos) || (tag[pos2] != ':')) {
140
+ rb_warn("TAG Should have a 'domain'. Assuming 'dmstk'");
141
+ // rb_raise(rb_eSyntaxError, "Tag should have a domain.");
142
+ domain = "dmstk";
143
+ name = string(tag, pos, pos2 - pos);
144
+ } else {
145
+ domain = string(tag, pos, pos2 - pos);
146
+ pos = pos2 + 1;
147
+ pos2 = tag.find_first_of(":/> \t\r\n", pos);
148
+ name = string(tag, pos, pos2 - pos);
149
+ }
150
+
151
+ // Si soy tag de cierre, no debo tener attributos.
152
+ if (close) return;
153
+
154
+ // Parseado el dominio y el nombre, saltamos a los attributos...
155
+ pos = tag.find_first_not_of(" \t\r\n", pos2);
156
+ if ((pos == string::npos) || (pos == '>')) return;
157
+
158
+ while ((pos != string::npos) && (tag[pos] != '>')) {
159
+ // Caso especial del tag de autocierre y el final de tag '>'
160
+ if ((tag[pos] == '/') && (tag[pos+1] == '>')) {
161
+ close = true; // autoclose ??
162
+ pos = string::npos;
163
+ break;
164
+ }
165
+
166
+ pos2 = tag.find_first_of(" \t\r\n,<>/=", pos);
167
+ string attrname = string(tag, pos, pos2 - pos);
168
+ string attrval = "";
169
+
170
+ pos2 = tag.find_first_not_of(" \t\r\n", pos2);
171
+ if ((pos2 != string::npos) && (tag[pos2]=='=')) {
172
+ // Parseando valor de atributo
173
+ pos2 = tag.find_first_not_of(" \t\r\n", pos2+1);
174
+
175
+ switch (tag[pos2]) {
176
+ case '\'': pos = pos2+1; pos2 = tag.find_first_of("'", pos); break;
177
+ case '"': pos = pos2+1; pos2 = tag.find_first_of("\"", pos); break;
178
+ default: pos = pos2; pos2 = tag.find_first_of(" \t\r\n"); break;
179
+ }
180
+ attrval = string(tag, pos, pos2 - pos);
181
+ } else {
182
+ // Atributo sin valores!! Asumimos --> nombre="nombre"
183
+ attrval = attrname;
184
+ }
185
+
186
+ attrs[attrname] = attrval;
187
+
188
+ // Tenemos que dejar "pos" en el siguiente atributo...
189
+ pos = tag.find_first_not_of(" \t\r\n", pos2+1);
190
+ }
191
+ }
@@ -0,0 +1,17 @@
1
+ #ifndef TXPARSE_LIB
2
+ #define TXPARSE_LIB
3
+
4
+ #include <string>
5
+ #include <map>
6
+
7
+ using namespace std;
8
+
9
+ extern string txp_domain_str;
10
+
11
+ //---------------------------------------------------------------------------
12
+ string::const_iterator txp_find_tag(string::const_iterator iter, string::const_iterator end);
13
+ string::const_iterator txp_find_close(string::const_iterator iter, string::const_iterator end);
14
+ string::const_iterator txp_find_par(string::const_iterator begin, string::const_iterator end, VALUE tag);
15
+ void txp_parse_tag(const string tag, string &domain, string &name, map<string, string> &attrs, bool &close);
16
+
17
+ #endif
@@ -0,0 +1,109 @@
1
+ #include "ruby.h"
2
+ #include "txparse.h"
3
+
4
+ extern "C" VALUE tag_initialize(VALUE self, VALUE orig)
5
+ {
6
+ string domain, name;
7
+ map<string, string> attrs;
8
+ bool is_close = false;
9
+ VALUE attr_hash = rb_hash_new();
10
+
11
+ rb_check_type(orig, T_STRING);
12
+ txp_parse_tag(string(RSTRING(orig)->ptr), domain, name, attrs, is_close);
13
+
14
+ /*
15
+ printf("PARSE-TAG DBG: ORIG='%s'\n", RSTRING(orig)->ptr);
16
+ printf(" DOMAIN='%s', NAME='%s'\n", domain.c_str(), name.c_str());
17
+ printf(" ATTRS(num)='%d', CLOSED='%c'\n", (int)attrs.size(), is_close ? 'Y' : 'N');
18
+ */
19
+
20
+ if (attrs.size()) {
21
+ for (map<string, string>::const_iterator iter = attrs.begin()
22
+ ; iter != attrs.end()
23
+ ; ++iter)
24
+ {
25
+ rb_hash_aset(attr_hash, rb_str_new2((*iter).first.c_str()), rb_str_new2((*iter).second.c_str()));
26
+ }
27
+ }
28
+
29
+ rb_iv_set(self, "@name", rb_str_new2(name.c_str()));
30
+ rb_iv_set(self, "@domain", rb_str_new2(domain.c_str()));
31
+ rb_iv_set(self, "@is_close", is_close ? Qtrue : Qfalse);
32
+ rb_iv_set(self, "@attr", attr_hash);
33
+ rb_iv_set(self, "@orig", orig);
34
+ return self;
35
+ }
36
+
37
+ extern "C" VALUE tag_name(VALUE self)
38
+ {
39
+ return rb_iv_get(self, "@name");
40
+ }
41
+
42
+ extern "C" VALUE tag_name_set(VALUE self, VALUE new_name)
43
+ {
44
+ return rb_iv_set(self, "@name", new_name);
45
+ }
46
+
47
+
48
+ extern "C" VALUE tag_domain(VALUE self)
49
+ {
50
+ return rb_iv_get(self, "@domain");
51
+ }
52
+
53
+ extern "C" VALUE tag_domain_set(VALUE self, VALUE new_domain)
54
+ {
55
+ return rb_iv_set(self, "@domain", new_domain);
56
+ }
57
+
58
+ extern "C" VALUE tag_thing(VALUE self)
59
+ {
60
+ return rb_iv_get(self, "@thing");
61
+ }
62
+
63
+ extern "C" VALUE tag_thing_set(VALUE self, VALUE new_thing)
64
+ {
65
+ return rb_iv_set(self, "@thing", new_thing);
66
+ }
67
+
68
+ extern "C" VALUE tag_attributes(VALUE self)
69
+ {
70
+ return rb_iv_get(self, "@attr");
71
+ }
72
+
73
+
74
+
75
+ extern "C" VALUE tag_is_close(VALUE self)
76
+ {
77
+ return rb_iv_get(self, "@is_close");
78
+ }
79
+
80
+ extern "C" VALUE tag_orig(VALUE self)
81
+ {
82
+ return rb_iv_get(self, "@orig");
83
+ }
84
+
85
+
86
+
87
+
88
+ VALUE mTXParseTag = Qnil;
89
+ void Init_TXParseTag()
90
+ {
91
+ // VALUE TXParse_Module = rb_define_module("TXParse");
92
+ mTXParseTag = rb_define_class_under(mTXParse, "Tag", rb_cObject);
93
+
94
+ rb_define_method(mTXParseTag, "initialize", RUBY_METHOD_FUNC(tag_initialize), 1);
95
+
96
+ rb_define_method(mTXParseTag, "name", RUBY_METHOD_FUNC(tag_name), 0);
97
+ rb_define_method(mTXParseTag, "name=", RUBY_METHOD_FUNC(tag_name_set), 1);
98
+
99
+ rb_define_method(mTXParseTag, "domain", RUBY_METHOD_FUNC(tag_domain), 0);
100
+ rb_define_method(mTXParseTag, "domain=", RUBY_METHOD_FUNC(tag_domain_set), 1);
101
+
102
+ rb_define_method(mTXParseTag, "thing", RUBY_METHOD_FUNC(tag_thing), 0);
103
+ rb_define_method(mTXParseTag, "thing=", RUBY_METHOD_FUNC(tag_thing_set), 1);
104
+
105
+ rb_define_method(mTXParseTag, "attr", RUBY_METHOD_FUNC(tag_attributes), 0);
106
+
107
+ rb_define_method(mTXParseTag, "close?", RUBY_METHOD_FUNC(tag_is_close), 0);
108
+ rb_define_method(mTXParseTag, "orig", RUBY_METHOD_FUNC(tag_orig), 0);
109
+ }
@@ -0,0 +1,7 @@
1
+ #ifndef TXPARSE_TAG
2
+ #define TXPARSE_TAG
3
+
4
+ extern VALUE mTXParseTag;
5
+ void Init_TXParseTag();
6
+
7
+ #endif
data/lib/init_rails.rb ADDED
@@ -0,0 +1,16 @@
1
+ begin
2
+ require File.join(File.dirname(__FILE__), 'txprails') # From here
3
+ rescue LoadError
4
+ begin
5
+ require 'txprails' # From gem
6
+ rescue LoadError => e
7
+ # gems:install may be run to install TXPRails with the skeleton plugin
8
+ # but not the gem itself installed.
9
+ # Don't die if this is the case.
10
+ raise e unless defined?(Rake) && Rake.application.top_level_tasks.include?('gems:install')
11
+ end
12
+ end
13
+
14
+ # Load TXPRails.
15
+ # TXPRails may be undefined if we're running gems:install.
16
+ TXPRails.init_rails if defined?(TXPRails)
@@ -0,0 +1,88 @@
1
+ require 'optparse'
2
+ require 'fileutils'
3
+
4
+ module TXPRails
5
+ # This module handles miscelaneous command line utilities
6
+ class Commands
7
+ # @param args [Array<String>] The command-line arguments
8
+ def initialize(args)
9
+ @args = args
10
+ @options = {}
11
+ @options[:requires] = [] # ??
12
+ @options[:load_paths] = [] # ??
13
+ end
14
+
15
+ # Parses the command-line arguments and runs the executable.
16
+ # Calls `Kernel#exit` at the end, so it never returns.
17
+ def parse!
18
+ begin
19
+ @opts = OptionParser.new(&method(:set_opts))
20
+ @opts.parse!(@args)
21
+ @options
22
+ rescue Exception => e
23
+ raise e if e.is_a?(SystemExit)
24
+
25
+ $stderr.puts e.message
26
+ exit 1
27
+ end
28
+ exit 0
29
+ end
30
+
31
+ # @return [String] A description of the executable
32
+ def to_s
33
+ @opts.to_s
34
+ end
35
+
36
+ protected
37
+
38
+ # Tells optparse how to parse the arguments
39
+ # available for all executables.
40
+ #
41
+ # This is meant to be overridden by subclasses
42
+ # so they can add their own options.
43
+ #
44
+ # @param opts [OptionParser]
45
+ def set_opts(opts)
46
+ opts.on_tail("-?", "-h", "--help", "Show this message") do
47
+ puts opts
48
+ exit
49
+ end
50
+
51
+ opts.on_tail("-v", "--version", "Print version") do
52
+ puts("TXPRails #{::TXPRails.version[:string]}")
53
+ exit
54
+ end
55
+
56
+ opts.on('--rails RAILS_DIR', "Install TXPRails from the Gem to a Rails project") do |dir|
57
+ original_dir = dir
58
+ dir = File.join(dir, 'vendor', 'plugins')
59
+ unless File.exists?(dir)
60
+ puts "Directory #{dir} doesn't exist"
61
+ exit
62
+ end
63
+
64
+ dir = File.join(dir, 'txprails')
65
+ if File.exists?(dir)
66
+ print "Directory #{dir} already exists, overwrite [y/N]? "
67
+ exit if gets !~ /y/i
68
+ FileUtils.rm_rf(dir)
69
+ end
70
+
71
+ begin
72
+ Dir.mkdir(dir)
73
+ rescue SystemCallError
74
+ puts "Cannot create #{dir}"
75
+ exit
76
+ end
77
+
78
+ File.open(File.join(dir, 'init.rb'), 'w') do |file|
79
+ file << File.read(File.dirname(__FILE__) + "/../init_rails.rb")
80
+ end
81
+
82
+ puts "Haml plugin added to #{original_dir}"
83
+ exit
84
+ end
85
+ end
86
+
87
+ end
88
+ end
@@ -0,0 +1,29 @@
1
+ # Simple template initialization code
2
+ # Borrowed ideas from Haml, but VERY much simplyfied
3
+ # WARNING: We choose to use the plugin approach, so NO RAILS < 2.1.0 compatibility!
4
+
5
+ module TXPRails
6
+
7
+ class TXPTemplateHandler < TXPRails::Util.av_template_class(:Handler)
8
+ include TXP
9
+
10
+ def initialize(view)
11
+ @view = view
12
+ end
13
+
14
+ def render(template, local_assigns = {})
15
+ parse(template.source)
16
+ end
17
+
18
+ def compilable?
19
+ false
20
+ end
21
+ end
22
+ end
23
+
24
+
25
+ if defined? ActionView::Template and ActionView::Template.respond_to? :register_template_handler
26
+ ActionView::Template
27
+ else
28
+ ActionView::Base
29
+ end.register_template_handler(:txp, TXPRails::TXPTemplateHandler)
@@ -0,0 +1,44 @@
1
+ module TXPRails
2
+ # A module containing various useful functions.
3
+ module Util
4
+ extend self
5
+
6
+ # An array of ints representing the Ruby version number.
7
+ RUBY_VERSION = ::RUBY_VERSION.split(".").map {|s| s.to_i}
8
+
9
+ # Returns the path of a file relative to the Haml root directory.
10
+ #
11
+ # @param file [String] The filename relative to the Haml root
12
+ # @return [String] The filename relative to the the working directory
13
+ def scope(file)
14
+ File.join(File.dirname(File.dirname(File.dirname(File.expand_path(__FILE__)))), file)
15
+ end
16
+
17
+ ## Cross Rails Version Compatibility
18
+
19
+ # Returns the root of the Rails application,
20
+ # if this is running in a Rails context.
21
+ # Returns `nil` if no such root is defined.
22
+ #
23
+ # @return [String, nil]
24
+ def rails_root
25
+ return Rails.root.to_s if defined?(Rails.root)
26
+ return RAILS_ROOT.to_s if defined?(RAILS_ROOT)
27
+ return nil
28
+ end
29
+
30
+ # Returns an ActionView::Template* class.
31
+ # In pre-3.0 versions of Rails, most of these classes
32
+ # were of the form `ActionView::TemplateFoo`,
33
+ # while afterwards they were of the form `ActionView::Template::Foo`.
34
+ #
35
+ # @param name [#to_s] The name of the class to get.
36
+ # For example, `:Error` will return `ActionView::TemplateError`
37
+ # or `ActionView::Template::Error`.
38
+ def av_template_class(name)
39
+ return ActionView.const_get("Template#{name}") if ActionView.const_defined?("Template#{name}")
40
+ return ActionView::Template.const_get(name.to_s)
41
+ end
42
+
43
+ end
44
+ end
@@ -0,0 +1,64 @@
1
+ require 'txprails/util'
2
+
3
+ module TXPRails
4
+ # Handles TXPRails version-reporting.
5
+ # TXPRails not only reports the standard three version numbers,
6
+ # but its Git revision hash as well,
7
+ # if it was installed from Git.
8
+ module Version
9
+ include TXPRails::Util
10
+
11
+ # Returns a hash representing the version of TXPRails.
12
+ # The `:major`, `:minor`, and `:teeny` keys have their respective numbers as Fixnums.
13
+ # The `:name` key has the name of the version.
14
+ # The `:string` key contains a human-readable string representation of the version.
15
+ # The `:number` key is the major, minor, and teeny keys separated by periods.
16
+ # If TXPRails is checked out from Git, the `:rev` key will have the revision hash.
17
+ # For example:
18
+ #
19
+ # {
20
+ # :string => "2.1.0.9616393",
21
+ # :rev => "9616393b8924ef36639c7e82aa88a51a24d16949",
22
+ # :number => "2.1.0",
23
+ # :major => 2, :minor => 1, :teeny => 0
24
+ # }
25
+ #
26
+ # @return [{Symbol => String/Fixnum}] The version hash
27
+ def version
28
+ return @@version if defined?(@@version)
29
+
30
+ numbers = File.read(scope('VERSION')).strip.split('.').map { |n| n.to_i }
31
+ name = File.read(scope('VERSION_NAME')).strip
32
+ @@version = {
33
+ :major => numbers[0],
34
+ :minor => numbers[1],
35
+ :teeny => numbers[2],
36
+ :name => name
37
+ }
38
+ @@version[:number] = [:major, :minor, :teeny].map { |comp| @@version[comp] }.compact.join('.')
39
+ @@version[:string] = @@version[:number].dup
40
+
41
+ if File.exists?(scope('REVISION'))
42
+ rev = File.read(scope('REVISION')).strip
43
+ rev = nil if rev !~ /^([a-f0-9]+|\(.*\))$/
44
+ end
45
+
46
+ if (rev.nil? || rev == '(unknown)') && File.exists?(scope('.git/HEAD'))
47
+ rev = File.read(scope('.git/HEAD')).strip
48
+ if rev =~ /^ref: (.*)$/
49
+ rev = File.read(scope(".git/#{$1}")).strip
50
+ end
51
+ end
52
+
53
+ if rev
54
+ @@version[:rev] = rev
55
+ unless rev[0] == ?(
56
+ @@version[:string] << "." << rev[0...7]
57
+ end
58
+ @@version[:string] << " (#{name})"
59
+ end
60
+
61
+ @@version
62
+ end
63
+ end
64
+ end
data/lib/txprails.rb ADDED
@@ -0,0 +1,44 @@
1
+ require 'txprails/txparse'
2
+ require 'txprails/version'
3
+
4
+ module TXPRails
5
+ extend TXPRails::Version
6
+
7
+ # A string representing the version of TXPRails.
8
+ # A more fine-grained representation is available from TXPRails.version.
9
+ VERSION = version[:string] unless defined?(TXPRails::VERSION)
10
+
11
+ # Initializes TXPRails for Rails.
12
+ #
13
+ # This method is called by `init.rb`,
14
+ # which is run by Rails on startup.
15
+ # We use it rather than putting stuff straight into `init.rb`
16
+ # so we can change the initialization behavior
17
+ # without modifying the file itself.
18
+ #
19
+ def self.init_rails
20
+ %w[txprails/template].each {|f| require f}
21
+ end
22
+ end
23
+
24
+ require 'txprails/util'
25
+
26
+ module TXP
27
+ include TXParse
28
+
29
+ def txp_doc(tag)
30
+ "<!DOCTYPE html>"
31
+ end
32
+
33
+ def txp_content(tag)
34
+ if content_for_layout = @view.instance_variable_get("@content_for_layout")
35
+ parse(content_for_layout)
36
+ end
37
+ end
38
+
39
+ def txp_include(tag)
40
+ @view.render :partial => tag.attr["name"]
41
+ end
42
+
43
+ # self.extend self
44
+ end
data/test/helper.rb ADDED
@@ -0,0 +1,10 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'shoulda'
4
+
5
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
6
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
7
+ require 'txprails'
8
+
9
+ class Test::Unit::TestCase
10
+ end
@@ -0,0 +1,7 @@
1
+ require 'helper'
2
+
3
+ class TestTxprails < Test::Unit::TestCase
4
+ should "probably rename this file and start testing for real" do
5
+ flunk "hey buddy, you should probably rename this file and start testing for real"
6
+ end
7
+ end