filtrate 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. data/.gitignore +6 -0
  2. data/Gemfile +14 -0
  3. data/Gemfile.lock +105 -0
  4. data/MIT-LICENSE +20 -0
  5. data/README.markdown +19 -0
  6. data/Rakefile +2 -0
  7. data/filtrate.gemspec +21 -0
  8. data/lib/filtrate.rb +26 -0
  9. data/lib/filtrate/filter.rb +24 -0
  10. data/lib/filtrate/filter_builder.rb +38 -0
  11. data/lib/filtrate/filterable.rb +14 -0
  12. data/lib/filtrate/helpers.rb +10 -0
  13. data/lib/filtrate/helpers/form_helper.rb +13 -0
  14. data/lib/filtrate/version.rb +3 -0
  15. data/test/dummy/Rakefile +7 -0
  16. data/test/dummy/app/controllers/application_controller.rb +3 -0
  17. data/test/dummy/app/controllers/users_controller.rb +5 -0
  18. data/test/dummy/app/helpers/application_helper.rb +2 -0
  19. data/test/dummy/app/models/user.rb +3 -0
  20. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  21. data/test/dummy/app/views/users/index.html.erb +17 -0
  22. data/test/dummy/config.ru +4 -0
  23. data/test/dummy/config/application.rb +45 -0
  24. data/test/dummy/config/boot.rb +10 -0
  25. data/test/dummy/config/database.yml +22 -0
  26. data/test/dummy/config/environment.rb +5 -0
  27. data/test/dummy/config/environments/development.rb +26 -0
  28. data/test/dummy/config/environments/production.rb +49 -0
  29. data/test/dummy/config/environments/test.rb +35 -0
  30. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  31. data/test/dummy/config/initializers/inflections.rb +10 -0
  32. data/test/dummy/config/initializers/mime_types.rb +5 -0
  33. data/test/dummy/config/initializers/secret_token.rb +7 -0
  34. data/test/dummy/config/initializers/session_store.rb +8 -0
  35. data/test/dummy/config/locales/en.yml +5 -0
  36. data/test/dummy/config/routes.rb +59 -0
  37. data/test/dummy/db/migrate/20110604112827_create_users.rb +12 -0
  38. data/test/dummy/db/migrate/20110605035626_add_date_of_birth_to_user.rb +9 -0
  39. data/test/dummy/db/schema.rb +22 -0
  40. data/test/dummy/public/404.html +26 -0
  41. data/test/dummy/public/422.html +26 -0
  42. data/test/dummy/public/500.html +26 -0
  43. data/test/dummy/public/favicon.ico +0 -0
  44. data/test/dummy/public/javascripts/application.js +2 -0
  45. data/test/dummy/public/javascripts/controls.js +965 -0
  46. data/test/dummy/public/javascripts/dragdrop.js +974 -0
  47. data/test/dummy/public/javascripts/effects.js +1123 -0
  48. data/test/dummy/public/javascripts/prototype.js +6001 -0
  49. data/test/dummy/public/javascripts/rails.js +191 -0
  50. data/test/dummy/public/stylesheets/.gitkeep +0 -0
  51. data/test/dummy/script/rails +6 -0
  52. data/test/filtrate_test.rb +7 -0
  53. data/test/integration/filter_by_date_range_test.rb +18 -0
  54. data/test/integration/filter_by_name_test.rb +16 -0
  55. data/test/integration/navigation_test.rb +11 -0
  56. data/test/support/integration_case.rb +5 -0
  57. data/test/test_helper.rb +23 -0
  58. metadata +155 -0
