kashiwamochi 0.2.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
+ 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: []