diff --git a/tracks/vendor/plugins/resource_feeder/README b/tracks/vendor/plugins/resource_feeder/README new file mode 100644 index 00000000..5502be25 --- /dev/null +++ b/tracks/vendor/plugins/resource_feeder/README @@ -0,0 +1,7 @@ +ResourceFeeder +============== + +Simple feeds for resources + +NOTE: This plugin depends on the latest version of simply_helpful, available here: +http://dev.rubyonrails.org/svn/rails/plugins/simply_helpful/ diff --git a/tracks/vendor/plugins/resource_feeder/Rakefile b/tracks/vendor/plugins/resource_feeder/Rakefile new file mode 100644 index 00000000..51fce7b3 --- /dev/null +++ b/tracks/vendor/plugins/resource_feeder/Rakefile @@ -0,0 +1,22 @@ +require 'rake' +require 'rake/testtask' +require 'rake/rdoctask' + +desc 'Default: run unit tests.' +task :default => :test + +desc 'Test the resource_feed plugin.' +Rake::TestTask.new(:test) do |t| + t.libs << 'lib' + t.pattern = 'test/**/*_test.rb' + t.verbose = true +end + +desc 'Generate documentation for the resource_feed plugin.' +Rake::RDocTask.new(:rdoc) do |rdoc| + rdoc.rdoc_dir = 'rdoc' + rdoc.title = 'ResourceFeed' + rdoc.options << '--line-numbers' << '--inline-source' + rdoc.rdoc_files.include('README') + rdoc.rdoc_files.include('lib/**/*.rb') +end diff --git a/tracks/vendor/plugins/resource_feeder/init.rb b/tracks/vendor/plugins/resource_feeder/init.rb new file mode 100644 index 00000000..7b55d76f --- /dev/null +++ b/tracks/vendor/plugins/resource_feeder/init.rb @@ -0,0 +1,2 @@ +require 'resource_feeder' +ActionController::Base.send(:include, ResourceFeeder::Rss, ResourceFeeder::Atom) \ No newline at end of file diff --git a/tracks/vendor/plugins/resource_feeder/lib/resource_feeder.rb b/tracks/vendor/plugins/resource_feeder/lib/resource_feeder.rb new file mode 100644 index 00000000..b5003419 --- /dev/null +++ b/tracks/vendor/plugins/resource_feeder/lib/resource_feeder.rb @@ -0,0 +1,2 @@ +require 'resource_feeder/rss' +require 'resource_feeder/atom' diff --git a/tracks/vendor/plugins/resource_feeder/lib/resource_feeder/atom.rb b/tracks/vendor/plugins/resource_feeder/lib/resource_feeder/atom.rb new file mode 100644 index 00000000..315f1d3a --- /dev/null +++ b/tracks/vendor/plugins/resource_feeder/lib/resource_feeder/atom.rb @@ -0,0 +1,66 @@ +require 'resource_feeder/common' + +module ResourceFeeder + module Atom + include ResourceFeeder::Common + extend self + + def render_atom_feed_for(resources, options = {}) + render :text => atom_feed_for(resources, options), :content_type => Mime::ATOM + end + + def atom_feed_for(resources, options = {}) + xml = Builder::XmlMarkup.new(:indent => 2) + + options[:feed] ||= {} + options[:item] ||= {} + options[:url_writer] ||= self + + if options[:class] || resources.first + klass = options[:class] || resources.first.class + new_record = klass.new + else + options[:feed] = { :title => "Empty", :link => "http://example.com" } + end + + options[:feed][:title] ||= klass.name.pluralize + options[:feed][:id] ||= "tag:#{request.host_with_port}:#{klass.name.pluralize}" + options[:feed][:link] ||= SimplyHelpful::PolymorphicRoutes.polymorphic_url(new_record, options[:url_writer]) + + options[:item][:title] ||= [ :title, :subject, :headline, :name ] + options[:item][:description] ||= [ :description, :body, :content ] + options[:item][:pub_date] ||= [ :updated_at, :updated_on, :created_at, :created_on ] + options[:item][:author] ||= [ :author, :creator ] + + resource_link = lambda { |r| SimplyHelpful::PolymorphicRoutes.polymorphic_url(r, options[:url_writer]) } + + xml.instruct! + xml.feed "xml:lang" => "en-US", "xmlns" => 'http://www.w3.org/2005/Atom' do + xml.title(options[:feed][:title]) + xml.id(options[:feed][:id]) + xml.link(:rel => 'alternate', :type => 'text/html', :href => options[:feed][:link]) + xml.link(:rel => 'self', :type => 'application/atom+xml', :href => options[:feed][:self]) if options[:feed][:self] + xml.subtitle(options[:feed][:description]) if options[:feed][:description] + + for resource in resources + published_at = call_or_read(options[:item][:pub_date], resource) + + xml.entry do + xml.title(call_or_read(options[:item][:title], resource)) + xml.content(call_or_read(options[:item][:description], resource), :type => 'html') + xml.id("tag:#{request.host_with_port},#{published_at.xmlschema}:#{call_or_read(options[:item][:guid] || options[:item][:link] || resource_link, resource)}") + xml.published(published_at.xmlschema) + xml.updated((resource.respond_to?(:updated_at) ? call_or_read(options[:item][:pub_date] || :updated_at, resource) : published_at).xmlschema) + xml.link(:rel => 'alternate', :type => 'text/html', :href => call_or_read(options[:item][:link] || options[:item][:guid] || resource_link, resource)) + + if author = call_or_read(options[:item][:author], resource) + xml.author do + xml.name() + end + end + end + end + end + end + end +end diff --git a/tracks/vendor/plugins/resource_feeder/lib/resource_feeder/common.rb b/tracks/vendor/plugins/resource_feeder/lib/resource_feeder/common.rb new file mode 100644 index 00000000..383b965e --- /dev/null +++ b/tracks/vendor/plugins/resource_feeder/lib/resource_feeder/common.rb @@ -0,0 +1,24 @@ +module ResourceFeeder + module Common + private + def call_or_read(procedure_or_attributes, resource) + case procedure_or_attributes + when nil + raise ArgumentError, "WTF is nil here? #{resource.inspect}" + when Array + attributes = procedure_or_attributes + if attr = attributes.select { |a| resource.respond_to?(a) }.first + resource.send attr + end + when Symbol + attribute = procedure_or_attributes + resource.send(attribute) + when Proc + procedure = procedure_or_attributes + procedure.call(resource) + else + raise ArgumentError, "WTF is #{procedure_or_attributes.inspect} here? #{resource.inspect}" + end + end + end +end diff --git a/tracks/vendor/plugins/resource_feeder/lib/resource_feeder/rss.rb b/tracks/vendor/plugins/resource_feeder/lib/resource_feeder/rss.rb new file mode 100644 index 00000000..1053f427 --- /dev/null +++ b/tracks/vendor/plugins/resource_feeder/lib/resource_feeder/rss.rb @@ -0,0 +1,67 @@ +require 'resource_feeder/common' + +module ResourceFeeder + module Rss + include ResourceFeeder::Common + extend self + + def render_rss_feed_for(resources, options = {}) + render :text => rss_feed_for(resources, options), :content_type => Mime::RSS + end + + def rss_feed_for(resources, options = {}) + xml = Builder::XmlMarkup.new(:indent => 2) + + options[:feed] ||= {} + options[:item] ||= {} + options[:url_writer] ||= self + + if options[:class] || resources.first + klass = options[:class] || resources.first.class + new_record = klass.new + else + options[:feed] = { :title => "Empty", :link => "http://example.com" } + end + use_content_encoded = options[:item].has_key?(:content_encoded) + + options[:feed][:title] ||= klass.name.pluralize + options[:feed][:link] ||= SimplyHelpful::PolymorphicRoutes.polymorphic_url(new_record, options[:url_writer]) + options[:feed][:language] ||= "en-us" + options[:feed][:ttl] ||= "40" + + options[:item][:title] ||= [ :title, :subject, :headline, :name ] + options[:item][:description] ||= [ :description, :body, :content ] + options[:item][:pub_date] ||= [ :updated_at, :updated_on, :created_at, :created_on ] + + resource_link = lambda { |r| SimplyHelpful::PolymorphicRoutes.polymorphic_url(r, options[:url_writer]) } + + rss_root_attributes = { :version => 2.0 } + rss_root_attributes.merge!("xmlns:content" => "http://purl.org/rss/1.0/modules/content/") if use_content_encoded + + xml.instruct! + + xml.rss(rss_root_attributes) do + xml.channel do + xml.title(options[:feed][:title]) + xml.link(options[:feed][:link]) + xml.description(options[:feed][:description]) if options[:feed][:description] + xml.language(options[:feed][:language]) + xml.ttl(options[:feed][:ttl]) + + for resource in resources + xml.item do + xml.title(call_or_read(options[:item][:title], resource)) + xml.description(call_or_read(options[:item][:description], resource)) + if use_content_encoded then + xml.content(:encoded) { xml.cdata!(call_or_read(options[:item][:content_encoded], resource)) } + end + xml.pubDate(call_or_read(options[:item][:pub_date], resource).to_s(:rfc822)) + xml.guid(call_or_read(options[:item][:guid] || options[:item][:link] || resource_link, resource)) + xml.link(call_or_read(options[:item][:link] || options[:item][:guid] || resource_link, resource)) + end + end + end + end + end + end +end diff --git a/tracks/vendor/plugins/resource_feeder/test/atom_feed_test.rb b/tracks/vendor/plugins/resource_feeder/test/atom_feed_test.rb new file mode 100644 index 00000000..3112da47 --- /dev/null +++ b/tracks/vendor/plugins/resource_feeder/test/atom_feed_test.rb @@ -0,0 +1,85 @@ +require File.dirname(__FILE__) + '/test_helper' +class AtomFeedTest < Test::Unit::TestCase + attr_reader :request + + def setup + @request = OpenStruct.new + @request.host_with_port = 'example.com' + @records = Array.new(5).fill(Post.new) + @records.each &:save + end + + def test_default_atom_feed + atom_feed_for @records + + assert_select 'feed' do + assert_select '>title', 'Posts' + assert_select '>id', "tag:#{request.host_with_port}:Posts" + assert_select '>link' do + assert_select "[rel='alternate']" + assert_select "[type='text/html']" + assert_select "[href='http://example.com/posts']" + end + assert_select 'entry', 5 do + assert_select 'title', :text => 'feed title (title)' + assert_select "content[type='html']", '<p>feed description (description)</p>' + assert_select 'id', "tag:#{request.host_with_port},#{@records.first.created_at.xmlschema}:#{'http://example.com/posts/1'}" + assert_select 'published', @records.first.created_at.xmlschema + assert_select 'updated', @records.first.created_at.xmlschema + assert_select 'link' do + assert_select "[rel='alternate']" + assert_select "[type='text/html']" + assert_select "[href='http://example.com/posts/1']" + end + end + end + end + + def test_should_allow_custom_feed_options + atom_feed_for @records, :feed => { :title => 'Custom Posts', :link => '/posts', :description => 'stuff', :self => '/posts.atom' } + + assert_select 'feed>title', 'Custom Posts' + assert_select "feed>link[href='/posts']" + assert_select 'feed>subtitle', 'stuff' + assert_select 'feed>link' do + assert_select "[rel='self']" + assert_select "[type='application/atom+xml']" + assert_select "[href='/posts.atom']" + end + end + + def test_should_allow_custom_item_attributes + atom_feed_for @records, :item => { :title => :name, :description => :body, :pub_date => :create_date, :link => :id } + + assert_select 'entry', 5 do + assert_select 'title', :text => 'feed title (name)' + assert_select "content[type='html']", '<p>feed description (body)</p>' + assert_select 'published', (@records.first.created_at - 5.minutes).xmlschema + assert_select 'updated', (@records.first.created_at - 5.minutes).xmlschema + assert_select 'id', "tag:#{request.host_with_port},#{(@records.first.created_at - 5.minutes).xmlschema}:1" + assert_select 'link' do + assert_select "[rel='alternate']" + assert_select "[type='text/html']" + assert_select "[href='1']" + end + end + end + + def test_should_allow_custom_item_attribute_blocks + atom_feed_for @records, :item => { :title => lambda { |r| r.name }, :description => lambda { |r| r.body }, :pub_date => lambda { |r| r.create_date }, + :link => lambda { |r| "/#{r.created_at.to_i}" }, :guid => lambda { |r| r.created_at.to_i } } + + assert_select 'entry', 5 do + assert_select 'title', :text => 'feed title (name)' + assert_select "content[type='html']", '<p>feed description (body)</p>' + assert_select 'published', (@records.first.created_at - 5.minutes).xmlschema + assert_select 'updated', (@records.first.created_at - 5.minutes).xmlschema + assert_select 'id', /:\d+$/ + assert_select 'link' do + assert_select "[rel='alternate']" + assert_select "[type='text/html']" + assert_select "[href=?]", /^\/\d+$/ + end + end + end +end diff --git a/tracks/vendor/plugins/resource_feeder/test/rss_feed_test.rb b/tracks/vendor/plugins/resource_feeder/test/rss_feed_test.rb new file mode 100644 index 00000000..90525baf --- /dev/null +++ b/tracks/vendor/plugins/resource_feeder/test/rss_feed_test.rb @@ -0,0 +1,86 @@ +require File.dirname(__FILE__) + '/test_helper' +class RssFeedTest < Test::Unit::TestCase + def setup + @records = Array.new(5).fill(Post.new) + @records.each &:save + end + + def test_default_rss_feed + rss_feed_for @records + + assert_select 'rss[version="2.0"]' do + assert_select 'channel' do + assert_select '>title', 'Posts' + assert_select '>link', 'http://example.com/posts' + assert_select 'language', 'en-us' + assert_select 'ttl', '40' + end + assert_select 'item', 5 do + assert_select 'title', :text => 'feed title (title)' + assert_select 'description', '<p>feed description (description)</p>' + %w(guid link).each do |node| + assert_select node, 'http://example.com/posts/1' + end + assert_select 'pubDate', @records.first.created_at.to_s(:rfc822) + end + end + end + + def test_should_allow_custom_feed_options + rss_feed_for @records, :feed => { :title => 'Custom Posts', :link => '/posts', :description => 'stuff', :language => 'en-gb', :ttl => '80' } + + assert_select 'channel>title', 'Custom Posts' + assert_select 'channel>link', '/posts' + assert_select 'channel>description', 'stuff' + assert_select 'channel>language', 'en-gb' + assert_select 'channel>ttl', '80' + end + + def test_should_allow_custom_item_attributes + rss_feed_for @records, :item => { :title => :name, :description => :body, :pub_date => :create_date, :link => :id } + + assert_select 'item', 5 do + assert_select 'title', :text => 'feed title (name)' + assert_select 'description', '<p>feed description (body)</p>' + assert_select 'pubDate', (@records.first.created_at - 5.minutes).to_s(:rfc822) + assert_select 'link', '1' + assert_select 'guid', '1' + end + end + + def test_should_allow_custom_item_attribute_blocks + rss_feed_for @records, :item => { :title => lambda { |r| r.name }, :description => lambda { |r| r.body }, :pub_date => lambda { |r| r.create_date }, + :link => lambda { |r| "/#{r.created_at.to_i}" }, :guid => lambda { |r| r.created_at.to_i } } + + assert_select 'item', 5 do + assert_select 'title', :text => 'feed title (name)' + assert_select 'description', '<p>feed description (body)</p>' + assert_select 'pubDate', (@records.first.created_at - 5.minutes).to_s(:rfc822) + end + end + + # note that assert_select isnt easily able to get elements that have xml namespaces (as it thinks they are + # invalid html psuedo children), so we do some manual testing with the response body + def test_should_allow_content_encoded_for_items + rss_feed_for @records, :item => { :content_encoded => :full_html_body } + + html_content = "Here is some full content, with out any excerpts" + assert_equal 5, @response.body.scan("").size + assert_select 'item', 5 do + assert_select 'description + *', " { :content_encoded => :full_html_body } + assert_equal %[\n], + @response.body.grep(/\n], + @response.body.grep(/feed description (#{attr_name})

