kashiwamochi 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format d
data/Gemfile ADDED
@@ -0,0 +1,13 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gem 'railties', '~> 3.0'
4
+
5
+ group :development do
6
+ gem 'activerecord', '~> 3.0'
7
+ gem 'sqlite3', '~> 1.3.4'
8
+ gem 'rspec', '~> 2.7.0'
9
+ gem 'rspec-rails', '~> 2.7.0'
10
+ gem 'bundler', '~> 1.0.11'
11
+ gem 'jeweler', '~> 1.6.4'
12
+ gem 'rcov', '~> 0.9.11'
13
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 mashiro
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.md ADDED
@@ -0,0 +1,70 @@
1
+ # kashiwamochi
2
+
3
+ Kashiwamochi is a minimal searching extension for Rails 3.
4
+
5
+ ## Installation
6
+
7
+ ```ruby
8
+ gem 'kashiwamochi'
9
+ # gem 'kashiwamochi', :git => 'git://github.com/mashiro/kashiwamochi.git'
10
+ ```
11
+
12
+ ## Getting started
13
+
14
+ ### In your controllers
15
+
16
+ ```ruby
17
+ # use before_filter.
18
+ before_filter :build_query!, :only => [:index]
19
+
20
+ # or write directly.
21
+ def index
22
+ @q = Kashiwamochi.build(params[:q])
23
+ @users = User.where(:name => @q.name)
24
+ end
25
+
26
+ ```
27
+
28
+ ### In your views
29
+
30
+ ```ruby
31
+ # _search.html.haml
32
+ = search_form_for @q do |f|
33
+ = f.text_field :name
34
+ = f.submit
35
+
36
+ # _list.html.haml
37
+ %table
38
+ %thead
39
+ %tr
40
+ %th= sort_link_to @q, :name, 'User name'
41
+ %tbody
42
+ ...
43
+ ```
44
+
45
+ #### With simple_form
46
+
47
+ ```ruby
48
+ = search_form_for @q, :form_method => :simple_form_for do |f|
49
+ = f.input :name
50
+ = f.button :submit
51
+ ```
52
+
53
+ ### CSS
54
+
55
+ ```css
56
+ // Show the sort direction.
57
+ .sort_link {
58
+ &.asc:after {
59
+ content: " \25b2";
60
+ }
61
+ &.desc:after {
62
+ content: " \25bc";
63
+ }
64
+ }
65
+ ```
66
+
67
+ ## Copyright
68
+
69
+ Copyright (c) 2011 mashiro
70
+
data/Rakefile ADDED
@@ -0,0 +1,49 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ begin
6
+ Bundler.setup(:default, :development)
7
+ rescue Bundler::BundlerError => e
8
+ $stderr.puts e.message
9
+ $stderr.puts "Run `bundle install` to install missing gems"
10
+ exit e.status_code
11
+ end
12
+ require 'rake'
13
+
14
+ require 'jeweler'
15
+ Jeweler::Tasks.new do |gem|
16
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
17
+ gem.name = "kashiwamochi"
18
+ gem.homepage = "http://github.com/mashiro/kashiwamochi"
19
+ gem.license = "MIT"
20
+ gem.summary = %Q{Minimal searching extension for Rails 3}
21
+ gem.description = %Q{Minimal searchng extension for Rails 3}
22
+ gem.email = "mail@mashiro.org"
23
+ gem.authors = ["mashiro"]
24
+ # dependencies defined in Gemfile
25
+ end
26
+ Jeweler::RubygemsDotOrgTasks.new
27
+
28
+ require 'rspec/core'
29
+ require 'rspec/core/rake_task'
30
+ RSpec::Core::RakeTask.new(:spec) do |spec|
31
+ spec.pattern = FileList['spec/**/*_spec.rb']
32
+ end
33
+
34
+ RSpec::Core::RakeTask.new(:rcov) do |spec|
35
+ spec.pattern = 'spec/**/*_spec.rb'
36
+ spec.rcov = true
37
+ end
38
+
39
+ task :default => :spec
40
+
41
+ require 'rdoc/task'
42
+ Rake::RDocTask.new do |rdoc|
43
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
44
+
45
+ rdoc.rdoc_dir = 'rdoc'
46
+ rdoc.title = "kashiwamochi #{version}"
47
+ rdoc.rdoc_files.include('README*')
48
+ rdoc.rdoc_files.include('lib/**/*.rb')
49
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.2.0
@@ -0,0 +1,83 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
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 = "kashiwamochi"
8
+ s.version = "0.2.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["mashiro"]
12
+ s.date = "2011-11-04"
13
+ s.description = "Minimal searchng extension for Rails 3"
14
+ s.email = "mail@mashiro.org"
15
+ s.extra_rdoc_files = [
16
+ "LICENSE.txt",
17
+ "README.md"
18
+ ]
19
+ s.files = [
20
+ ".document",
21
+ ".rspec",
22
+ "Gemfile",
23
+ "LICENSE.txt",
24
+ "README.md",
25
+ "Rakefile",
26
+ "VERSION",
27
+ "kashiwamochi.gemspec",
28
+ "lib/kashiwamochi.rb",
29
+ "lib/kashiwamochi/action_controller.rb",
30
+ "lib/kashiwamochi/action_view.rb",
31
+ "lib/kashiwamochi/configuration.rb",
32
+ "lib/kashiwamochi/query.rb",
33
+ "lib/kashiwamochi/railtie.rb",
34
+ "lib/kashiwamochi/search.rb",
35
+ "lib/kashiwamochi/sort.rb",
36
+ "spec/fake_app.rb",
37
+ "spec/helpers/action_view_spec.rb",
38
+ "spec/kashiwamochi/action_controller_spec.rb",
39
+ "spec/kashiwamochi/config_spec.rb",
40
+ "spec/kashiwamochi/query_spec.rb",
41
+ "spec/kashiwamochi/sort_spec.rb",
42
+ "spec/spec_helper.rb"
43
+ ]
44
+ s.homepage = "http://github.com/mashiro/kashiwamochi"
45
+ s.licenses = ["MIT"]
46
+ s.require_paths = ["lib"]
47
+ s.rubygems_version = "1.8.10"
48
+ s.summary = "Minimal searching extension for Rails 3"
49
+
50
+ if s.respond_to? :specification_version then
51
+ s.specification_version = 3
52
+
53
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
54
+ s.add_runtime_dependency(%q<railties>, ["~> 3.0"])
55
+ s.add_development_dependency(%q<activerecord>, ["~> 3.0"])
56
+ s.add_development_dependency(%q<sqlite3>, ["~> 1.3.4"])
57
+ s.add_development_dependency(%q<rspec>, ["~> 2.7.0"])
58
+ s.add_development_dependency(%q<rspec-rails>, ["~> 2.7.0"])
59
+ s.add_development_dependency(%q<bundler>, ["~> 1.0.11"])
60
+ s.add_development_dependency(%q<jeweler>, ["~> 1.6.4"])
61
+ s.add_development_dependency(%q<rcov>, ["~> 0.9.11"])
62
+ else
63
+ s.add_dependency(%q<railties>, ["~> 3.0"])
64
+ s.add_dependency(%q<activerecord>, ["~> 3.0"])
65
+ s.add_dependency(%q<sqlite3>, ["~> 1.3.4"])
66
+ s.add_dependency(%q<rspec>, ["~> 2.7.0"])
67
+ s.add_dependency(%q<rspec-rails>, ["~> 2.7.0"])
68
+ s.add_dependency(%q<bundler>, ["~> 1.0.11"])
69
+ s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
70
+ s.add_dependency(%q<rcov>, ["~> 0.9.11"])
71
+ end
72
+ else
73
+ s.add_dependency(%q<railties>, ["~> 3.0"])
74
+ s.add_dependency(%q<activerecord>, ["~> 3.0"])
75
+ s.add_dependency(%q<sqlite3>, ["~> 1.3.4"])
76
+ s.add_dependency(%q<rspec>, ["~> 2.7.0"])
77
+ s.add_dependency(%q<rspec-rails>, ["~> 2.7.0"])
78
+ s.add_dependency(%q<bundler>, ["~> 1.0.11"])
79
+ s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
80
+ s.add_dependency(%q<rcov>, ["~> 0.9.11"])
81
+ end
82
+ end
83
+
@@ -0,0 +1,7 @@
1
+ require 'active_support'
2
+ require 'active_support/core_ext'
3
+ require 'kashiwamochi/configuration'
4
+ require 'kashiwamochi/search'
5
+ require 'kashiwamochi/sort'
6
+ require 'kashiwamochi/query'
7
+ require 'kashiwamochi/railtie' if defined?(Rails)
@@ -0,0 +1,15 @@
1
+ module Kashiwamochi
2
+ module ActionController
3
+ extend ActiveSupport::Concern
4
+
5
+ module InstanceMethods
6
+
7
+ def build_search_query!
8
+ q = params.delete(Kashiwamochi.config.search_key)
9
+ instance_variable_set("@#{Kashiwamochi.config.search_key}", Kashiwamochi.build(q))
10
+ end
11
+ alias_method :build_query!, :build_search_query! unless defined?(build_query!)
12
+
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,51 @@
1
+ module Kashiwamochi
2
+ module ActionView
3
+ extend ActiveSupport::Concern
4
+
5
+ module InstanceMethods
6
+
7
+ def search_form_for(query, *args, &block)
8
+ options = args.extract_options!
9
+
10
+ options[:url] ||= url_for
11
+ options[:as] ||= Kashiwamochi.config.search_key
12
+ options[:method] ||= :get
13
+ options[:html] ||= {}
14
+ options[:html].tap do |html|
15
+ html[:id] ||= "#{options[:as]}_#{Kashiwamochi.config.form_class}"
16
+ html[:class] = [
17
+ html[:class] || "#{options[:as]}_#{Kashiwamochi.config.form_class}",
18
+ "#{Kashiwamochi.config.form_class}"
19
+ ].compact.join(' ')
20
+ html[:method] ||= :get
21
+ end
22
+
23
+ form_method = options.delete(:form_method) || Kashiwamochi.config.form_method
24
+ send(form_method, query, *(args << options), &block)
25
+ end
26
+
27
+ def search_sort_link_to(query, attribute, *args)
28
+ options = args.extract_options!
29
+ html_options = options.delete(:html_options) || {}
30
+ default_order = options.delete(:default_order)
31
+
32
+ attr_name = attribute.to_s
33
+ sort = query.sort_params[attr_name] || Kashiwamochi::Sort.new(attr_name, default_order)
34
+
35
+ html_options[:class] = [
36
+ html_options[:class] || "#{attr_name}_#{Kashiwamochi.config.sort_link_class}",
37
+ Kashiwamochi.config.sort_link_class,
38
+ sort.dir.downcase
39
+ ].compact.join(' ')
40
+
41
+ query.sort_params[attr_name] = sort.toggle!
42
+ options[Kashiwamochi.config.search_key] = query.to_option
43
+
44
+ name = args.shift || attr_name
45
+ link_to(name, options, html_options)
46
+ end
47
+ alias_method :sort_link_to, :search_sort_link_to unless defined?(sort_link_to)
48
+
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,26 @@
1
+ module Kashiwamochi
2
+ def self.config
3
+ @config ||= Kashiwamochi::Configuration.new
4
+ end
5
+
6
+ def self.configure
7
+ yield config
8
+ end
9
+
10
+ class Configuration
11
+ include ActiveSupport::Configurable
12
+ config_accessor :search_key
13
+ config_accessor :sort_key
14
+ config_accessor :form_class
15
+ config_accessor :form_method
16
+ config_accessor :sort_link_class
17
+
18
+ configure do |config|
19
+ config.search_key = :q
20
+ config.sort_key = :s
21
+ config.form_class = :search
22
+ config.form_method = :form_for
23
+ config.sort_link_class = :sort_link
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,87 @@
1
+ require 'kashiwamochi/configuration'
2
+ require 'kashiwamochi/search'
3
+ require 'kashiwamochi/sort'
4
+
5
+ module Kashiwamochi
6
+
7
+ class Query
8
+ attr_accessor :search_params, :sort_params
9
+
10
+ def initialize(attributes)
11
+ @search_params = ActiveSupport::OrderedHash.new.with_indifferent_access
12
+ @sort_params = ActiveSupport::OrderedHash.new.with_indifferent_access
13
+
14
+ sort_key = Kashiwamochi.config.sort_key.to_s
15
+
16
+ attributes ||= {}
17
+ attributes.each do |key, value|
18
+ if key.to_s == sort_key
19
+ add_sort_param(key, value)
20
+ else
21
+ add_search_param(key, value)
22
+ end
23
+ end
24
+ end
25
+
26
+ def add_search_param(key, value)
27
+ unless @search_params.key? key
28
+ instance_eval <<-METHOD
29
+ def attribute_#{key}
30
+ search = @search_params["#{key}"]
31
+ search.value
32
+ end
33
+ alias original_#{key} #{key} if defined? #{key}
34
+ alias #{key} attribute_#{key}
35
+ METHOD
36
+ end
37
+
38
+ search = Search.new(key, value)
39
+ @search_params[search.key] = search
40
+ end
41
+
42
+ def add_sort_param(key, value)
43
+ values = value.is_a?(Array) ? value : [value]
44
+ values.each do |v|
45
+ sort = Sort.parse(v)
46
+ @sort_params[sort.key] = sort if sort.valid?
47
+ end
48
+ end
49
+
50
+ def method_missing(method_id, *args, &block)
51
+ method_name = method_id.to_s
52
+ if method_name =~ /(.+)=$/
53
+ super
54
+ else
55
+ nil
56
+ end
57
+ end
58
+
59
+ def sorts_query(*keys)
60
+ allowed_keys = keys.flatten.map(&:to_s).uniq
61
+ allowed_sorts = @sort_params.values.reject do |sort|
62
+ !allowed_keys.empty? && !allowed_keys.include?(sort.key.to_s)
63
+ end
64
+ allowed_sorts.empty? ? nil : allowed_sorts.map(&:to_query).join(', ')
65
+ end
66
+ alias_method :sorts, :sorts_query
67
+
68
+ def to_option
69
+ hash = Hash[*@search_params.values.map { |search| [search.key, search.value] }.flatten]
70
+ hash[Kashiwamochi.config.sort_key] = @sort_params.values.map(&:to_query)
71
+ hash
72
+ end
73
+
74
+ def inspect
75
+ "<Query search: #{@search_params}, sort: #{@sort_params}>"
76
+ end
77
+
78
+ def persisted?
79
+ false
80
+ end
81
+ end
82
+
83
+ def self.build(attributes)
84
+ Query.new attributes
85
+ end
86
+
87
+ end
@@ -0,0 +1,15 @@
1
+ require 'kashiwamochi/action_controller'
2
+ require 'kashiwamochi/action_view'
3
+
4
+ module Kashiwamochi
5
+ class Railtie < Rails::Railtie
6
+ initializer 'kashiwamochi.initialize' do
7
+ ActiveSupport.on_load(:action_controller) do
8
+ include Kashiwamochi::ActionController
9
+ end
10
+ ActiveSupport.on_load(:action_view) do
11
+ include Kashiwamochi::ActionView
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,16 @@
1
+ module Kashiwamochi
2
+
3
+ class Search
4
+ attr_reader :key, :value
5
+
6
+ def initialize(key, value)
7
+ @key = key
8
+ @value = value
9
+ end
10
+
11
+ def inspect
12
+ "#<Search #{key}: #{value}>"
13
+ end
14
+ end
15
+
16
+ end
@@ -0,0 +1,72 @@
1
+ require 'active_support/core_ext'
2
+
3
+ module Kashiwamochi
4
+
5
+ class Sort
6
+ DIRS = {:asc => 'asc', :desc => 'desc'}.freeze
7
+
8
+ def initialize(key, dir = nil)
9
+ self.key = key
10
+ self.dir = dir
11
+ end
12
+
13
+ def key
14
+ @key
15
+ end
16
+
17
+ def key=(value)
18
+ @key = Sort.sanitize(value)
19
+ end
20
+
21
+ def dir
22
+ @dir
23
+ end
24
+
25
+ def dir=(value)
26
+ @dir = Sort.sanitize_dir(value)
27
+ end
28
+
29
+ def toggle!
30
+ @dir = asc? ? DIRS[:desc] : DIRS[:asc]
31
+ self
32
+ end
33
+
34
+ def toggle
35
+ self.dup.toggle!
36
+ end
37
+
38
+ def asc?
39
+ @dir == DIRS[:asc]
40
+ end
41
+
42
+ def desc?
43
+ @dir == DIRS[:desc]
44
+ end
45
+
46
+ def valid?
47
+ @key.present?
48
+ end
49
+
50
+ def to_query
51
+ "#{key} #{dir}"
52
+ end
53
+
54
+ def inspect
55
+ "#<Sort #{key}: #{dir}>"
56
+ end
57
+
58
+ def self.sanitize(value)
59
+ value.to_s.strip
60
+ end
61
+
62
+ def self.sanitize_dir(dir)
63
+ sanitize(dir).downcase != DIRS[:desc] ? DIRS[:asc] : DIRS[:desc]
64
+ end
65
+
66
+ def self.parse(value)
67
+ key, dir = sanitize(value).split(/\s+/, 2)
68
+ new(key, dir)
69
+ end
70
+ end
71
+
72
+ end
data/spec/fake_app.rb ADDED
@@ -0,0 +1,27 @@
1
+ require 'active_record'
2
+ require 'action_controller/railtie'
3
+ require 'action_view/railtie'
4
+
5
+ ActiveRecord::Base.configurations = {'test' => {:adapter => 'sqlite3', :database => ':memory:'}}
6
+ ActiveRecord::Base.establish_connection('test')
7
+
8
+ app = Class.new(Rails::Application)
9
+ app.config.active_support.deprecation = :log
10
+ app.initialize!
11
+
12
+ app.routes.draw do
13
+ resources :users
14
+ end
15
+
16
+ class User < ActiveRecord::Base
17
+ has_many :statuses
18
+ end
19
+
20
+ class CreateTestTables < ActiveRecord::Migration
21
+ def self.up
22
+ create_table :users do |t|
23
+ t.string :name
24
+ t.integer :age
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,27 @@
1
+ require 'spec_helper'
2
+
3
+ describe Kashiwamochi::ActionView do
4
+ describe '#search_form_for' do
5
+ before do
6
+ @q = Kashiwamochi::Query.new(:name => 'test', :s => ['name desc'])
7
+ helper.search_form_for @q, :url => {:controller => 'users', :action => 'index'} do |f|
8
+ @f = f
9
+ end
10
+ end
11
+ subject { @f }
12
+
13
+ it { should be_an_instance_of ActionView::Helpers::FormBuilder }
14
+ end
15
+
16
+ describe '#search_sort_link_to' do
17
+ before do
18
+ @q = Kashiwamochi::Query.new(:name => 'test', :s => ['name desc'])
19
+ @link = helper.search_sort_link_to(@q, :name, 'User name', :controller => 'users', :action => 'index')
20
+ end
21
+ subject { @link }
22
+
23
+ it { should match %r(href="/users\?q%5Bname%5D=test&amp;q%5Bs%5D%5B%5D=name\+asc") }
24
+ it { should match %r(class="name_sort_link sort_link desc") }
25
+ it { should match %r(User name) }
26
+ end
27
+ end
@@ -0,0 +1,38 @@
1
+ require 'spec_helper'
2
+ require 'action_controller/railtie'
3
+
4
+ include Kashiwamochi::ActionController
5
+
6
+ describe Kashiwamochi::ActionController do
7
+ describe '#build_search_query' do
8
+ before do
9
+ instance_eval <<-EOS
10
+ def params
11
+ @params
12
+ end
13
+ EOS
14
+ end
15
+ subject do
16
+ build_search_query!
17
+ @q
18
+ end
19
+
20
+ context 'with query' do
21
+ before do
22
+ @params = {:q => {:name => 'foo'}}
23
+ end
24
+
25
+ it { should be_an_instance_of Kashiwamochi::Query }
26
+ its(:name) { should eq 'foo' }
27
+ end
28
+
29
+ context 'without query' do
30
+ before do
31
+ @params = {}
32
+ end
33
+
34
+ it { should be_an_instance_of Kashiwamochi::Query }
35
+ its(:name) { should be_nil }
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,27 @@
1
+ require 'spec_helper'
2
+
3
+ describe Kashiwamochi::Configuration do
4
+ subject { Kashiwamochi.config }
5
+
6
+ describe '#configure' do
7
+ before do
8
+ Kashiwamochi.configure do |config|
9
+ @config = config
10
+ end
11
+ end
12
+ subject { @config }
13
+
14
+ it { should be_an_instance_of Kashiwamochi::Configuration }
15
+ it { should eq Kashiwamochi.config }
16
+ end
17
+
18
+ describe 'config' do
19
+ context 'by default' do
20
+ its(:search_key) { should eq :q }
21
+ its(:sort_key) { should eq :s }
22
+ its(:form_class) { should eq :search }
23
+ its(:form_method) { should eq :form_for }
24
+ its(:sort_link_class) { should eq :sort_link }
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,83 @@
1
+ require 'spec_helper'
2
+
3
+ describe Kashiwamochi::Query do
4
+ describe '#initialize' do
5
+ context 'with {:foo => 1, :bar => 2, :to_s => 3, :s => ["name asc", " ", "created_at desc"]}' do
6
+ before { @q = Kashiwamochi::Query.new(:foo => 1, :bar => 2, :to_s => 3, :s => ["name asc", " ", "created_at desc"]) }
7
+ subject { @q }
8
+
9
+ describe 'length' do
10
+ context 'search_params' do
11
+ subject { @q.search_params }
12
+ its(:length) { should eq 3 }
13
+ end
14
+
15
+ context 'sort_params' do
16
+ subject { @q.sort_params }
17
+ its(:length) { should eq 2 }
18
+ end
19
+ end
20
+
21
+ context 'having' do
22
+ its(:foo) { should eq 1 }
23
+ its(:bar) { should eq 2 }
24
+ its(:to_s) { should eq 3 }
25
+ end
26
+
27
+ context 'missing' do
28
+ its(:buzz) { should be_nil }
29
+ end
30
+
31
+ context 'alias' do
32
+ its(:attribute_foo) { should eq 1 }
33
+ its(:original_to_s) { should be_an_instance_of String }
34
+ end
35
+
36
+ end
37
+ end
38
+
39
+ describe '#sorts_query' do
40
+ context 'build with {:s => ["name asc", " ", "created_at desc"]}' do
41
+ before { @q = Kashiwamochi::Query.new(:s => ["name asc", " ", "created_at desc"]) }
42
+ subject { @q.sorts_query(keys) }
43
+
44
+ context 'with empty' do
45
+ let(:keys) { [] }
46
+ it { should eq 'name asc, created_at desc' }
47
+ end
48
+
49
+ context 'with :name' do
50
+ let(:keys) { [:name] }
51
+ it { should eq 'name asc' }
52
+ end
53
+
54
+ context 'with :created_at' do
55
+ let(:keys) { [:created_at] }
56
+ it { should eq 'created_at desc' }
57
+ end
58
+
59
+ context 'with [:name, :created_at]' do
60
+ let(:keys) { [:name, :created_at] }
61
+ it { should eq 'name asc, created_at desc' }
62
+ end
63
+
64
+ context 'with [:foo, :bar]' do
65
+ let(:keys) { [:foo, :bar] }
66
+ it { should be_nil }
67
+ end
68
+ end
69
+ end
70
+
71
+ describe '#to_option' do
72
+ before { @q = Kashiwamochi::Query.new(:name => 'aira', :s => ["created_at desc"]) }
73
+ subject { @q.to_option }
74
+ it { should be_an_instance_of Hash }
75
+ it { should eq ({:name => 'aira', :s => ['created_at desc']}) }
76
+ end
77
+
78
+ describe '#build' do
79
+ subject { Kashiwamochi.build(:name => 'rizumu') }
80
+ it { should be_an_instance_of Kashiwamochi::Query }
81
+ its(:name) { should eq 'rizumu' }
82
+ end
83
+ end
@@ -0,0 +1,119 @@
1
+ require 'spec_helper'
2
+
3
+ describe Kashiwamochi::Sort do
4
+ before do
5
+ @asc = Kashiwamochi::Sort::DIRS[:asc]
6
+ @desc = Kashiwamochi::Sort::DIRS[:desc]
7
+ end
8
+
9
+ describe '#dir' do
10
+ before { @sort = Kashiwamochi::Sort.new('name', nil) }
11
+ subject { @sort }
12
+
13
+ context 'assign "asc"' do
14
+ before { @sort.dir = 'asc' }
15
+ its(:dir) { should eq @asc }
16
+ end
17
+
18
+ context 'assign "desc"' do
19
+ before { @sort.dir = 'desc' }
20
+ its(:dir) { should eq @desc }
21
+ end
22
+
23
+ context 'assign nil' do
24
+ before { @sort.dir = nil }
25
+ its(:dir) { should eq @asc }
26
+ end
27
+
28
+ context 'assign "test"' do
29
+ before { @sort.dir = 'test' }
30
+ its(:dir) { should eq @asc }
31
+ end
32
+ end
33
+
34
+ describe '#asc? / #desc?' do
35
+ before { @sort = Kashiwamochi::Sort.new('name', nil) }
36
+ subject { @sort }
37
+
38
+ context 'when ASC' do
39
+ before { @sort.dir = 'ASC' }
40
+ its(:asc?) { should be_true }
41
+ its(:desc?) { should be_false }
42
+ end
43
+
44
+ context 'when DESC' do
45
+ before { @sort.dir = 'DESC' }
46
+ its(:asc?) { should be_false }
47
+ its(:desc?) { should be_true }
48
+ end
49
+ end
50
+
51
+ describe '#toggle' do
52
+ before { @sort = Kashiwamochi::Sort.new('name', 'asc') }
53
+
54
+ context 'not toggled' do
55
+ subject { @sort }
56
+ its(:asc?) { should be_true }
57
+ its(:desc?) { should be_false }
58
+ its(:dir) { should eq @asc }
59
+ end
60
+
61
+ context 'one time' do
62
+ subject { @sort.toggle }
63
+ its(:asc?) { should be_false }
64
+ its(:desc?) { should be_true }
65
+ its(:dir) { should eq @desc }
66
+ end
67
+
68
+ context 'two times' do
69
+ subject { @sort.toggle.toggle }
70
+ its(:asc?) { should be_true }
71
+ its(:desc?) { should be_false }
72
+ its(:dir) { should eq @asc }
73
+ end
74
+
75
+ context 'three time' do
76
+ subject { @sort.toggle.toggle.toggle }
77
+ its(:asc?) { should be_false }
78
+ its(:desc?) { should be_true }
79
+ its(:dir) { should eq @desc }
80
+ end
81
+ end
82
+
83
+ describe '.parse' do
84
+ context "with 'name asc'" do
85
+ subject { Kashiwamochi::Sort.parse('name asc') }
86
+ its(:key) { should eq 'name' }
87
+ its(:dir) { should eq @asc }
88
+ it { should be_valid }
89
+ end
90
+
91
+ context "with ' name asc '" do
92
+ subject { Kashiwamochi::Sort.parse(' name asc ') }
93
+ its(:key) { should eq 'name' }
94
+ its(:dir) { should eq @asc }
95
+ it { should be_valid }
96
+ end
97
+
98
+ context "with ' aa bb cc dd '" do
99
+ subject { Kashiwamochi::Sort.parse(' aa bb cc dd ') }
100
+ its(:key) { should eq 'aa' }
101
+ its(:dir) { should eq @asc }
102
+ it { should be_valid }
103
+ end
104
+
105
+ context "with nil" do
106
+ subject { Kashiwamochi::Sort.parse(nil) }
107
+ its(:key) { should be_empty }
108
+ its(:dir) { should eq @asc }
109
+ it { should_not be_valid }
110
+ end
111
+
112
+ context "with ''" do
113
+ subject { Kashiwamochi::Sort.parse('') }
114
+ its(:key) { should be_empty }
115
+ its(:dir) { should eq @asc }
116
+ it { should_not be_valid }
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,18 @@
1
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
3
+ require 'rails'
4
+ require 'kashiwamochi'
5
+ require 'rspec'
6
+
7
+ require File.join(File.dirname(__FILE__), 'fake_app')
8
+ require 'rspec/rails'
9
+
10
+ # Requires supporting files with custom matchers and macros, etc,
11
+ # in ./support/ and its subdirectories.
12
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
13
+
14
+ RSpec.configure do |config|
15
+ config.before(:suite) do
16
+ CreateTestTables.up
17
+ end
18
+ end
metadata ADDED
@@ -0,0 +1,161 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: kashiwamochi
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - mashiro
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-11-04 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: railties
16
+ requirement: &24760700 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: '3.0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *24760700
25
+ - !ruby/object:Gem::Dependency
26
+ name: activerecord
27
+ requirement: &24760060 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ~>
31
+ - !ruby/object:Gem::Version
32
+ version: '3.0'
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: *24760060
36
+ - !ruby/object:Gem::Dependency
37
+ name: sqlite3
38
+ requirement: &24759420 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ~>
42
+ - !ruby/object:Gem::Version
43
+ version: 1.3.4
44
+ type: :development
45
+ prerelease: false
46
+ version_requirements: *24759420
47
+ - !ruby/object:Gem::Dependency
48
+ name: rspec
49
+ requirement: &24758800 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: 2.7.0
55
+ type: :development
56
+ prerelease: false
57
+ version_requirements: *24758800
58
+ - !ruby/object:Gem::Dependency
59
+ name: rspec-rails
60
+ requirement: &24747280 !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ~>
64
+ - !ruby/object:Gem::Version
65
+ version: 2.7.0
66
+ type: :development
67
+ prerelease: false
68
+ version_requirements: *24747280
69
+ - !ruby/object:Gem::Dependency
70
+ name: bundler
71
+ requirement: &24746680 !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ~>
75
+ - !ruby/object:Gem::Version
76
+ version: 1.0.11
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: *24746680
80
+ - !ruby/object:Gem::Dependency
81
+ name: jeweler
82
+ requirement: &24746120 !ruby/object:Gem::Requirement
83
+ none: false
84
+ requirements:
85
+ - - ~>
86
+ - !ruby/object:Gem::Version
87
+ version: 1.6.4
88
+ type: :development
89
+ prerelease: false
90
+ version_requirements: *24746120
91
+ - !ruby/object:Gem::Dependency
92
+ name: rcov
93
+ requirement: &24745520 !ruby/object:Gem::Requirement
94
+ none: false
95
+ requirements:
96
+ - - ~>
97
+ - !ruby/object:Gem::Version
98
+ version: 0.9.11
99
+ type: :development
100
+ prerelease: false
101
+ version_requirements: *24745520
102
+ description: Minimal searchng extension for Rails 3
103
+ email: mail@mashiro.org
104
+ executables: []
105
+ extensions: []
106
+ extra_rdoc_files:
107
+ - LICENSE.txt
108
+ - README.md
109
+ files:
110
+ - .document
111
+ - .rspec
112
+ - Gemfile
113
+ - LICENSE.txt
114
+ - README.md
115
+ - Rakefile
116
+ - VERSION
117
+ - kashiwamochi.gemspec
118
+ - lib/kashiwamochi.rb
119
+ - lib/kashiwamochi/action_controller.rb
120
+ - lib/kashiwamochi/action_view.rb
121
+ - lib/kashiwamochi/configuration.rb
122
+ - lib/kashiwamochi/query.rb
123
+ - lib/kashiwamochi/railtie.rb
124
+ - lib/kashiwamochi/search.rb
125
+ - lib/kashiwamochi/sort.rb
126
+ - spec/fake_app.rb
127
+ - spec/helpers/action_view_spec.rb
128
+ - spec/kashiwamochi/action_controller_spec.rb
129
+ - spec/kashiwamochi/config_spec.rb
130
+ - spec/kashiwamochi/query_spec.rb
131
+ - spec/kashiwamochi/sort_spec.rb
132
+ - spec/spec_helper.rb
133
+ homepage: http://github.com/mashiro/kashiwamochi
134
+ licenses:
135
+ - MIT
136
+ post_install_message:
137
+ rdoc_options: []
138
+ require_paths:
139
+ - lib
140
+ required_ruby_version: !ruby/object:Gem::Requirement
141
+ none: false
142
+ requirements:
143
+ - - ! '>='
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ segments:
147
+ - 0
148
+ hash: 3086285395406666836
149
+ required_rubygems_version: !ruby/object:Gem::Requirement
150
+ none: false
151
+ requirements:
152
+ - - ! '>='
153
+ - !ruby/object:Gem::Version
154
+ version: '0'
155
+ requirements: []
156
+ rubyforge_project:
157
+ rubygems_version: 1.8.10
158
+ signing_key:
159
+ specification_version: 3
160
+ summary: Minimal searching extension for Rails 3
161
+ test_files: []