casey_jones 0.0.99

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ gem 'rails', '3.0.0.beta4'
2
+ gem 'sqlite3-ruby', :require => 'sqlite3'
3
+ gem 'jeweler'
4
+ gem "da_huangs_ruby_extensions"
5
+
data/README ADDED
@@ -0,0 +1,59 @@
1
+ == HABTM Example
2
+
3
+ Complex forms on a HABTM association.
4
+
5
+ Using code borrowed from Pat (http://patshaughnessy.net), whose view_mapper
6
+ finally taught this hobbyist hacker to write forms.
7
+
8
+ Hopefully this will fit snugly into someone else's gem
9
+
10
+ == Installation
11
+
12
+ * Install as a gem:
13
+ # Add to your Gemfile
14
+ gem "anaf_habtm"
15
+ * or as a plugin
16
+ rails plugin install git://github.com/tylergannon/anaf_habtm.git
17
+
18
+ Run the generator to place the javascript in the right place:
19
+
20
+ rails generate anaf_habtm
21
+
22
+ Add the following to your layout:
23
+ <%= javascript_include_tag 'nested_attributes.js' %>
24
+
25
+ == Usage
26
+
27
+ Inside your model, call anaf_habtm just as you would call has_and_belongs_to_many,
28
+ except now you need to offer a code block telling rails what to do with each object.
29
+ The plugin will handle deleting stuff.
30
+
31
+ # Basically, your code block needs to return an object of the correct
32
+ # type for your association collection, or else nil if your code
33
+ # determines that the object should be rejected.
34
+ class Customer < ActiveRecord::Base
35
+ anaf_habtm :orders, :autosave => true, :uniq => false do |params, order|
36
+ order = order ||= Order.new
37
+ order.attributes = params
38
+ logger.error params.inspect
39
+ order
40
+ end
41
+ end
42
+
43
+ class Order < ActiveRecord::Base
44
+ has_and_belongs_to_many :customers
45
+ anaf_habtm :items, :autosave => true, :uniq => false do |params, item|
46
+ logger.error "ITEM::: #{params.inspect}"
47
+ item ||= Item.find_or_create_by_name(params["name"])
48
+ end
49
+ end
50
+
51
+ == Additional info
52
+
53
+ See the example app at http://github.com/tylergannon/accepts-nested-attributes-habtm-example for more details.
54
+
55
+ Also check out Pat's view_mapper... it can generate the code you need inside your views.
56
+
57
+ http://github.com/patshaughnessy/view_mapper
58
+
59
+
data/Rakefile ADDED
@@ -0,0 +1,70 @@
1
+
2
+ PKG_FILES = FileList[
3
+ 'anaf_habtm.gemspec',
4
+ 'Gemfile',
5
+ 'install.rb',
6
+ 'Rakefile', 'README', 'uninstall.rb',
7
+ 'assets/**/*',
8
+ 'lib/**/*',
9
+ 'rails/**/*',
10
+ 'test/**/*'
11
+ ]
12
+
13
+ require 'rubygems'
14
+ require 'rake'
15
+
16
+ begin
17
+ require 'jeweler'
18
+ Jeweler::Tasks.new do |s|
19
+ s.name = "casey_jones"
20
+ s.author = "Tyler Gannon"
21
+ s.email = "t--g__a--nnon@gmail.com"
22
+ s.homepage = "http://github.com/tylergannon/anaf_habtm"
23
+ s.platform = Gem::Platform::RUBY
24
+ s.description = "some extra stuff for rails apps"
25
+ s.summary = "My favorite rails goodies all in one"
26
+ s.files = PKG_FILES.to_a
27
+ s.require_path = "lib"
28
+ s.has_rdoc = false
29
+ s.extra_rdoc_files = ["README"]
30
+ end
31
+
32
+ Jeweler::GemcutterTasks.new
33
+ rescue LoadError
34
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
35
+ end
36
+
37
+ require 'rake/testtask'
38
+ Rake::TestTask.new(:test) do |test|
39
+ test.libs << 'lib' << 'test'
40
+ test.pattern = 'test/**/test_*.rb'
41
+ test.verbose = true
42
+ end
43
+
44
+ begin
45
+ require 'rcov/rcovtask'
46
+ Rcov::RcovTask.new do |test|
47
+ test.libs << 'test'
48
+ test.pattern = 'test/**/test_*.rb'
49
+ test.verbose = true
50
+ end
51
+ rescue LoadError
52
+ task :rcov do
53
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
54
+ end
55
+ end
56
+
57
+ task :test => :check_dependencies
58
+
59
+ task :default => :test
60
+
61
+ require 'rake/rdoctask'
62
+ Rake::RDocTask.new do |rdoc|
63
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
64
+
65
+ rdoc.rdoc_dir = 'rdoc'
66
+ rdoc.title = "da_huangs_ruby_extensions #{version}"
67
+ rdoc.rdoc_files.include('README*')
68
+ rdoc.rdoc_files.include('lib/**/*.rb')
69
+ end
70
+
data/install.rb ADDED
@@ -0,0 +1 @@
1
+ # Install hook code here
@@ -0,0 +1,34 @@
1
+ module ActsAsLinkable
2
+ module ActiveRecordExtensions
3
+ def acts_as_linkable(opts={}, &block)
4
+ class_eval "def link_attr; #{opts.inspect}; end;"
5
+ end
6
+ end
7
+
8
+ module ActionViewExtensions
9
+ def link(obj)
10
+ raise "I can't link to nil." unless obj
11
+ if (obj.class == Array) || (obj.class == ActiveRecord::Relation)
12
+ obj.map{|v| link(v)}.to_sentence
13
+ else
14
+ p = obj.link_attr
15
+ p[:partial] = "#{obj.class.name.tableize}/link" if p.empty?
16
+ unless p[:partial].nil?
17
+ obj_name = (p[:object_name] ||= obj.class.name.underscore).to_s.to_sym
18
+ (render :partial => p[:partial], :locals => {obj_name => obj}).strip
19
+ else
20
+ opts = {}
21
+ link_attr = obj.link_attr
22
+ link_attr.each do |key, val|
23
+ link_attr[key] = obj.send(val) if val.class == Symbol
24
+ end
25
+ opts[:title] = link_attr[:title] if link_attr.has_key?(:title)
26
+ link_to link_attr[:name], obj, opts
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ ActiveRecord::Base.extend(ActsAsLinkable::ActiveRecordExtensions)
33
+ ActionView::Base.send :include, ActsAsLinkable::ActionViewExtensions
34
+
@@ -0,0 +1,2 @@
1
+ require 'ajax_loading/controller_resource'
2
+
@@ -0,0 +1,37 @@
1
+ module AjaxLoading
2
+ class ControllerResource < CanCan::ControllerResource
3
+ def initialize(controller, name, parent = nil, options = {})
4
+ super(controller, name, parent, options)
5
+ end
6
+
7
+ def load_resource
8
+ puts "AjaxLoading::load_resource"
9
+ params = @controller.params
10
+ if params.has_key?(:associated)
11
+ ass_params = params[:associated]
12
+ relation = ass_params["class_name"].constantize.find(ass_params["id"])
13
+ association = ass_params["association"]
14
+ instance_variable_set 'container',
15
+ ass_params["container"] ||= relation.element_id(:show, association)
16
+
17
+ self.model_instance = relation.send(association)
18
+ elsif collection_action?
19
+ self.model_instance = model_class.where('1=1')
20
+ else
21
+ super
22
+ end
23
+ end
24
+
25
+ private
26
+
27
+ def instance_variable_set(name, value)
28
+ name = '@'+name unless name.include?('@')
29
+ @controller.instance_variable_set(name, value)
30
+ end
31
+ def instance_variable_get(name)
32
+ name = '@'+name unless name.include?('@')
33
+ @controller.instance_variable_get(name)
34
+ end
35
+ end
36
+ end
37
+
@@ -0,0 +1,45 @@
1
+
2
+ module AnafHabtm
3
+ module ActiveRecord
4
+ def anaf_habtm(association, options={}, &block)
5
+ class_eval do
6
+ # Define a proc that will look up the (potentially) existing object
7
+ finder = proc {|id| association.to_s.singularize.camelize.constantize.where(:id=>id).first
8
+ }
9
+
10
+ # Define a proc that will set the association collection
11
+ set_collection = proc {|me, coll| me.send("#{association.to_s.tableize}=", coll)}
12
+ has_and_belongs_to_many association.to_sym, options
13
+ # Define the actual association setter.
14
+ define_method "#{association.to_s.tableize}_attributes=", lambda{|attributes_for_association|
15
+ coll = []
16
+
17
+ attributes_for_association.each_value do |params|
18
+ next if params["_destroy"] == "1"
19
+ obj = finder.call(params["id"]) if params.has_key?("id")
20
+ params.extend(AnafHabtm::HashExtension)
21
+ # ActiveRecord::Base.attributes=() doesn't like extra parameters.
22
+ coll << block.call(params.copy_without_destroy, obj)
23
+ end
24
+ set_collection.call(self, coll)
25
+ }
26
+ end
27
+ end
28
+
29
+ def named_association(member, attribute, opts={})
30
+ member = member.to_s
31
+ klass = opts.has_key?(:class) ? opts[:class_name] : member.to_s.singularize.camelize
32
+ attribute = attribute.to_s
33
+ if opts.has_key?(:create)
34
+ class_eval "def #{member}_#{attribute}=(#{attribute});
35
+ return if #{attribute}.blank?
36
+ self.#{member} = #{klass}.find_or_create_by_#{attribute}(#{attribute})
37
+ end;"
38
+ else
39
+ class_eval "def #{member}_#{attribute}=(#{attribute}); self.#{member} = #{klass}.find_by_#{attribute}(#{attribute}) unless #{attribute}.blank?; end;"
40
+ end
41
+ class_eval "def #{member}_#{attribute}; #{member}.#{attribute} if #{member}; end;"
42
+ end
43
+ end
44
+ end
45
+
@@ -0,0 +1,8 @@
1
+ require 'casey_jones/active_record_extensions'
2
+ require 'casey_jones/application_helper_methods'
3
+ require 'casey_jones/string_reader'
4
+ require 'ajax_loading/ajax_loading'
5
+ require 'acts_as_linkable/acts_as_linkable'
6
+ ActiveRecord::Base.extend(CaseyJones::ActiveRecord)
7
+ ActionView::Base.send :include, CaseyJones::ApplicationHelperMethods
8
+
@@ -0,0 +1,160 @@
1
+
2
+ module CaseyJones
3
+ module ActiveRecord
4
+ def autocomplete_format(&block)
5
+ class_eval do
6
+ @autocomplete_block = block
7
+ def self.to_autocomplete(items)
8
+ items.map{|t| @autocomplete_block.call(t)}.to_json
9
+ end
10
+ end
11
+ end
12
+
13
+ # Needs to call scopes on a class and pass it values that are
14
+ # pulled from a hash called obj_attr
15
+ def make_scope_string(find_opts)
16
+ _scopes = []
17
+ find_opts.each{ |scope, attr_name|
18
+ if attr_name.class == Hash
19
+ _scopes << "#{scope.to_s}(obj_attr[#{name.first[0].to_s}][#{name.first[1].to_s}])"
20
+ else
21
+ _scopes << "#{scope.to_s}(obj_attr[#{name.to_s}])"
22
+ end
23
+ }
24
+ _scopes.join(".")
25
+ end
26
+
27
+ def anaf_habtm(association, options={})
28
+ ar_opts = options[:ar_options] ||= {}
29
+ klass = ar_opts[:class_name] ||= association.to_s.singularize.camelize
30
+ class_eval do
31
+ has_and_belongs_to_many association.to_sym, ar_opts
32
+ end
33
+ find_line = "obj = obj ||= #{klass}.#{make_scope_string(options[:find])}.first" if options.has_key?(:find)
34
+ association = association.to_s.underscore.tableize
35
+ scope_string =
36
+ class_eval <<END
37
+ def #{association}_attributes=(attr_hash)
38
+ obj_coll = []
39
+ attr_hash.each_value do |obj_attr|
40
+ next if obj_attr["_destroy"] == "1"
41
+ obj = #{klass}.find(obj_attr["id"]) if obj_attr.has_key?("id")
42
+ obj_attr = obj_attr.reject_keys ["id", "_destroy"]
43
+ #{find_line}
44
+ if obj && obj.update_attributes(obj_attr)
45
+ obj_coll << obj
46
+ elsif (obj = #{klass}.new(obj_attributes)) && obj.save
47
+ obj_coll << obj
48
+ end
49
+ end
50
+ self.#{association} = obj_coll
51
+ end
52
+ END
53
+ end
54
+
55
+ def association_text(association, opts={})
56
+ raise "Must give a name for text_association" unless opts.has_key?(:name)
57
+ class_eval do
58
+ if opts.has_key?(:class_name)
59
+ klass = opts[:class_name].constantize
60
+ else
61
+ klass = association.to_s.singularize.camelize.constantize
62
+ end
63
+ define_method "#{association.to_s}_text=", lambda{ |text|
64
+ return if text.empty?
65
+ coll = StringReader.new.read_items(text) do |name, commentary|
66
+ a = klass.undecorate(name) if klass.methods.include?("undecorate")
67
+ if opts.has_key?(:scope)
68
+ obj = self.send(association).scopes[opts[:scope]].call(name).first
69
+ end
70
+ params = {opts[:name]=>name}
71
+ params[opts[:commentary]] = commentary if opts.has_key?(:commentary)
72
+ obj = obj ||= klass.new
73
+ obj = klass.find(obj) unless obj.new_record?
74
+ obj.decoration = a if a
75
+ obj.attributes = params
76
+ obj.save
77
+ obj
78
+ end
79
+ self.send("#{association.to_s}=", coll)
80
+ }
81
+
82
+ define_method "#{association.to_s}_text", lambda{
83
+ StringReader.new.write_items(self.send(association.to_s)) do |item|
84
+ name = item.send(opts[:name])
85
+ name = item.decorate(name) if item.methods.include?("decorate")
86
+ [name, opts.has_key?(:commentary) ? item.send(opts[:commentary]) : ""]
87
+ end
88
+ }
89
+ end
90
+ end
91
+
92
+ def named_association(member, attribute, opts={})
93
+ member = member.to_s
94
+ klass = (opts.has_key?(:class_name) ? opts[:class_name] : member.to_s.singularize.camelize).constantize
95
+ attribute = attribute.to_s
96
+ if opts.has_key?(:create)
97
+ class_eval do
98
+ define_method "#{member}_#{attribute}=", lambda{|value|
99
+ return if value.blank?
100
+ obj = klass.named(value)
101
+ obj = obj ||= klass.create(attribute => value)
102
+ self.send("#{member}=", obj)
103
+ }
104
+ end
105
+ else
106
+ class_eval do
107
+ define_method "#{member}_#{attribute}=", lambda{|value|
108
+ self.send("#{member}=",klass.named(value)) unless value.blank?
109
+ }
110
+ end
111
+ end
112
+ class_eval "def #{member}_#{attribute};
113
+ #{member}.#{attribute} if #{member};
114
+ end;"
115
+ end
116
+
117
+ def search_on(*cols)
118
+ class_eval "def self.search_columns; #{cols.map{|t| t.to_s}.to_ary.inspect}; end;"
119
+ class_eval do
120
+ scope :search, lambda{|str|
121
+ items = like_condition(str.downcase)
122
+ if scopes.has_key?(:search_mod)
123
+ items = items.search_mod
124
+ end
125
+ items
126
+ }
127
+ scope :with_name, lambda{|str|
128
+ equals_condition(str.downcase).limit(1)
129
+ }
130
+ end
131
+ end
132
+
133
+ def lookup(params)
134
+ str = params[:id]
135
+ if str.match(/\D/)
136
+ named(str)
137
+ else
138
+ find(str)
139
+ end
140
+ end
141
+
142
+ def like_condition(str)
143
+ where(condition("ilike '%#{str}%'"))
144
+ end
145
+
146
+ def equals_condition(str)
147
+ where(condition("= '#{str.downcase}'"))
148
+ end
149
+
150
+
151
+ def named(str)
152
+ with_name(str).first
153
+ end
154
+
155
+ def condition(cond)
156
+ search_columns.map{|c| "trim(lower(#{c})) #{cond}"}.join(" or ")
157
+ end
158
+ end
159
+ end
160
+
@@ -0,0 +1,39 @@
1
+ module CaseyJones
2
+ module ApplicationHelperMethods
3
+ def remove_child_link(name, form_builder)
4
+ value = form_builder.object.new_record? ? "1" : "false"
5
+ klass = form_builder.object.class.name.underscore
6
+ form_builder.hidden_field(:_destroy, {:value=>value, "data-remove"=>klass}) +
7
+ link_to(name, options={}, html_options={"href"=>"#", "class"=>"remove-child-link", :tabindex=> "0"})
8
+ end
9
+
10
+ def add_child_link(name, child, form_builder, options={})
11
+ # puts "||#{form_builder}||"
12
+ new_form = new_child_fields(child, form_builder, options)
13
+ raw(content_tag(:div, new_form, {:id=>"#{child}_template", :class=>"form-template"}, escape=false))+
14
+ link_to(name, options={}, html_options={"href"=>"#", "class"=>"add-child-link", "data-class-name"=>child})
15
+ end
16
+
17
+ def new_child_fields(child, form_builder, options={})
18
+ partial = options[:partial] ||= child.underscore
19
+ output = ""
20
+ form_builder.fields_for(child.pluralize.to_sym, child.camelize.constantize.new, :child_index => "__#{child}_id__") do |f|
21
+ output += render(:partial => partial, :locals => { :f => f })
22
+ end
23
+ output
24
+ end
25
+
26
+ def tfwac(f, field, controller, opts={})
27
+ opts["data-auto-complete"]='tf'
28
+ opts["data-auto-complete-url"]=eval("#{controller.to_s.underscore.tableize}_path(:format=>:json)")
29
+ f.text_field field, opts
30
+ end
31
+
32
+ def text_area_with_auto_complete(f, field, controller, opts={})
33
+ opts["data-auto-complete"]='ta'
34
+ opts["data-auto-complete-url"]=eval("#{controller.to_s.underscore.tableize}_path(:format=>:json)")
35
+ f.text_area field, opts
36
+ end
37
+ end
38
+ end
39
+
@@ -0,0 +1,113 @@
1
+ module AnafHabtm
2
+ class StringReader
3
+ KEY_SYMPTOM = "*"
4
+ POSS_SYMPTOM = "-"
5
+ START_COMMENT = "{"
6
+ ONE_LINE_COMMENT = "/"
7
+ END_COMMENT = "}"
8
+ NEWLINE = "\n"
9
+
10
+ DELIM = [START_COMMENT, NEWLINE, ONE_LINE_COMMENT, END_COMMENT]
11
+
12
+ MULTI_LINE = :multi_line
13
+ ONE_LINE = :one_line
14
+ NAME = :name
15
+ COMMENT = [MULTI_LINE, ONE_LINE]
16
+
17
+ @item = ""
18
+ @comment = nil
19
+ @items = []
20
+
21
+ def save(block)
22
+ unless @item.strip.empty?
23
+ @items << block.call(@item.strip, @comment.nil? ? nil : @comment.strip)
24
+ end
25
+ @item = ""
26
+ @comment = nil
27
+ end
28
+
29
+ def write_items(coll, &block)
30
+ lines = []
31
+ coll.each do |obj|
32
+ item, comment = block.call(obj)
33
+ if comment.nil? || comment.empty?
34
+ lines << item
35
+ elsif comment.index("/") || comment.index("\n")
36
+ lines << "#{item} {#{comment}}"
37
+ else
38
+ lines << "#{item} / #{comment}"
39
+ end
40
+ end
41
+ lines.join("\n")
42
+ end
43
+
44
+ def read_items(str, &block)
45
+ @items = []
46
+ buffer = ""
47
+ @item = ""
48
+ @comment = nil
49
+ state = NAME
50
+
51
+ str.chars.each do |char|
52
+ if (char == "/") && (state != MULTI_LINE)
53
+ @item = buffer.strip
54
+ buffer = ""
55
+ state = ONE_LINE
56
+ elsif char == "{"
57
+ @item = buffer.strip
58
+ buffer = ""
59
+ state = MULTI_LINE
60
+ elsif char == "}"
61
+ @comment = buffer.strip unless buffer.strip.empty?
62
+ buffer = ""
63
+ save(block)
64
+ state = NAME
65
+ elsif char == "\n"
66
+ if state == NAME
67
+ @item = buffer.strip
68
+ buffer = ""
69
+ save(block)
70
+ elsif state == ONE_LINE
71
+ @comment = buffer.strip
72
+ state = NAME
73
+ buffer = ""
74
+ save(block)
75
+ else
76
+ buffer << char
77
+ end
78
+ else
79
+ buffer << char
80
+ end
81
+ end
82
+
83
+ if state == ONE_LINE
84
+ @comment = buffer
85
+ elsif state == MULTI_LINE
86
+ @comment = buffer
87
+ else
88
+ @item = buffer
89
+ end
90
+ save(block)
91
+ @items
92
+ end
93
+
94
+ def self.parse_symptom(obj, symptom)
95
+ if symptom.index(KEY_SYMPTOM) == 0
96
+ obj.key_symptom = true
97
+ obj.symptom_name = symptom[KEY_SYMPTOM.length..symptom.length]
98
+ elsif symptom.index(POSS_SYMPTOM) == 0
99
+ obj.maybe = true
100
+ obj.symptom_name = symptom[POSS_SYMPTOM.length..symptom.length]
101
+ else
102
+ obj.symptom_name = symptom
103
+ end
104
+ end
105
+
106
+ def self.decorate_symptom(obj)
107
+ decorator = ""
108
+ decorator = KEY_SYMPTOM if obj.key_symptom
109
+ decorator = POSS_SYMPTOM if obj.maybe
110
+ "#{decorator}#{obj.symptom_name}"
111
+ end
112
+ end
113
+ end
@@ -0,0 +1,11 @@
1
+ require 'rails/generators'
2
+
3
+ class AnafHabtmGenerator < Rails::Generators::Base
4
+ self.source_root File.expand_path("assets", File.dirname(__FILE__))
5
+
6
+ def copy_initializer_file
7
+ copy_file "nested_attributes.js", "public/javascripts/nested_attributes.js"
8
+ copy_file "nested_attributes.css", "public/stylesheets/nested_attributes.css"
9
+ end
10
+ end
11
+
@@ -0,0 +1,3 @@
1
+
2
+ .form-template {
3
+ display: none; }
@@ -0,0 +1,73 @@
1
+
2
+ function setUpDocument($jq) {
3
+ $jq.find("input[data-auto-complete|=tf]").each( function(idx, el){
4
+ $(el).autocomplete({
5
+ source: $(el).attr('data-auto-complete-url'),
6
+ minLength: 2
7
+ });
8
+ });
9
+
10
+ $jq.find("textarea[data-auto-complete|=ta]").each( function(idx, el){
11
+ setTextAreaAutoComplete($(el));
12
+ });
13
+
14
+ $jq.find("a.add-child-link").click( function() {
15
+ klass = $(this).attr('data-class-name');
16
+ $el = $(this).prev().children().first().clone();
17
+ new_id=new Date().getTime()
18
+ $el.html($el.html().replace(new RegExp('__'+klass+'_id__', 'g'), new_id));
19
+ $el.find('input[data-remove|='+klass+']').attr('value', 'false');
20
+ $(this).closest('.child').find('.'+klass+'_children').first()
21
+ .append($el).show();
22
+ setUpDocument($el);
23
+ return false;
24
+ });
25
+
26
+ $jq.find('a.remove-child-link').click( function() {
27
+ $(this).prev('input[type|=hidden]').val('1');
28
+ $(this).closest('.child').hide();
29
+ return false;
30
+ });
31
+ }
32
+
33
+ $(function () {
34
+ setUpDocument($("body"));
35
+
36
+ });
37
+ var text_area_delimiter = '\n';
38
+ function split(val) {
39
+ return val.split(new RegExp(text_area_delimiter+'\s*'));
40
+ }
41
+ function extractLast(term) {
42
+ return split(term).pop();
43
+ }
44
+ function setTextAreaAutoComplete($el) {
45
+ $el.autocomplete({
46
+ source: function(request, response) {
47
+ $.getJSON($el.attr('data-auto-complete-url'), {
48
+ term: extractLast(request.term)
49
+ }, response);
50
+ },
51
+ search: function() {
52
+ // custom minLength
53
+ var term = extractLast(this.value);
54
+ if (term.length < 2) {
55
+ return false;
56
+ }
57
+ },
58
+ focus: function() {
59
+ // prevent value inserted on focus
60
+ return false;
61
+ },
62
+ select: function(event, ui) {
63
+ var terms = split( this.value );
64
+ terms.pop(); // remove the current input
65
+ terms.push( ui.item.value ); // add the selected item
66
+ // add placeholder to get the comma-and-space at the end
67
+ // terms.push("");
68
+ this.value = terms.join(text_area_delimiter);
69
+ return false;
70
+ }
71
+ });
72
+ }
73
+
@@ -0,0 +1,8 @@
1
+ require 'test_helper'
2
+
3
+ class AnafHabtmTest < ActiveSupport::TestCase
4
+ # Replace this with your real tests.
5
+ test "the truth" do
6
+ assert true
7
+ end
8
+ end
@@ -0,0 +1,3 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'active_support'
data/uninstall.rb ADDED
@@ -0,0 +1 @@
1
+ # Uninstall hook code here
metadata ADDED
@@ -0,0 +1,85 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: casey_jones
3
+ version: !ruby/object:Gem::Version
4
+ hash: 217
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 99
10
+ version: 0.0.99
11
+ platform: ruby
12
+ authors:
13
+ - Tyler Gannon
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-07-21 00:00:00 -07:00
19
+ default_executable:
20
+ dependencies: []
21
+
22
+ description: some extra stuff for rails apps
23
+ email: t--g__a--nnon@gmail.com
24
+ executables: []
25
+
26
+ extensions: []
27
+
28
+ extra_rdoc_files:
29
+ - README
30
+ files:
31
+ - Gemfile
32
+ - README
33
+ - Rakefile
34
+ - install.rb
35
+ - lib/acts_as_linkable/acts_as_linkable.rb
36
+ - lib/ajax_loading/ajax_loading.rb
37
+ - lib/ajax_loading/controller_resource.rb
38
+ - lib/anaf_active_record.rb
39
+ - lib/casey_jones.rb
40
+ - lib/casey_jones/active_record_extensions.rb
41
+ - lib/casey_jones/application_helper_methods.rb
42
+ - lib/casey_jones/string_reader.rb
43
+ - lib/generators/anaf_habtm/anaf_habtm_generator.rb
44
+ - lib/generators/anaf_habtm/assets/nested_attributes.css
45
+ - lib/generators/anaf_habtm/assets/nested_attributes.js
46
+ - test/anaf_habtm_test.rb
47
+ - test/test_helper.rb
48
+ - uninstall.rb
49
+ has_rdoc: true
50
+ homepage: http://github.com/tylergannon/anaf_habtm
51
+ licenses: []
52
+
53
+ post_install_message:
54
+ rdoc_options:
55
+ - --charset=UTF-8
56
+ require_paths:
57
+ - lib
58
+ required_ruby_version: !ruby/object:Gem::Requirement
59
+ none: false
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ hash: 3
64
+ segments:
65
+ - 0
66
+ version: "0"
67
+ required_rubygems_version: !ruby/object:Gem::Requirement
68
+ none: false
69
+ requirements:
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ hash: 3
73
+ segments:
74
+ - 0
75
+ version: "0"
76
+ requirements: []
77
+
78
+ rubyforge_project:
79
+ rubygems_version: 1.3.7
80
+ signing_key:
81
+ specification_version: 3
82
+ summary: My favorite rails goodies all in one
83
+ test_files:
84
+ - test/anaf_habtm_test.rb
85
+ - test/test_helper.rb