filter_fu 0.5.0

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.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
data/.gitignore ADDED
@@ -0,0 +1,6 @@
1
+ *.sw?
2
+ .DS_Store
3
+ coverage
4
+ rdoc
5
+ pkg
6
+ spec/debug.log
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Benedikt Deicke
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.
data/README.rdoc ADDED
@@ -0,0 +1,75 @@
1
+ = filter_fu
2
+
3
+ This Ruby on Rails plugin adds a filtered_by method to your models. It accepts a hash of filters that are applied using named_scopes. In addition the plugin adds some view helpers to easily build filter forms.
4
+
5
+ == Install
6
+
7
+ You can install filter_fu as a gem or as a rails plugin.
8
+
9
+ === Install as gem
10
+
11
+ Add this line to your <tt>config/environment.rb</tt> and run <tt>rake gems:install</tt>
12
+
13
+ config.gem 'filter_fu', :source => 'http://www.gemcutter.org'
14
+
15
+ === Install as plugin
16
+
17
+ Run this command in your currrent project's +RAILS_ROOT+
18
+
19
+ ./script/plugin install git://github.com/benedikt/filter_fu.git
20
+
21
+ == Usage
22
+
23
+ === Models
24
+
25
+ To enable filter_fu on a model, simply add one line to its definition:
26
+
27
+ class Project
28
+ filter_fu
29
+ end
30
+
31
+ Let's say you don't want your Projects list filtered by its +hidden+ column. You can easly
32
+ tell filter_fu to ignore certian named scopes or columns:
33
+
34
+ class Project
35
+ filter_fu :except => [:hidden]
36
+ end
37
+
38
+ Of course this also works the other way round using the <tt>:only</tt> option to only allow filtering
39
+ for the given named scopes or columns:
40
+
41
+ class Project
42
+ filter_fu :only => [:starts_on, :ends_on]
43
+ end
44
+
45
+ Once you enabled filter_fu on your model it provides a filtered_by method.
46
+
47
+ Project.filtered_by(params[:filter])
48
+ Project.filtered_by(params[:filter]).some.named_scopes
49
+ Project.some.other.named_scopes.filtered_by(params[:filter])
50
+
51
+
52
+ === Helper
53
+
54
+ filter_fu comes with helpers to simplify the generation of filter forms:
55
+
56
+ <% filter_form do |f| %>
57
+ # f is a ActionView::Helpers::FormBuilder
58
+ <% end %>
59
+
60
+ You can also specify a name for the filter (Default is <tt>:filter</tt>). This way you're able to have multiple filters on the same page.
61
+
62
+ <% filter_form_for(:product_filter) do |f| %>
63
+ # f is a ActionView::Helpers::FormBuilder
64
+ <% end %>
65
+
66
+ filter_fu will automatically include all other parameters for the current page (ie. pagination parameters) within the form.
67
+ If you wish to explicitly exclude some you can do this by passing an array as :ignore_parameters option.
68
+
69
+ <% filter_form_for(:product_filter, :ignore_parameters => [:page]) do |f| %>
70
+ # f is a ActionView::Helpers::FormBuilder
71
+ <% end %>
72
+
73
+ == Copyright
74
+
75
+ Copyright (c) 2009 Benedikt Deicke. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,60 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "filter_fu"
8
+ gem.summary = %Q{Filter ActiveRecord models using named_scopes}
9
+ gem.description = %Q{This Ruby on Rails plugin adds a filtered_by method to your models. It accepts a hash of filters that are applied using named_scopes. In addition the plugin adds some view helpers to easily build filter forms.}
10
+ gem.email = "benedikt@synatic.net"
11
+ gem.homepage = "http://github.com/benedikt/filter_fu"
12
+ gem.authors = ["Benedikt Deicke"]
13
+ gem.add_development_dependency "rspec"
14
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
15
+ end
16
+ Jeweler::GemcutterTasks.new
17
+ rescue LoadError
18
+ puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
19
+ end
20
+
21
+ require 'spec/rake/spectask'
22
+ Spec::Rake::SpecTask.new(:spec) do |spec|
23
+ spec.libs << 'lib' << 'spec'
24
+ spec.spec_opts = ['--options', 'spec/spec.opts']
25
+ spec.spec_files = FileList['spec/**/*_spec.rb']
26
+ end
27
+
28
+ namespace :spec do
29
+ Spec::Rake::SpecTask.new(:rcov) do |spec|
30
+ spec.libs << 'lib'
31
+ spec.pattern = 'spec/**/*_spec.rb'
32
+ spec.rcov = true
33
+ spec.rcov_opts = ["--exclude", "^/,^spec/"]
34
+ end
35
+
36
+ Spec::Rake::SpecTask.new(:doc) do |spec|
37
+ spec.libs << 'lib' << 'spec'
38
+ spec.spec_opts = ["--color", "--format", "specdoc"]
39
+ spec.pattern = 'spec/**/*_spec.rb'
40
+ end
41
+ end
42
+
43
+ task :spec => :check_dependencies
44
+
45
+ task :default => :spec
46
+
47
+ require 'rake/rdoctask'
48
+ Rake::RDocTask.new do |rdoc|
49
+ if File.exist?('VERSION')
50
+ version = File.read('VERSION')
51
+ else
52
+ version = ""
53
+ end
54
+
55
+ rdoc.rdoc_dir = 'rdoc'
56
+ rdoc.title = "filter_fu #{version}"
57
+ rdoc.rdoc_files.include('README*')
58
+ rdoc.rdoc_files.include('LICENSE*')
59
+ rdoc.rdoc_files.include('lib/**/*.rb')
60
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.5.0
data/filter_fu.gemspec ADDED
@@ -0,0 +1,68 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run `rake gemspec`
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{filter_fu}
8
+ s.version = "0.5.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Benedikt Deicke"]
12
+ s.date = %q{2009-10-15}
13
+ s.description = %q{This Ruby on Rails plugin adds a filtered_by method to your models. It accepts a hash of filters that are applied using named_scopes. In addition the plugin adds some view helpers to easily build filter forms.}
14
+ s.email = %q{benedikt@synatic.net}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE",
17
+ "README.rdoc"
18
+ ]
19
+ s.files = [
20
+ ".document",
21
+ ".gitignore",
22
+ "LICENSE",
23
+ "README.rdoc",
24
+ "Rakefile",
25
+ "VERSION",
26
+ "filter_fu.gemspec",
27
+ "lib/filter_fu.rb",
28
+ "lib/filter_fu/active_record.rb",
29
+ "lib/filter_fu/view_helper.rb",
30
+ "rails/init.rb",
31
+ "spec/active_record_spec.rb",
32
+ "spec/db/database.yml",
33
+ "spec/db/schema.rb",
34
+ "spec/dummies.rb",
35
+ "spec/filter_fu_spec.rb",
36
+ "spec/fixtures/employee.rb",
37
+ "spec/spec.opts",
38
+ "spec/spec_helper.rb",
39
+ "spec/view_helper_spec.rb"
40
+ ]
41
+ s.homepage = %q{http://github.com/benedikt/filter_fu}
42
+ s.rdoc_options = ["--charset=UTF-8"]
43
+ s.require_paths = ["lib"]
44
+ s.rubygems_version = %q{1.3.5}
45
+ s.summary = %q{Filter ActiveRecord models using named_scopes}
46
+ s.test_files = [
47
+ "spec/active_record_spec.rb",
48
+ "spec/db/schema.rb",
49
+ "spec/dummies.rb",
50
+ "spec/filter_fu_spec.rb",
51
+ "spec/fixtures/employee.rb",
52
+ "spec/spec_helper.rb",
53
+ "spec/view_helper_spec.rb"
54
+ ]
55
+
56
+ if s.respond_to? :specification_version then
57
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
58
+ s.specification_version = 3
59
+
60
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
61
+ s.add_development_dependency(%q<rspec>, [">= 0"])
62
+ else
63
+ s.add_dependency(%q<rspec>, [">= 0"])
64
+ end
65
+ else
66
+ s.add_dependency(%q<rspec>, [">= 0"])
67
+ end
68
+ end
@@ -0,0 +1,62 @@
1
+ module FilterFu
2
+ module ActiveRecord
3
+
4
+ def self.included(base) # :nodoc:
5
+ base.extend(ClassMethods)
6
+ end
7
+
8
+ module ClassMethods
9
+
10
+ VALID_FILTER_OPTIONS = [:only, :except]
11
+
12
+ def filter_fu(opts = {})
13
+ opts = opts.symbolize_keys!
14
+ opts.each_key { |option| raise "Invalid filter_fu option: #{option}" unless VALID_FILTER_OPTIONS.include?(option) }
15
+ raise "Use either :only or :except as a filter_fu option." if opts.has_key?(:only) && opts.has_key?(:except)
16
+
17
+ opts[:only] = [opts[:only]].flatten.collect(&:to_sym) if opts[:only]
18
+ opts[:except] = [opts[:except]].flatten.collect(&:to_sym) if opts[:except]
19
+
20
+ @filter_options = opts
21
+
22
+ extend SingletonMethods
23
+ end
24
+
25
+ end
26
+
27
+ module SingletonMethods
28
+
29
+ def filtered_by(filter)
30
+ return scoped({}) if !filter || filter.empty?
31
+
32
+ filter.inject(self) do |memo, (scope, arg)|
33
+ scope = scope.to_sym
34
+ next if protected?(scope)
35
+ if scopes.has_key?(scope)
36
+ memo.send(scope, arg)
37
+ else
38
+ memo.scoped(build_anonymous_scope(scope, arg))
39
+ end
40
+ end || scoped({})
41
+ end
42
+
43
+ private
44
+
45
+ def build_anonymous_scope(scope, arg)
46
+ return {} unless column_names.include?(scope.to_s) && !arg.blank?
47
+ { :conditions => { scope => arg } }
48
+ end
49
+
50
+ def protected?(scope)
51
+ if @filter_options.has_key?(:only)
52
+ return !@filter_options[:only].include?(scope)
53
+ elsif @filter_options.has_key?(:except)
54
+ return @filter_options[:except].include?(scope)
55
+ end
56
+ return false
57
+ end
58
+
59
+ end
60
+
61
+ end
62
+ end
@@ -0,0 +1,50 @@
1
+ require 'ostruct'
2
+
3
+ module FilterFu
4
+ module ViewHelper
5
+
6
+ def self.included(base) # :nodoc:
7
+ base.send :include, InstanceMethods
8
+ end
9
+
10
+ module InstanceMethods
11
+
12
+ def filter_form_for(*args, &block)
13
+ raise ArgumentError, 'Missing block' unless block_given?
14
+
15
+ opts = args.extract_options!
16
+ name = (args.first || :filter).to_sym
17
+
18
+ opts[:ignore_parameters] ||= []
19
+ opts[:ignore_parameters] += [:controller, :action, name]
20
+
21
+ opts[:html] ||= {}
22
+ opts[:html][:method] ||= :get
23
+
24
+ form_for(name, OpenStruct.new(params[name]), opts) do |f|
25
+ hidden_fields_for(params, opts)
26
+ block.call(f)
27
+ end
28
+ end
29
+ alias_method :filter_form, :filter_form_for
30
+
31
+ private
32
+
33
+ def hidden_fields_for(params, opts, prefix = nil)
34
+ params.each_pair do |k, v|
35
+ next if opts[:ignore_parameters].include?(k.to_sym)
36
+
37
+ k = "[#{k}]" if prefix
38
+
39
+ if v.kind_of?(Hash)
40
+ hidden_fields_for(v, opts, "#{prefix}#{k}")
41
+ else
42
+ concat(hidden_field_tag("#{prefix}#{k}", v))
43
+ end
44
+ end
45
+ end
46
+
47
+ end
48
+
49
+ end
50
+ end
data/lib/filter_fu.rb ADDED
@@ -0,0 +1,4 @@
1
+ %w(active_record view_helper).each { |file| require File.join(File.dirname(__FILE__), 'filter_fu', file) }
2
+
3
+ ActiveRecord::Base.send :include, FilterFu::ActiveRecord
4
+ ActionView::Base.send :include, FilterFu::ViewHelper
data/rails/init.rb ADDED
@@ -0,0 +1 @@
1
+ require 'filter_fu'
@@ -0,0 +1,159 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+ require File.expand_path(File.dirname(__FILE__) + '/fixtures/employee')
3
+
4
+ describe FilterFu::ActiveRecord do
5
+
6
+ it "should add a filter_fu class method to ActiveRecord::Base" do
7
+ ActiveRecord::Base.should respond_to(:filter_fu)
8
+ end
9
+
10
+ describe "filter_fu" do
11
+
12
+ it "should accept an options hash" do
13
+ lambda { ActiveRecord::Base.filter_fu({}) }.should_not raise_error(ArgumentError)
14
+ end
15
+
16
+ it "should not require an options hash" do
17
+ lambda { ActiveRecord::Base.filter_fu }.should_not raise_error(ArgumentError)
18
+ end
19
+
20
+ it "should add a new singleton method called filtered_by" do
21
+ Employee.should respond_to(:filtered_by)
22
+ end
23
+
24
+ it "should not accept invalid options" do
25
+ lambda { ActiveRecord::Base.filter_fu(:invalid_option => 'some value') }.should raise_error
26
+ end
27
+
28
+ %w(only except).each do |option|
29
+ it "should accept :#{option} as an option" do
30
+ lambda { ActiveRecord::Base.filter_fu(option => 'some value') }.should_not raise_error
31
+ end
32
+ end
33
+
34
+ it "should not accept :except and :only option at the same time" do
35
+ lambda { ActiveRecord::Base.filter_fu(:only => 'some value', :except => 'some other value') }.should raise_error(/Use either :only or :except/)
36
+ end
37
+
38
+ end
39
+
40
+ describe "filtered_by" do
41
+
42
+ before(:each) do
43
+ @plain_class = Class.new(Employee)
44
+ @class = @plain_class.clone
45
+ @class.filter_fu if @class.respond_to?(:filter_fu)
46
+ end
47
+
48
+ it "should require a hash with filter params" do
49
+ lambda { @class.filtered_by }.should raise_error(ArgumentError)
50
+ end
51
+
52
+ it "should not fail if the hash with filter params is nil" do
53
+ lambda { @class.filtered_by(nil) }.should_not raise_error(NoMethodError)
54
+ end
55
+
56
+ it "should not filter anything if the hash is nil" do
57
+ @class.filtered_by(nil).should == @class.all
58
+ end
59
+
60
+ it "should not filter anything if the hash is empty" do
61
+ @class.filtered_by({}).should == @class.all
62
+ end
63
+
64
+ it "should not return nil if all scopes were skipped" do
65
+ # This is ugly. Is there a better solution to this?
66
+ klass = @plain_class.filter_fu :only => :salary
67
+ klass.filtered_by({ :country => 'Whatever' }).should_not be_nil
68
+ end
69
+
70
+ it "should handle HashWithIndifferentAccess correctly" do
71
+ @class.filtered_by(HashWithIndifferentAccess.new('salary' => 100000)).should == @class.all(:conditions => 'salary = 100000')
72
+ @class.filtered_by(HashWithIndifferentAccess.new('boss' => true)).should == @class.all(:conditions => "position = 'Boss'")
73
+ end
74
+
75
+ it "should return an instace of ActiveRecord::NamedScope::Scope" do
76
+ @class.filtered_by({ :boss => nil }).class.should == ActiveRecord::NamedScope::Scope
77
+ end
78
+
79
+ it "should call named scopes if specified in the filter params" do
80
+ @class.should_receive(:boss)
81
+ @class.filtered_by({ :boss => '' })
82
+ end
83
+
84
+ it "should pass the value to the named scope" do
85
+ @class.should_receive(:country).with('some value')
86
+ @class.filtered_by({ :country => 'some value'})
87
+ end
88
+
89
+ it "should only call the specified named scope if it is available" do
90
+ @class.should_not_receive(:unavailable)
91
+ @class.filtered_by({ :unavailable => '' })
92
+ end
93
+
94
+ it "should allow multiple scopes at once and combine them" do
95
+ @class.filtered_by({ :position => 'Worker', :country => 'Country 1'}).should == @class.all(:conditions => { :position => 'Worker', :country => 'Country 1'})
96
+ end
97
+
98
+ describe "when the given named scope is not available" do
99
+
100
+ it "should create an anonymous scope using the filter options as conditions" do
101
+ @class.filtered_by(:salary => 100000).should == @class.all(:conditions => 'salary = 100000')
102
+ end
103
+
104
+ it "should not create an anonymous scope if there is no column for it" do
105
+ lambda { @class.filtered_by(:non_existing_column => 'some value').all }.should_not raise_error(/no such column/)
106
+ end
107
+
108
+ it "should not create an anonymous scope if the value is blank" do
109
+ @class.filtered_by(:salary => '').should == @class.all()
110
+ end
111
+
112
+ it "should create an anonymous scope that is able to handle an array of possible values for the filter" do
113
+ @class.filtered_by(:salary => [80000, 90000]).should == @class.all(:conditions => 'salary IN (80000, 90000)')
114
+ end
115
+
116
+ end
117
+
118
+ it "should not filter by scopes defined in :except option" do
119
+ klass = @plain_class.clone
120
+ klass.filter_fu :except => :dont_access_me
121
+ klass.named_scope :dont_access_me, {}
122
+ klass.named_scope :access_me, {}
123
+
124
+ klass.should_not_receive(:dont_access_me)
125
+ klass.filtered_by(:dont_access_me => '')
126
+ end
127
+
128
+ it "should filter by scopes not defined in :except option" do
129
+ klass = @plain_class.clone
130
+ klass.filter_fu :except => :dont_access_me
131
+ klass.named_scope :dont_access_me, {}
132
+ klass.named_scope :access_me, {}
133
+
134
+ klass.should_receive(:access_me)
135
+ klass.filtered_by(:access_me => '')
136
+ end
137
+
138
+ it "should only filter by scopes define in :only option" do
139
+ klass = @plain_class.clone
140
+ klass.filter_fu :only => :only_access_me
141
+ klass.named_scope :only_access_me, {}
142
+ klass.named_scope :dont_access_me, {}
143
+
144
+ klass.should_receive(:only_access_me)
145
+ klass.filtered_by(:only_access_me => '')
146
+ end
147
+
148
+ it "should not filter by scopes not defined in :only option" do
149
+ klass = @plain_class.clone
150
+ klass.filter_fu :only => :only_access_me
151
+ klass.named_scope :only_access_me, {}
152
+ klass.named_scope :dont_access_me, {}
153
+
154
+ klass.should_not_receive(:dont_access_me)
155
+ klass.filtered_by(:dont_access_me => '')
156
+ end
157
+ end
158
+
159
+ end
@@ -0,0 +1,3 @@
1
+ sqlite3:
2
+ database: ":memory:"
3
+ adapter: sqlite3
data/spec/db/schema.rb ADDED
@@ -0,0 +1,10 @@
1
+ ActiveRecord::Schema.define(:version => 0) do
2
+
3
+ create_table :employees, :force => true do |t|
4
+ t.string :name
5
+ t.string :country
6
+ t.string :position
7
+ t.integer :salary
8
+ end
9
+
10
+ end
data/spec/dummies.rb ADDED
@@ -0,0 +1,46 @@
1
+ # Taken from mislav's will_paginate http://github.com/mislav/will_paginate/tree/master
2
+
3
+ class DummyRequest
4
+ attr_accessor :symbolized_path_parameters
5
+
6
+ def initialize
7
+ @get = true
8
+ @params = {}
9
+ @symbolized_path_parameters = { :controller => 'foo', :action => 'bar' }
10
+ end
11
+
12
+ def get?
13
+ @get
14
+ end
15
+
16
+ def post
17
+ @get = false
18
+ end
19
+
20
+ def relative_url_root
21
+ ''
22
+ end
23
+
24
+ def params(more = nil)
25
+ @params.update(more) if more
26
+ @params
27
+ end
28
+ end
29
+
30
+ class DummyController
31
+ attr_reader :request
32
+ attr_accessor :controller_name
33
+
34
+ def initialize
35
+ @request = DummyRequest.new
36
+ @url = ActionController::UrlRewriter.new(@request, @request.params)
37
+ end
38
+
39
+ def params
40
+ @request.params
41
+ end
42
+
43
+ def url_for(params)
44
+ @url.rewrite(params)
45
+ end
46
+ end
@@ -0,0 +1,13 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe FilterFu do
4
+
5
+ it "should include FilterFu::ViewHelper into ActionView::Base" do
6
+ ActionView::Base.ancestors.should include(FilterFu::ViewHelper)
7
+ end
8
+
9
+ it "should include FilterFu::ActiveRecord into ActiveRecord::Base" do
10
+ ActiveRecord::Base.ancestors.should include(FilterFu::ActiveRecord)
11
+ end
12
+
13
+ end
@@ -0,0 +1,14 @@
1
+ class Employee < ActiveRecord::Base
2
+
3
+ named_scope :boss, :conditions => "position = 'Boss'"
4
+ named_scope :country, lambda { |country| { :conditions => ["country = ?", country] } }
5
+
6
+ end
7
+
8
+ 20.times do |n|
9
+ position = (n == 0) ? "Boss" : "Worker"
10
+ salary = (n == 0) ? 100000 : (((n+1) % 5) * 10000)
11
+ Employee.create(:name => "Employee #{n}", :country => "Country #{(n % 10) + 1}", :position => position, :salary => salary)
12
+ end
13
+
14
+ #puts Employee.all.inspect
data/spec/spec.opts ADDED
@@ -0,0 +1,4 @@
1
+ --colour
2
+ --format progress
3
+ --loadby mtime
4
+ --reverse
@@ -0,0 +1,25 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
2
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
+
4
+ begin
5
+ require File.dirname(__FILE__) + '/../../../../spec/spec_helper'
6
+ rescue LoadError
7
+ puts "You need to install rspec in your base app"
8
+ exit
9
+ end
10
+
11
+ require 'filter_fu'
12
+
13
+ Spec::Runner.configure do |config|
14
+
15
+ end
16
+
17
+ ActiveRecord::Base.logger = Logger.new(File.join(File.dirname(__FILE__), 'debug.log'))
18
+
19
+ configuration = YAML.load_file(File.join(File.dirname(__FILE__), 'db', 'database.yml'))
20
+ ActiveRecord::Base.establish_connection(configuration[ENV["DB"] || "sqlite3"])
21
+
22
+ ActiveRecord::Base.silence do
23
+ ActiveRecord::Migration.verbose = false
24
+ load(File.join(File.dirname(__FILE__), "db", "schema.rb"))
25
+ end
@@ -0,0 +1,127 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+ require 'dummies'
3
+
4
+ describe FilterFu::ViewHelper, :type => :helper do
5
+
6
+ before(:each) do
7
+ @controller = DummyController.new
8
+ @request = @controller.request
9
+
10
+ helper.controller = @controller
11
+ helper.request = @request
12
+
13
+ helper.output_buffer = ""
14
+ end
15
+
16
+ it "should provide a filter_form_for method" do
17
+ helper.should respond_to(:filter_form_for)
18
+ end
19
+
20
+ it "should prodive a filter_form method as an alias for filter_form" do
21
+ helper.should respond_to(:filter_form)
22
+ end
23
+
24
+ it "should require a block" do
25
+ lambda { helper.filter_form_for }.should raise_error(ArgumentError, /Missing block/)
26
+ end
27
+
28
+ it "should accept options" do
29
+ lambda { helper.filter_form_for({}) {} }.should_not raise_error(ArgumentError)
30
+ end
31
+
32
+ it "should not require options" do
33
+ lambda { helper.filter_form_for() {} }.should_not raise_error(ArgumentError)
34
+ end
35
+
36
+ it "should accept a name together with options" do
37
+ lambda { helper.filter_form_for(:other, {}) {} }.should_not raise_error(ArgumentError)
38
+ end
39
+
40
+ it "should call the associated block" do
41
+ lambda {
42
+ helper.filter_form_for() { throw :done }
43
+ }.should throw_symbol(:done)
44
+ end
45
+
46
+ it "should pass a ActionView::Helpers::FormBuilder to the block" do
47
+ helper.filter_form_for { |f| f.should be_kind_of(ActionView::Helpers::FormBuilder) }
48
+ end
49
+
50
+ it "should include the erb of the block" do
51
+ html = eval_erb("<% filter_form_for { %><div>Some random HTML</div><% } %>")
52
+ html.should have_tag('div', 'Some random HTML')
53
+ end
54
+
55
+ it "should include a form tag" do
56
+ html = eval_erb("<% filter_form_for { %> <% } %>")
57
+ html.should have_tag('form')
58
+ end
59
+
60
+ it "should set the form method attribute to GET" do
61
+ html = eval_erb("<% filter_form_for { %> <% } %>")
62
+ html.should have_tag('form[method=?]', 'get')
63
+ end
64
+
65
+ it "should set the form action attribute to the current url" do
66
+ # Controller and Action are foo and bar as defined in the dummies
67
+ html = eval_erb("<% filter_form_for { %> <% } %>")
68
+ html.should have_tag('form[action=?]', '/foo/bar')
69
+ end
70
+
71
+ it "should use :filter as the default namespace in form fields" do
72
+ html = eval_erb("<% filter_form_for { |f| %><%= f.text_field :name %><% } %>")
73
+ html.should have_tag('input[name=?]', 'filter[name]')
74
+ end
75
+
76
+ it "should use another name as namespace if it's provided as the first argument" do
77
+ html = eval_erb("<% filter_form_for(:other) { |f| %><%= f.text_field :name %><% } %>")
78
+ html.should have_tag('input[name=?]', 'other[name]')
79
+ end
80
+
81
+ it "should pass options to the form_for helper" do
82
+ html = eval_erb("<% filter_form_for(:html => { :class => 'filter' }) { |f| %> <% } %>")
83
+ html.should have_tag('form[class=?]', 'filter')
84
+ end
85
+
86
+ it "should preserve the page's parameters with hidden fields" do
87
+ helper.params = { :some_param => 'some value', :some_other_param => 'some other value' }
88
+ html = eval_erb("<% filter_form_for() { |f| %> <% } %>")
89
+ html.should have_tag('input[type=?][name=?][value=?]', 'hidden', 'some_param', 'some value')
90
+ html.should have_tag('input[type=?][name=?][value=?]', 'hidden', 'some_other_param', 'some other value')
91
+ end
92
+
93
+ it "should preserve the page's nested parameters with hidden fields" do
94
+ helper.params = { :some_param => 'some value', :nested => { :some_other_param => 'some other value', :deeply_nested => { :down_here => 'yet another value' } } }
95
+ html = eval_erb("<% filter_form_for() { |f| %> <% } %>")
96
+ html.should have_tag('input[type=?][name=?][value=?]', 'hidden', 'some_param', 'some value')
97
+ html.should have_tag('input[type=?][name=?][value=?]', 'hidden', 'nested[some_other_param]', 'some other value')
98
+ html.should have_tag('input[type=?][name=?][value=?]', 'hidden', 'nested[deeply_nested][down_here]', 'yet another value')
99
+ end
100
+
101
+ it "should not preserve the page's parameters for the current filter" do
102
+ helper.params = { :other => { :name => 'some value' }}
103
+ html = eval_erb("<% filter_form_for(:other) { |f| %> <% } %>")
104
+ html.should_not have_tag('input[type=?][name=?]', 'hidden', 'other')
105
+ html.should_not have_tag('input[type=?][name=?][value=?]', 'hidden', 'other[name]', 'some value')
106
+ end
107
+
108
+ it "should not preserve the controller and action params" do
109
+ helper.params = { :controller => 'foo', :action => 'bar' }
110
+ html = eval_erb("<% filter_form_for() { |f| %> <% } %>")
111
+ html.should_not have_tag('input[type=?][name=?][value=?]', 'hidden', 'controller', 'foo')
112
+ html.should_not have_tag('input[type=?][name=?][value=?]', 'hidden', 'action', 'bar')
113
+ end
114
+
115
+ it "should not preserve params specified in :ignore_parameters" do
116
+ helper.params = { :some_param => 'some value', :some_other_param => 'some other value' }
117
+ html = eval_erb("<% filter_form_for(:ignore_parameters => [:some_other_param]) { |f| %> <% } %>")
118
+ html.should have_tag('input[type=?][name=?][value=?]', 'hidden', 'some_param', 'some value')
119
+ html.should_not have_tag('input[type=?][name=?][value=?]', 'hidden', 'some_other_param', 'some other value')
120
+ end
121
+
122
+ it "should use the current filter params as defaults for the form" do
123
+ helper.params = { :filter => { :some_param => 'some value' } }
124
+ html = eval_erb("<% filter_form_for() { |f| %><%= f.text_field :some_param %><% } %>")
125
+ html.should have_tag('input[type=?][name=?][value=?]', 'text', 'filter[some_param]', 'some value')
126
+ end
127
+ end
metadata ADDED
@@ -0,0 +1,90 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: filter_fu
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.5.0
5
+ platform: ruby
6
+ authors:
7
+ - Benedikt Deicke
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-10-15 00:00:00 +02:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: rspec
17
+ type: :development
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0"
24
+ version:
25
+ description: This Ruby on Rails plugin adds a filtered_by method to your models. It accepts a hash of filters that are applied using named_scopes. In addition the plugin adds some view helpers to easily build filter forms.
26
+ email: benedikt@synatic.net
27
+ executables: []
28
+
29
+ extensions: []
30
+
31
+ extra_rdoc_files:
32
+ - LICENSE
33
+ - README.rdoc
34
+ files:
35
+ - .document
36
+ - .gitignore
37
+ - LICENSE
38
+ - README.rdoc
39
+ - Rakefile
40
+ - VERSION
41
+ - filter_fu.gemspec
42
+ - lib/filter_fu.rb
43
+ - lib/filter_fu/active_record.rb
44
+ - lib/filter_fu/view_helper.rb
45
+ - rails/init.rb
46
+ - spec/active_record_spec.rb
47
+ - spec/db/database.yml
48
+ - spec/db/schema.rb
49
+ - spec/dummies.rb
50
+ - spec/filter_fu_spec.rb
51
+ - spec/fixtures/employee.rb
52
+ - spec/spec.opts
53
+ - spec/spec_helper.rb
54
+ - spec/view_helper_spec.rb
55
+ has_rdoc: true
56
+ homepage: http://github.com/benedikt/filter_fu
57
+ licenses: []
58
+
59
+ post_install_message:
60
+ rdoc_options:
61
+ - --charset=UTF-8
62
+ require_paths:
63
+ - lib
64
+ required_ruby_version: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: "0"
69
+ version:
70
+ required_rubygems_version: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: "0"
75
+ version:
76
+ requirements: []
77
+
78
+ rubyforge_project:
79
+ rubygems_version: 1.3.5
80
+ signing_key:
81
+ specification_version: 3
82
+ summary: Filter ActiveRecord models using named_scopes
83
+ test_files:
84
+ - spec/active_record_spec.rb
85
+ - spec/db/schema.rb
86
+ - spec/dummies.rb
87
+ - spec/filter_fu_spec.rb
88
+ - spec/fixtures/employee.rb
89
+ - spec/spec_helper.rb
90
+ - spec/view_helper_spec.rb