" + end + end + + def full_html_body + "Here is some full content, with out any excerpts" + end + + def create_date + @created_at - 5.minutes + end +end + +class Test::Unit::TestCase + include ResourceFeeder::Rss, ResourceFeeder::Atom + + def render_feed(xml) + @response = OpenStruct.new + @response.headers = {'Content-Type' => 'text/xml'} + @response.body = xml + end + + def rss_feed_for_with_ostruct(resources, options = {}) + render_feed rss_feed_for_without_ostruct(resources, options) + end + + def atom_feed_for_with_ostruct(resources, options = {}) + render_feed atom_feed_for_without_ostruct(resources, options) + end + + alias_method_chain :rss_feed_for, :ostruct + alias_method_chain :atom_feed_for, :ostruct + + def html_document + @html_document ||= HTML::Document.new(@response.body, false, true) + end + + def posts_url + "http://example.com/posts" + end + + def post_url(post) + "http://example.com/posts/#{post.id}" + end +end diff --git a/tracks/vendor/plugins/simply_helpful/CHANGELOG b/tracks/vendor/plugins/simply_helpful/CHANGELOG new file mode 100644 index 00000000..fb38a874 --- /dev/null +++ b/tracks/vendor/plugins/simply_helpful/CHANGELOG @@ -0,0 +1,9 @@ +* Added formatted_polymorphic_url, formatted_polymorphic_path + +* Added support for route options. Example: + + polymorphic_url(:id => @subject, :anchor => "photo") + +* Added polymorphic routes for new and edit actions (new_polymorphic_url, edit_polymorphic_url) + +* Moved polymorphic routes from SimplyHelpful::RecordIdentifier to SimplyHelpful::PolymorphicRoutes \ No newline at end of file diff --git a/tracks/vendor/plugins/simply_helpful/README b/tracks/vendor/plugins/simply_helpful/README new file mode 100644 index 00000000..4711fe24 --- /dev/null +++ b/tracks/vendor/plugins/simply_helpful/README @@ -0,0 +1,4 @@ +SimplyHelpful +============= + +Description goes here \ No newline at end of file diff --git a/tracks/vendor/plugins/simply_helpful/Rakefile b/tracks/vendor/plugins/simply_helpful/Rakefile new file mode 100644 index 00000000..efce24d2 --- /dev/null +++ b/tracks/vendor/plugins/simply_helpful/Rakefile @@ -0,0 +1,22 @@ +require 'rake' +require 'rake/testtask' +require 'rake/rdoctask' + +desc 'Default: run unit tests.' +task :default => :test + +desc 'Test the simply_helpful plugin.' +Rake::TestTask.new(:test) do |t| + t.libs << 'lib' + t.pattern = 'test/**/*_test.rb' + t.verbose = true +end + +desc 'Generate documentation for the simply_helpful plugin.' +Rake::RDocTask.new(:rdoc) do |rdoc| + rdoc.rdoc_dir = 'rdoc' + rdoc.title = 'SimplyHelpful' + rdoc.options << '--line-numbers' << '--inline-source' + rdoc.rdoc_files.include('README') + rdoc.rdoc_files.include('lib/**/*.rb') +end diff --git a/tracks/vendor/plugins/simply_helpful/init.rb b/tracks/vendor/plugins/simply_helpful/init.rb new file mode 100644 index 00000000..d80efa41 --- /dev/null +++ b/tracks/vendor/plugins/simply_helpful/init.rb @@ -0,0 +1,4 @@ +require 'simply_helpful' +ActionController::Base.send :include, SimplyHelpful::RecordIdentificationHelper +ActionController::Base.helper SimplyHelpful::RecordIdentificationHelper, + SimplyHelpful::RecordTagHelper diff --git a/tracks/vendor/plugins/simply_helpful/lib/simply_helpful.rb b/tracks/vendor/plugins/simply_helpful/lib/simply_helpful.rb new file mode 100644 index 00000000..60e4d167 --- /dev/null +++ b/tracks/vendor/plugins/simply_helpful/lib/simply_helpful.rb @@ -0,0 +1,10 @@ +require 'simply_helpful/record_identification_helper' +require 'simply_helpful/record_identifier' +require 'simply_helpful/record_tag_helper' + +require 'simply_helpful/polymorphic_routes' + +require 'simply_helpful/jsg_extensions' +require 'simply_helpful/av_extensions' +require 'simply_helpful/form_helper_extensions' +require 'simply_helpful/controller_extensions' \ No newline at end of file diff --git a/tracks/vendor/plugins/simply_helpful/lib/simply_helpful/av_extensions.rb b/tracks/vendor/plugins/simply_helpful/lib/simply_helpful/av_extensions.rb new file mode 100644 index 00000000..d4cd4f97 --- /dev/null +++ b/tracks/vendor/plugins/simply_helpful/lib/simply_helpful/av_extensions.rb @@ -0,0 +1,26 @@ +module ActionView + module Partials + def render_partial_with_record_identification(partial_path, local_assigns = nil, deprecated_local_assigns = nil) + if partial_path.is_a?(String) || partial_path.is_a?(Symbol) || partial_path.nil? + render_partial_without_record_identification( + partial_path, local_assigns, deprecated_local_assigns + ) + elsif partial_path.is_a?(Array) + if partial_path.any? + path = SimplyHelpful::RecordIdentifier.partial_path(partial_path.first) + collection = partial_path + render_partial_collection( + path, collection, nil, local_assigns.value + ) + else + "" + end + else + render_partial_without_record_identification( + SimplyHelpful::RecordIdentifier.partial_path(partial_path), local_assigns, deprecated_local_assigns + ) + end + end + alias_method_chain :render_partial, :record_identification + end +end diff --git a/tracks/vendor/plugins/simply_helpful/lib/simply_helpful/controller_extensions.rb b/tracks/vendor/plugins/simply_helpful/lib/simply_helpful/controller_extensions.rb new file mode 100644 index 00000000..5ce3c44f --- /dev/null +++ b/tracks/vendor/plugins/simply_helpful/lib/simply_helpful/controller_extensions.rb @@ -0,0 +1,42 @@ +module SimplyHelpful + module ActionControllerExtensions + POLYMORPHIC_ROUTES = %w( + polymorphic_url polymorphic_path + edit_polymorphic_url edit_polymorphic_path + new_polymorphic_url new_polymorphic_path + formatted_polymorphic_url formatted_polymorphic_path + ) + + def self.included(base) + POLYMORPHIC_ROUTES.each { |route| base.helper_method(route) } + end + + POLYMORPHIC_ROUTES.each do |route| + module_eval <<-EOT + def #{route}(record) + SimplyHelpful::PolymorphicRoutes.#{route}(record, self) + end + EOT + end + + def redirect_to_with_record_identification(*args) + return redirect_to_without_record_identification *args unless args.size == 1 + + potential_object = args.first + + case potential_object + when String, Symbol, Hash + redirect_to_without_record_identification *args + else + redirect_to_without_record_identification SimplyHelpful::PolymorphicRoutes.polymorphic_url(potential_object, self) + end + end + end +end + +module ActionController + class Base + include SimplyHelpful::ActionControllerExtensions + alias_method_chain :redirect_to, :record_identification + end +end \ No newline at end of file diff --git a/tracks/vendor/plugins/simply_helpful/lib/simply_helpful/form_helper_extensions.rb b/tracks/vendor/plugins/simply_helpful/lib/simply_helpful/form_helper_extensions.rb new file mode 100644 index 00000000..b284ab7b --- /dev/null +++ b/tracks/vendor/plugins/simply_helpful/lib/simply_helpful/form_helper_extensions.rb @@ -0,0 +1,48 @@ +module ActionView + module Helpers + module FormHelper + def form_for_with_record_identification(name_or_object, *args, &proc) + form_method_with_record_identification :form_for, name_or_object, *args, &proc + end + + alias_method_chain :form_for, :record_identification + + protected + def form_method_with_record_identification(method_name, name_or_object, *args, &proc) + old_method_name = "#{method_name}_without_record_identification" + case name_or_object + when String, Symbol, NilClass + send(old_method_name, name_or_object, *args, &proc) + else + options = args.first || {} + + object_name = SimplyHelpful::RecordIdentifier.singular_class_name(name_or_object) + object = name_or_object + url = SimplyHelpful::PolymorphicRoutes.polymorphic_url(object, self) + + html_options = if object.new_record? + { :class => dom_class(object, :new), :id => dom_id(object), :method => :post } + else + { :class => dom_class(object, :edit), :id => dom_id(object, :edit), :method => :put } + end + + send(old_method_name, + object_name, object, options.merge({ :url => url, :html => html_options.update(options[:html] || {}) }), &proc + ) + end + end + end + end +end + +module ActionView + module Helpers + module PrototypeHelper + def remote_form_for_with_record_identification(name_or_object, *args, &proc) + form_method_with_record_identification :remote_form_for, name_or_object, *args, &proc + end + + alias_method_chain :remote_form_for, :record_identification + end + end +end diff --git a/tracks/vendor/plugins/simply_helpful/lib/simply_helpful/jsg_extensions.rb b/tracks/vendor/plugins/simply_helpful/lib/simply_helpful/jsg_extensions.rb new file mode 100644 index 00000000..6c9842a9 --- /dev/null +++ b/tracks/vendor/plugins/simply_helpful/lib/simply_helpful/jsg_extensions.rb @@ -0,0 +1,18 @@ +module ActionView + module Helpers + module PrototypeHelper + class JavaScriptGenerator + module GeneratorMethods + def [](id) + case id + when String, Symbol, NilClass + JavaScriptElementProxy.new(self, id) + else + JavaScriptElementProxy.new(self, SimplyHelpful::RecordIdentifier.dom_id(id)) + end + end + end + end + end + end +end \ No newline at end of file diff --git a/tracks/vendor/plugins/simply_helpful/lib/simply_helpful/polymorphic_routes.rb b/tracks/vendor/plugins/simply_helpful/lib/simply_helpful/polymorphic_routes.rb new file mode 100644 index 00000000..49cba920 --- /dev/null +++ b/tracks/vendor/plugins/simply_helpful/lib/simply_helpful/polymorphic_routes.rb @@ -0,0 +1,52 @@ +module SimplyHelpful + module PolymorphicRoutes + extend self + + def polymorphic_url(record_or_hash, url_writer, options = {}) + record = extract_record(record_or_hash) + + case + when options[:action] == "new" + url_writer.send(action_prefix(options) + RecordIdentifier.singular_class_name(record) + routing_type(options)) + + when record.new_record? + url_writer.send(RecordIdentifier.plural_class_name(record) + routing_type(options)) + + else + url_writer.send( + action_prefix(options) + RecordIdentifier.singular_class_name(record) + routing_type(options), record_or_hash + ) + end + end + + def polymorphic_path(record_or_hash, url_writer) + polymorphic_url(record_or_hash, url_writer, :routing_type => :path) + end + + %w( edit new formatted ).each do |action| + module_eval <<-EOT + def #{action}_polymorphic_url(record_or_hash, url_writer) + polymorphic_url(record_or_hash, url_writer, :action => "#{action}") + end + + def #{action}_polymorphic_path(record_or_hash, url_writer) + polymorphic_url(record_or_hash, url_writer, :action => "#{action}", :routing_type => :path) + end + EOT + end + + + private + def action_prefix(options) + options[:action] ? "#{options[:action]}_" : "" + end + + def routing_type(options) + "_#{options[:routing_type] || "url"}" + end + + def extract_record(record_or_hash) + record_or_hash.is_a?(Hash) ? record_or_hash[:id] : record_or_hash + end + end +end diff --git a/tracks/vendor/plugins/simply_helpful/lib/simply_helpful/record_identification_helper.rb b/tracks/vendor/plugins/simply_helpful/lib/simply_helpful/record_identification_helper.rb new file mode 100644 index 00000000..49178478 --- /dev/null +++ b/tracks/vendor/plugins/simply_helpful/lib/simply_helpful/record_identification_helper.rb @@ -0,0 +1,16 @@ +module SimplyHelpful + module RecordIdentificationHelper + protected + def partial_path(*args, &block) + RecordIdentifier.partial_path(*args, &block) + end + + def dom_class(*args, &block) + RecordIdentifier.dom_class(*args, &block) + end + + def dom_id(*args, &block) + RecordIdentifier.dom_id(*args, &block) + end + end +end diff --git a/tracks/vendor/plugins/simply_helpful/lib/simply_helpful/record_identifier.rb b/tracks/vendor/plugins/simply_helpful/lib/simply_helpful/record_identifier.rb new file mode 100644 index 00000000..d50b4bad --- /dev/null +++ b/tracks/vendor/plugins/simply_helpful/lib/simply_helpful/record_identifier.rb @@ -0,0 +1,32 @@ +module SimplyHelpful + module RecordIdentifier + extend self + + def partial_path(record_or_class) + klass = class_from_record_or_class(record_or_class) + "#{klass.name.tableize}/#{klass.name.demodulize.underscore}" + end + + def dom_class(record_or_class, prefix = nil) + [ prefix, singular_class_name(record_or_class) ].compact * '_' + end + + def dom_id(record, prefix = nil) + prefix ||= 'new' unless record.id + [ prefix, singular_class_name(record), record.id ].compact * '_' + end + + def plural_class_name(record_or_class) + singular_class_name(record_or_class).pluralize + end + + def singular_class_name(record_or_class) + class_from_record_or_class(record_or_class).name.underscore.tr('/', '_') + end + + private + def class_from_record_or_class(record_or_class) + record_or_class.is_a?(Class) ? record_or_class : record_or_class.class + end + end +end diff --git a/tracks/vendor/plugins/simply_helpful/lib/simply_helpful/record_tag_helper.rb b/tracks/vendor/plugins/simply_helpful/lib/simply_helpful/record_tag_helper.rb new file mode 100644 index 00000000..1352053f --- /dev/null +++ b/tracks/vendor/plugins/simply_helpful/lib/simply_helpful/record_tag_helper.rb @@ -0,0 +1,76 @@ +module SimplyHelpful + module RecordTagHelper + # Produces a wrapper DIV element with id and class parameters that + # relate to the specified ActiveRecord object. Usage example: + # + # <% div_for(@person, :class => "foo") do %> + # <%=h @person.name %> + # <% end %> + # + # produces: + # + #
Joe Bloggs
+ # + def div_for(record, *args, &block) + content_tag_for(:div, record, *args, &block) + end + + # content_tag_for creates an HTML element with id and class parameters + # that relate to the specified ActiveRecord object. For example: + # + # <% content_tag_for(:tr, @person) do %> + # <%=h @person.first_name %> + # <%=h @person.last_name %> + # <% end %> + # + # would produce hthe following HTML (assuming @person is an instance of + # a Person object, with an id value of 123): + # + # .... + # + # If you require the HTML id attribute to have a prefix, you can specify it: + # + # <% content_tag_for(:tr, @person, :foo) do %> ... + # + # produces: + # + # ... + # + # content_tag_for also accepts a hash of options, which will be converted to + # additional HTML attributes. If you specify a +:class+ value, it will be combined + # with the default class name for your object. For example: + # + # <% content_tag_for(:li, @person, :class => "bar") %>... + # + # produces: + # + #
  • ... + # + def content_tag_for(tag_name, record, *args, &block) + prefix = args.first.is_a?(Hash) ? nil : args.shift + options = args.first.is_a?(Hash) ? args.shift : {} + concat content_tag(tag_name, capture(&block), + options.merge({ :class => "#{dom_class(record)} #{options[:class]}".strip, :id => dom_id(record, prefix) })), + block.binding + end + end +end + +module ActionView + module Helpers + module UrlHelper + def link_to_with_record_identification(attr_name, record = {}, html_options = nil, *parameters_for_method_reference) + case record + when Hash, String, Symbol, NilClass + link_to_without_record_identification(attr_name, record, html_options, *parameters_for_method_reference) + else + url = SimplyHelpful::PolymorphicRoutes.polymorphic_url(record, self) + link_text = record.respond_to?(attr_name) ? record.send(attr_name) : attr_name + link_to_without_record_identification(link_text, url, html_options, *parameters_for_method_reference) + end + end + + alias_method_chain :link_to, :record_identification + end + end +end \ No newline at end of file diff --git a/tracks/vendor/plugins/simply_helpful/test/controller_extensions_test.rb b/tracks/vendor/plugins/simply_helpful/test/controller_extensions_test.rb new file mode 100644 index 00000000..a1a4607c --- /dev/null +++ b/tracks/vendor/plugins/simply_helpful/test/controller_extensions_test.rb @@ -0,0 +1,52 @@ +require File.dirname(__FILE__) + '/test_helper' +require 'ostruct' + +class RedirectionTestingController < ActionController::Base + class MockResponse + attr_accessor :redirected_to + + def redirect(_) + end + + end + + def initialize + super + @response = MockResponse.new + @request = OpenStruct.new + @request.protocol= "http://" + @request.host_with_port= "www.example.com" + end + + def response + @response + end + + def request + @request + end + + def post_url(p) + "/posts/#{p.id}" + end + + +end + +class ControllerExtensionsTest < Test::Unit::TestCase + def setup + @record = Post.new + @record.save + @controller = RedirectionTestingController.new + end + + def test_redirect_to_record + @controller.send :redirect_to, @record + assert_equal "http://www.example.com/posts/1", @controller.response.redirected_to + end + + def test_redirect_to_string + @controller.send :redirect_to, "http://www.yahoo.com" + assert_equal "http://www.yahoo.com", @controller.response.redirected_to + end +end \ No newline at end of file diff --git a/tracks/vendor/plugins/simply_helpful/test/form_helper_extensions_test.rb b/tracks/vendor/plugins/simply_helpful/test/form_helper_extensions_test.rb new file mode 100644 index 00000000..3e1fa944 --- /dev/null +++ b/tracks/vendor/plugins/simply_helpful/test/form_helper_extensions_test.rb @@ -0,0 +1,96 @@ +require File.dirname(__FILE__) + '/test_helper' + +class LabelledFormBuilder < ActionView::Helpers::FormBuilder + (field_helpers - %w(hidden_field)).each do |selector| + src = <<-END_SRC + def #{selector}(field, *args, &proc) + " " + super + "
    " + end + END_SRC + class_eval src, __FILE__, __LINE__ + end +end + +class FormHelperExtensionsTest < Test::Unit::TestCase + include ActionView::Helpers::FormHelper + include ActionView::Helpers::FormTagHelper + include ActionView::Helpers::PrototypeHelper + include ActionView::Helpers::UrlHelper + include ActionView::Helpers::TagHelper + include ActionView::Helpers::TextHelper + include SimplyHelpful::RecordIdentificationHelper + + def setup + @record = Post.new + @controller = Class.new do + attr_reader :url_for_options + def url_for(options, *parameters_for_method_reference) + @url_for_options = options + @url_for_options || "http://www.example.com" + end + end + @controller = @controller.new + end + + def test_form_for_with_record_identification_with_new_record + _erbout = '' + form_for(@record, {:html => { :id => 'create-post' }}) {} + + expected = "
    " + assert_dom_equal expected, _erbout + end + def test_form_for_with_record_identification_with_custom_builder + _erbout = '' + form_for(@record, :builder => LabelledFormBuilder) do |f| + _erbout.concat(f.text_field(:name)) + end + + expected = "
    " + + "" + + "
    " + + "
    " + assert_dom_equal expected, _erbout + end + + def test_form_for_with_record_identification_without_html_options + _erbout = '' + form_for(@record) {} + + expected = "
    " + assert_dom_equal expected, _erbout + end + + def test_form_for_with_record_identification_with_existing_record + @record.save + _erbout = '' + form_for(@record) {} + + expected = "
    " + assert_dom_equal expected, _erbout + end + + def test_remote_form_for_with_record_identification_with_new_record + _erbout = '' + remote_form_for(@record, {:html => { :id => 'create-post' }}) {} + + expected = %(
    ) + assert_dom_equal expected, _erbout + end + + def test_remote_form_for_with_record_identification_without_html_options + _erbout = '' + remote_form_for(@record) {} + + expected = %(
    ) + assert_dom_equal expected, _erbout + end + + def test_remote_form_for_with_record_identification_with_existing_record + @record.save + _erbout = '' + remote_form_for(@record) {} + + expected = %(
    ) + assert_dom_equal expected, _erbout + end +end \ No newline at end of file diff --git a/tracks/vendor/plugins/simply_helpful/test/record_identifier_test.rb b/tracks/vendor/plugins/simply_helpful/test/record_identifier_test.rb new file mode 100644 index 00000000..902e58bd --- /dev/null +++ b/tracks/vendor/plugins/simply_helpful/test/record_identifier_test.rb @@ -0,0 +1,80 @@ +require File.dirname(__FILE__) + '/test_helper' + +class RecordIdentifierTest < Test::Unit::TestCase + include SimplyHelpful + + def setup + @klass = Post + @record = @klass.new + @singular = 'post' + @plural = 'posts' + end + + def test_dom_id_with_new_record + assert_equal "new_#{@singular}", dom_id(@record) + end + + def test_dom_id_with_new_record_and_prefix + assert_equal "custom_prefix_#{@singular}", dom_id(@record, :custom_prefix) + end + + def test_dom_id_with_saved_record + @record.save + assert_equal "#{@singular}_1", dom_id(@record) + end + + def test_dom_id_with_prefix + @record.save + assert_equal "edit_#{@singular}_1", dom_id(@record, :edit) + end + + def test_partial_path + expected = "#{@plural}/#{@singular}" + assert_equal expected, partial_path(@record) + assert_equal expected, partial_path(Post) + end + + def test_dom_class + assert_equal @singular, dom_class(@record) + end + + def test_dom_class_with_prefix + assert_equal "custom_prefix_#{@singular}", dom_class(@record, :custom_prefix) + end + + def test_singular_class_name + assert_equal @singular, singular_class_name(@record) + end + + def test_singular_class_name_for_class + assert_equal @singular, singular_class_name(@klass) + end + + def test_plural_class_name + assert_equal @plural, plural_class_name(@record) + end + + def test_plural_class_name_for_class + assert_equal @plural, plural_class_name(@klass) + end + + private + def method_missing(method, *args) + RecordIdentifier.send(method, *args) + end +end + +class NestedRecordIdentifierTest < RecordIdentifierTest + def setup + @klass = Post::Nested + @record = @klass.new + @singular = 'post_nested' + @plural = 'post_nesteds' + end + + def test_partial_path + expected = "post/nesteds/nested" + assert_equal expected, partial_path(@record) + assert_equal expected, partial_path(Post::Nested) + end +end \ No newline at end of file diff --git a/tracks/vendor/plugins/simply_helpful/test/record_tag_helper_test.rb b/tracks/vendor/plugins/simply_helpful/test/record_tag_helper_test.rb new file mode 100644 index 00000000..0ac38dd7 --- /dev/null +++ b/tracks/vendor/plugins/simply_helpful/test/record_tag_helper_test.rb @@ -0,0 +1,133 @@ +require File.dirname(__FILE__) + '/test_helper' + +class RecordTagHelperTest < Test::Unit::TestCase + include ActionView::Helpers::UrlHelper + include ActionView::Helpers::TagHelper + include ActionView::Helpers::CaptureHelper + include ActionView::Helpers::TextHelper + include SimplyHelpful::RecordTagHelper + include SimplyHelpful::RecordIdentificationHelper + + def setup + @record = Post.new + end + + def test_content_tag_for_with_new_record + _erbout = '' + content_tag_for(:li, @record) {} + + expected = "
  • " + assert_dom_equal expected, _erbout + end + + def test_content_tag_for_with_existing_record + @record.save + _erbout = '' + content_tag_for(:li, @record) {} + + expected = "
  • " + assert_dom_equal expected, _erbout + end + + def test_content_tag_for_merges_given_class_names + _erbout = '' + content_tag_for(:li, @record, :class => 'foo') {} + + expected = "
  • " + assert_dom_equal expected, _erbout + + _erbout = '' + content_tag_for(:li, @record, :class => 'foo bar') {} + + expected = "
  • " + assert_dom_equal expected, _erbout + end + + def test_content_tag_for_with_dom_id_prefix_on_new_record + _erbout = '' + content_tag_for(:li, @record, :foo, :class => 'foo') {} + + expected = "
  • " + assert_dom_equal expected, _erbout + end + + def test_content_tag_for_with_dom_id_prefix_on_existing_record + @record.save + _erbout = '' + content_tag_for(:li, @record, :foo, :class => 'foo') {} + + expected = "
  • " + assert_dom_equal expected, _erbout + end + + def test_div_for_with_new_record + _erbout = '' + div_for(@record) {} + + expected = "
    " + assert_dom_equal expected, _erbout + end + + def test_div_for_with_existing_record + @record.save + _erbout = '' + div_for(@record) {} + + expected = "
    " + assert_dom_equal expected, _erbout + end + + def test_div_for_merges_given_class_names + _erbout = '' + div_for(@record, :class => 'foo') {} + + expected = "
    " + assert_dom_equal expected, _erbout + + _erbout = '' + div_for(@record, :class => 'foo bar') {} + + expected = "
    " + assert_dom_equal expected, _erbout + end + + def test_div_for_with_dom_id_prefix_on_new_record + _erbout = '' + div_for(@record, :foo, :class => 'foo') {} + + expected = "
    " + assert_dom_equal expected, _erbout + end + + def test_div_for_with_dom_id_prefix_on_existing_record + @record.save + _erbout = '' + div_for(@record, :foo, :class => 'foo') {} + + expected = "
    " + assert_dom_equal expected, _erbout + end + + def test_link_to_with_new_record + actual = link_to :name, @record + + expected = "new post" + assert_dom_equal expected, actual + end + + def test_link_to_with_existing_record + @record.save + actual = link_to :name, @record + + expected = "post #1" + assert_dom_equal expected, actual + end + + def test_link_to_with_an_existing_method_and_constant_text + @record.save + actual = link_to "Cancel Editing", @record + + expected = "Cancel Editing" + assert_dom_equal expected, actual + end +end \ No newline at end of file diff --git a/tracks/vendor/plugins/simply_helpful/test/simply_helpful_test.rb b/tracks/vendor/plugins/simply_helpful/test/simply_helpful_test.rb new file mode 100644 index 00000000..d202d3e7 --- /dev/null +++ b/tracks/vendor/plugins/simply_helpful/test/simply_helpful_test.rb @@ -0,0 +1,6 @@ +require File.dirname(__FILE__) + '/test_helper' + +class SimplyHelpfulTest < Test::Unit::TestCase + def default_test + end +end diff --git a/tracks/vendor/plugins/simply_helpful/test/test_helper.rb b/tracks/vendor/plugins/simply_helpful/test/test_helper.rb new file mode 100644 index 00000000..c0888078 --- /dev/null +++ b/tracks/vendor/plugins/simply_helpful/test/test_helper.rb @@ -0,0 +1,25 @@ +RAILS_ENV = 'test' +require File.expand_path(File.join(File.dirname(__FILE__), '../../../../config/environment.rb')) +require 'action_controller/test_process' +require 'breakpoint' + +class Post + attr_reader :id + def save; @id = 1 end + def new_record?; @id.nil? end + def name + @id.nil? ? 'new post' : "post ##{@id}" + end + class Nested < Post; end +end + +class Test::Unit::TestCase + protected + def posts_url + 'http://www.example.com/posts' + end + + def post_url(post) + "http://www.example.com/posts/#{post.id}" + end +end \ No newline at end of file