@@ -0,0 +1,6 @@
1
+ .bundle/
2
+ log/*.log
3
+ pkg/
4
+ test/dummy/db/*.sqlite3
5
+ test/dummy/log/*.log
6
+ test/dummy/tmp/
data/Gemfile ADDED
@@ -0,0 +1,14 @@
1
+ source "http://rubygems.org"
2
+
3
+ gem "rails", "3.0.4"
4
+ gem "arel"
5
+
6
+ group :development, :test do
7
+ gem "launchy"
8
+ gem "capybara", ">= 0.4.0"
9
+ gem "sqlite3"
10
+ end
11
+
12
+ # To use debugger (ruby-debug for Ruby 1.8.7+, ruby-debug19 for Ruby 1.9.2+)
13
+ # gem 'ruby-debug'
14
+ # gem 'ruby-debug19'
@@ -0,0 +1,105 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ abstract (1.0.0)
5
+ actionmailer (3.0.4)
6
+ actionpack (= 3.0.4)
7
+ mail (~> 2.2.15)
8
+ actionpack (3.0.4)
9
+ activemodel (= 3.0.4)
10
+ activesupport (= 3.0.4)
11
+ builder (~> 2.1.2)
12
+ erubis (~> 2.6.6)
13
+ i18n (~> 0.4)
14
+ rack (~> 1.2.1)
15
+ rack-mount (~> 0.6.13)
16
+ rack-test (~> 0.5.7)
17
+ tzinfo (~> 0.3.23)
18
+ activemodel (3.0.4)
19
+ activesupport (= 3.0.4)
20
+ builder (~> 2.1.2)
21
+ i18n (~> 0.4)
22
+ activerecord (3.0.4)
23
+ activemodel (= 3.0.4)
24
+ activesupport (= 3.0.4)
25
+ arel (~> 2.0.2)
26
+ tzinfo (~> 0.3.23)
27
+ activeresource (3.0.4)
28
+ activemodel (= 3.0.4)
29
+ activesupport (= 3.0.4)
30
+ activesupport (3.0.4)
31
+ arel (2.0.9)
32
+ builder (2.1.2)
33
+ capybara (0.4.1.1)
34
+ celerity (>= 0.7.9)
35
+ culerity (>= 0.2.4)
36
+ mime-types (>= 1.16)
37
+ nokogiri (>= 1.3.3)
38
+ rack (>= 1.0.0)
39
+ rack-test (>= 0.5.4)
40
+ selenium-webdriver (>= 0.0.27)
41
+ xpath (~> 0.1.3)
42
+ celerity (0.8.7)
43
+ childprocess (0.1.6)
44
+ ffi (~> 0.6.3)
45
+ configuration (1.2.0)
46
+ culerity (0.2.15)
47
+ erubis (2.6.6)
48
+ abstract (>= 1.0.0)
49
+ ffi (0.6.3)
50
+ rake (>= 0.8.7)
51
+ i18n (0.5.0)
52
+ json_pure (1.5.1)
53
+ launchy (0.3.7)
54
+ configuration (>= 0.0.5)
55
+ rake (>= 0.8.1)
56
+ mail (2.2.19)
57
+ activesupport (>= 2.3.6)
58
+ i18n (>= 0.4.0)
59
+ mime-types (~> 1.16)
60
+ treetop (~> 1.4.8)
61
+ mime-types (1.16)
62
+ nokogiri (1.4.4)
63
+ polyglot (0.3.1)
64
+ rack (1.2.3)
65
+ rack-mount (0.6.14)
66
+ rack (>= 1.0.0)
67
+ rack-test (0.5.7)
68
+ rack (>= 1.0)
69
+ rails (3.0.4)
70
+ actionmailer (= 3.0.4)
71
+ actionpack (= 3.0.4)
72
+ activerecord (= 3.0.4)
73
+ activeresource (= 3.0.4)
74
+ activesupport (= 3.0.4)
75
+ bundler (~> 1.0)
76
+ railties (= 3.0.4)
77
+ railties (3.0.4)
78
+ actionpack (= 3.0.4)
79
+ activesupport (= 3.0.4)
80
+ rake (>= 0.8.7)
81
+ thor (~> 0.14.4)
82
+ rake (0.9.1)
83
+ rubyzip (0.9.4)
84
+ selenium-webdriver (0.1.2)
85
+ childprocess (~> 0.1.5)
86
+ ffi (~> 0.6.3)
87
+ json_pure
88
+ rubyzip
89
+ sqlite3 (1.3.3)
90
+ thor (0.14.6)
91
+ treetop (1.4.9)
92
+ polyglot (>= 0.3.1)
93
+ tzinfo (0.3.27)
94
+ xpath (0.1.3)
95
+ nokogiri (~> 1.3)
96
+
97
+ PLATFORMS
98
+ ruby
99
+
100
+ DEPENDENCIES
101
+ arel
102
+ capybara (>= 0.4.0)
103
+ launchy
104
+ rails (= 3.0.4)
105
+ sqlite3
@@ -0,0 +1,20 @@
1
+ Copyright 2011 Jared Fraser
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,19 @@
1
+ Filtrate
2
+ ========
3
+
4
+
5
+ Controller
6
+
7
+ ```ruby
8
+ @filtered = User.filtered(params[:filters]).all
9
+ ```
10
+
11
+
12
+ Views
13
+
14
+ ```ruby
15
+ <%= filtrate users_path do |f|%>
16
+ <%= f.filter :name %>
17
+ <%= f.submit "Submit" %>
18
+ <% end %>
19
+ ```
@@ -0,0 +1,2 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
@@ -0,0 +1,21 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "filtrate/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "filtrate"
7
+ s.version = Filtrate::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Jared Fraser"]
10
+ s.email = ["j.fraser@modsognir.com"]
11
+ s.homepage = "http://github.com/modsognir/filtrate"
12
+ s.summary = %q{Rails record filtering}
13
+ s.description = %q{Helpers for building interfaces to filter records easily}
14
+
15
+ s.rubyforge_project = "filtrate"
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
+ s.require_paths = ["lib"]
21
+ end
@@ -0,0 +1,26 @@
1
+ require 'active_record'
2
+ require 'active_support'
3
+ require 'action_view/helpers'
4
+
5
+
6
+ require 'filtrate/filterable'
7
+ require 'filtrate/helpers/form_helper'
8
+
9
+ module Filtrate
10
+ extend ActiveSupport::Concern
11
+ extend ActiveSupport::Autoload
12
+
13
+ autoload :Filter, 'filtrate/filter'
14
+ autoload :Filterable, 'filtrate/filterable'
15
+ autoload :FilterBuilder, 'filtrate/filter_builder'
16
+
17
+ module ClassMethods
18
+ def filterable
19
+ extend Filterable
20
+ end
21
+ end
22
+ end
23
+
24
+ ActiveRecord::Base.class_eval{ include Filtrate }
25
+ ActiveRecord::Relation.class_eval{ include Filterable }
26
+ ActionView::Helpers.class_eval{ include Filtrate::Helpers::FormHelper }
@@ -0,0 +1,24 @@
1
+ require 'arel'
2
+
3
+ module Filtrate
4
+ class Filter
5
+ def initialize(scope, attr, val)
6
+ @scope = scope
7
+ @attr = attr
8
+ @value = val
9
+ @type = @scope.columns_hash[attr].try(:type)
10
+ @col = @scope.table[attr]
11
+ end
12
+
13
+ def to_scope
14
+ case @type
15
+ when :string
16
+ @scope.where(@col.matches("%#{@value}%"))
17
+ when :date
18
+ @scope.where(@attr => @value['from']..@value['to'])
19
+ else
20
+ @scope
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,38 @@
1
+ require 'action_view/helpers/form_tag_helper'
2
+
3
+ module Filtrate
4
+ class FilterBuilder
5
+ include ActionView::Helpers::FormTagHelper
6
+
7
+ def filter(attr, name=nil, value="", text_field_opts={})
8
+ label_tag("filters[#{attr}]", (name || attr.to_s.humanize)) + text_field_tag("filters[#{attr}]", value, text_field_opts)
9
+ end
10
+
11
+ # FIXME: Date field stuff is very messy.
12
+ def filter_date(attr, label_options={}, value="", text_field_options={})
13
+ label_options[:prefix] ||= nil
14
+ label_options[:from] ||= "From"
15
+ label_options[:to] ||= "To"
16
+ [:to, :from].map {|type| date_field_set(type, attr, label_options, value, text_field_options) }.join('').html_safe
17
+ end
18
+
19
+ def date_field_set(type, attr, label_options={}, value="", text_field_opts={})
20
+ date_label(type, attr, label_options) + date_field(type, attr, value, text_field_opts)
21
+ end
22
+
23
+ def date_label(type, attr, opts={})
24
+ label_tag("filters[#{attr}][#{type}]", "#{opts[:prefix]} #{opts[type].try(:humanize)}".strip)
25
+ end
26
+
27
+ def date_field(type, attr, value, opts)
28
+ text_field_tag("filters[#{attr}][#{type}]", value, opts)
29
+ end
30
+
31
+ def submit(value="Save changes", options={})
32
+ submit_tag(value, options)
33
+ end
34
+
35
+ def method_missing(method, *args)
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,14 @@
1
+ module Filterable
2
+ def filtered(opts)
3
+ opts ||= {}
4
+ scope = self.scoped
5
+ opts.each do |attr, val|
6
+ if val.kind_of? Hash
7
+ scope = Filtrate::Filter.new(scope, attr, val).to_scope if val['from'].present? && val['to'].present?
8
+ else
9
+ scope = Filtrate::Filter.new(scope, attr, val).to_scope if val.present?
10
+ end
11
+ end
12
+ scope
13
+ end
14
+ end
@@ -0,0 +1,10 @@
1
+ module Filtrate
2
+ module Helpers
3
+ extend ActiveSupport::Autoload
4
+
5
+ autoload :FormHelper, 'filtrate/helpers/form_helper'
6
+ autoload :FilterBuilder, 'filtrate/filter_builder'
7
+
8
+ include Filtrate::Helpers::FormHelper
9
+ end
10
+ end
@@ -0,0 +1,13 @@
1
+ module Filtrate
2
+ module Helpers
3
+ module FormHelper
4
+ def filtrate(url_for_options = {}, options = {}, *parameters_for_url, &block)
5
+ builder = Filtrate::FilterBuilder.new
6
+ builder.send(:include, ActionView::Helpers::FormTagHelper)
7
+ form_tag(url_for_options, options.merge({:method => :get}), *parameters_for_url) do
8
+ yield builder
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,3 @@
1
+ module Filtrate
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,7 @@
1
+ # Add your own tasks in files placed in lib/tasks ending in .rake,
2
+ # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
3
+
4
+ require File.expand_path('../config/application', __FILE__)
5
+ require 'rake'
6
+
7
+ Dummy::Application.load_tasks
@@ -0,0 +1,3 @@
1
+ class ApplicationController < ActionController::Base
2
+ protect_from_forgery
3
+ end
@@ -0,0 +1,5 @@
1
+ class UsersController < ApplicationController
2
+ def index
3
+ @filtered = User.filtered(params[:filters]).all
4
+ end
5
+ end
@@ -0,0 +1,2 @@
1
+ module ApplicationHelper
2
+ end
@@ -0,0 +1,3 @@
1
+ class User < ActiveRecord::Base
2
+ filterable
3
+ end
@@ -0,0 +1,14 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Dummy</title>
5
+ <%= stylesheet_link_tag :all %>
6
+ <%= javascript_include_tag :defaults %>
7
+ <%= csrf_meta_tag %>
8
+ </head>
9
+ <body>
10
+
11
+ <%= yield %>
12
+
13
+ </body>
14
+ </html>
@@ -0,0 +1,17 @@
1
+ <p><%= params.inspect %></p>
2
+ <table>
3
+ <tr>
4
+ <th>Name</th>
5
+ </tr>
6
+ <% @filtered.each do |record| %>
7
+ <tr>
8
+ <td><%= record.name %></td>
9
+ </tr>
10
+ <% end %>
11
+ <table>
12
+
13
+ <%= filtrate users_path do |f|%>
14
+ <%= f.filter :name %>
15
+ <%= f.filter_date :date_of_birth, :prefix => "Date of Birth" %>
16
+ <%= f.submit "Submit" %>
17
+ <% end %>
@@ -0,0 +1,4 @@
1
+ # This file is used by Rack-based servers to start the application.
2
+
3
+ require ::File.expand_path('../config/environment', __FILE__)
4
+ run Dummy::Application
@@ -0,0 +1,45 @@
1
+ require File.expand_path('../boot', __FILE__)
2
+
3
+ require "active_model/railtie"
4
+ require "active_record/railtie"
5
+ require "action_controller/railtie"
6
+ require "action_view/railtie"
7
+ require "action_mailer/railtie"
8
+
9
+ Bundler.require
10
+ require "filtrate"
11
+
12
+ module Dummy
13
+ class Application < Rails::Application
14
+ # Settings in config/environments/* take precedence over those specified here.
15
+ # Application configuration should go into files in config/initializers
16
+ # -- all .rb files in that directory are automatically loaded.
17
+
18
+ # Custom directories with classes and modules you want to be autoloadable.
19
+ # config.autoload_paths += %W(#{config.root}/extras)
20
+
21
+ # Only load the plugins named here, in the order given (default is alphabetical).
22
+ # :all can be used as a placeholder for all plugins not explicitly named.
23
+ # config.plugins = [ :exception_notification, :ssl_requirement, :all ]
24
+
25
+ # Activate observers that should always be running.
26
+ # config.active_record.observers = :cacher, :garbage_collector, :forum_observer
27
+
28
+ # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
29
+ # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
30
+ # config.time_zone = 'Central Time (US & Canada)'
31
+
32
+ # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
33
+ # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
34
+ # config.i18n.default_locale = :de
35
+
36
+ # JavaScript files you want as :defaults (application.js is always included).
37
+ # config.action_view.javascript_expansions[:defaults] = %w(jquery rails)
38
+
39
+ # Configure the default encoding used in templates for Ruby 1.9.
40
+ config.encoding = "utf-8"
41
+
42
+ # Configure sensitive parameters which will be filtered from the log file.
43
+ config.filter_parameters += [:password]
44
+ end
45
+ end