datagrid 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -17,7 +17,8 @@ group :development do
17
17
  gem "bundler", "~> 1.0.0"
18
18
  gem "jeweler", "~> 1.6.0"
19
19
  gem "rcov", ">= 0"
20
- gem "ruby-debug"
20
+ gem "ruby-debug", :platform => "mri_18"
21
+ #gem "ruby-debug19", :platform => "mri_19"
21
22
  gem "sqlite3-ruby"
22
23
  gem "fastercsv"
23
24
  gem "nokogiri"
@@ -41,9 +41,9 @@ class SimpleReport
41
41
  filter(:category, :enum, :select => ["first", "second"])
42
42
  filter(:disabled, :eboolean)
43
43
  filter(:confirmed, :boolean)
44
- filter(:group_id, :multiple => true)
44
+ filter(:group_id, :integer, :multiple => true)
45
45
  integer_range_filter(:logins_count, :integer)
46
- filter(:group_name, :header => "Group") do |value|
46
+ filter(:group_name, :string, :header => "Group") do |value|
47
47
  self.joins(:group).where(:groups => {:name => value})
48
48
  end
49
49
 
@@ -66,7 +66,14 @@ end
66
66
  Basic grid api:
67
67
 
68
68
  ``` ruby
69
- report = SimpleReport.new(:order => "group", :descending => true, :group_id => [1,2], :from_logins_count => 1, :category => "first")
69
+ report = SimpleReport.new(
70
+ :order => "group",
71
+ :descending => true,
72
+ :group_id => [1,2], :from_logins_count => 1,
73
+ :category => "first",
74
+ :order => :group,
75
+ :descending => true
76
+ )
70
77
 
71
78
  report.assets # => Array of User instances:
72
79
  # SELECT * FROM users WHERE users.group_id in (1,2) AND users.logins_count >= 1 AND users.category = 'first' ORDER BY groups.name DESC
@@ -85,7 +92,13 @@ report.to_csv # => Yes, it is
85
92
  ### Scope
86
93
 
87
94
  Default scope of objects to filter and display.
88
- In common case it is `ActiveRecord::Base` subclass with some generic scopes like in example above.
95
+ In common case it is `ActiveRecord::Base` subclass with some generic scopes like in example above:
96
+
97
+ ``` ruby
98
+ scope do
99
+ User.includes(:group)
100
+ end
101
+ ```
89
102
 
90
103
  ### Filters
91
104
 
@@ -104,16 +117,18 @@ Datagrid supports different type of filters including:
104
117
  * boolean
105
118
  * eboolean - the select of "yes", "no" and any
106
119
  * enum
120
+ * string
107
121
 
108
- Read more about filters here:
122
+ [More about filters](https://github.com/bogdan/datagrid/wiki/Filters)
109
123
 
110
124
 
111
125
  ### Columns
112
126
 
113
127
  Each column is represented by name and code block to calculate the value.
114
- Grids are sortable by it's columns. Ordering is controller by `#order` and `#descending` attributes.
128
+ Some formatting options are also available.
129
+ Each column is sortable.
115
130
 
116
- More information about columns here:
131
+ [More about columns](https://github.com/bogdan/datagrid/wiki/Columns)
117
132
 
118
133
 
119
134
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.0
1
+ 0.3.0
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{datagrid}
8
- s.version = "0.2.0"
8
+ s.version = "0.3.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Bogdan Gusiev"]
12
- s.date = %q{2011-06-22}
12
+ s.date = %q{2011-07-01}
13
13
  s.description = %q{This allows you to easily build datagrid aka data tables with sortable columns and filters}
14
14
  s.email = %q{agresso@gmail.com}
15
15
  s.extra_rdoc_files = [
@@ -39,6 +39,7 @@ Gem::Specification.new do |s|
39
39
  "lib/datagrid/filters/enum_filter.rb",
40
40
  "lib/datagrid/filters/filter_eval.rb",
41
41
  "lib/datagrid/filters/integer_filter.rb",
42
+ "lib/datagrid/filters/string_filter.rb",
42
43
  "lib/datagrid/form_builder.rb",
43
44
  "lib/datagrid/helper.rb",
44
45
  "lib/datagrid/rspec.rb",
@@ -56,11 +57,10 @@ Gem::Specification.new do |s|
56
57
  s.homepage = %q{http://github.com/bogdan/datagrid}
57
58
  s.licenses = ["MIT"]
58
59
  s.require_paths = ["lib"]
59
- s.rubygems_version = %q{1.3.7}
60
+ s.rubygems_version = %q{1.6.2}
60
61
  s.summary = %q{Ruby gem to create datagrids}
61
62
 
62
63
  if s.respond_to? :specification_version then
63
- current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
64
64
  s.specification_version = 3
65
65
 
66
66
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
@@ -29,6 +29,7 @@ module Datagrid
29
29
  end # InstanceMethods
30
30
 
31
31
  class ConfigurationError < StandardError; end
32
+ class ArgumentError < StandardError; end
32
33
 
33
34
 
34
35
  end
@@ -14,7 +14,24 @@ module Datagrid
14
14
 
15
15
  include Datagrid::Core
16
16
 
17
- datagrid_attribute :order
17
+ datagrid_attribute :order do |value|
18
+ unless value.blank?
19
+ value = value.to_sym
20
+ column = column_by_name(value)
21
+ unless column
22
+ order_unsupported(value, "no column #{value} in #{self.class}")
23
+ end
24
+ unless column.order
25
+ order_unsupported(
26
+ name, "#{self.class}##{name} don't support order"
27
+ )
28
+ end
29
+ value
30
+ else
31
+ nil
32
+ end
33
+
34
+ end
18
35
  datagrid_attribute :descending do |value|
19
36
  Datagrid::Utils.booleanize(value)
20
37
  end
@@ -30,69 +47,6 @@ module Datagrid
30
47
  @columns ||= []
31
48
  end
32
49
 
33
- # Defines column that will be used to display data.
34
- #
35
- # Example:
36
- #
37
- # class UserGrid
38
- # include Datagrid
39
- #
40
- # scope do
41
- # User.order("users.created_at desc").includes(:group)
42
- # end
43
- #
44
- # column(:name)
45
- # column(:group, :order => "groups.name")
46
- # self.group.name
47
- # end
48
- # column(:active, :header => "Activated") do |user|
49
- # !user.disabled
50
- # end
51
- #
52
- # end
53
- #
54
- # Each column will be used to generate data.
55
- # In order to create grid that display all users:
56
- #
57
- # grid = UserGrid.new
58
- # grid.rows
59
- # grid.header # => ["Group", "Name", "Disabled"]
60
- # grid.rows # => [
61
- # # ["Steve", "Spammers", true],
62
- # # [ "John", "Spoilers", true],
63
- # # ["Berry", "Good people", false]
64
- # # ]
65
- # grid.data # => Header & Rows
66
- #
67
- # = Column value
68
- #
69
- # Column value can be defined by passing a block to <tt>#column</tt> method.
70
- # If no block given column it is generated automatically by sending column name method to model.
71
- # The block could have zero arguments(<tt>instance_eval</tt>) or one argument that is model object.
72
- #
73
- # = Column options
74
- #
75
- # The following options can be passed to column definition:
76
- #
77
- # * <tt>:order</tt> - an order SQL that should be used to sort by this column.
78
- # Default: report column name if there is database column with this name.
79
- # * <tt>:order_desc</tt> - descending order expression from this column. Default: "#{order} desc".
80
- #
81
- # TODO: frontend options description
82
- #
83
- # = Columns order
84
- #
85
- # Each column supports <tt>:order</tt> option that is used to specify SQL to sort data by the given column.
86
- # In order to specify order the following attributes are used:
87
- #
88
- # * <tt>:order</tt> - column name to sort with as <tt>Symbol</tt>. Default: nil.
89
- # * <tt>:descending</tt> - if true descending suffix is added to specified order. Default: false.
90
- #
91
- # Example:
92
- #
93
- # grid = UserGrid.new(:order => :group, :descending => true)
94
- # grid.assets # => Return assets ordered by :group column descending
95
- #
96
50
  def column(name, options = {}, &block)
97
51
  check_scope_defined!("Scope should be defined before columns")
98
52
  block ||= lambda do |model|
@@ -101,25 +55,36 @@ module Datagrid
101
55
  self.columns << Datagrid::Columns::Column.new(self, name, options, &block)
102
56
  end
103
57
 
58
+ def order_unsupported(name, reason)
59
+ raise Datagrid::OrderUnsupported, "Can not sort #{self.inspect} by ##{name}: #{reason}"
60
+ end
104
61
 
62
+ def column_by_name(name)
63
+ self.columns.find do |col|
64
+ col.name.to_sym == name.to_sym
65
+ end
66
+ end
105
67
  end # ClassMethods
106
68
 
107
69
  module InstanceMethods
108
70
 
71
+ # Returns <tt>Array</tt> of human readable column names. See also "Localization" section
109
72
  def header
110
73
  self.class.columns.map(&:header)
111
74
  end
112
75
 
76
+ # Returns <tt>Array</tt> column values for given asset
113
77
  def row_for(asset)
114
78
  self.class.columns.map do |column|
115
- column.value(asset)
79
+ column.value(asset, self)
116
80
  end
117
81
  end
118
82
 
83
+ # Returns <tt>Hash</tt> where keys are column names and values are column values for the given asset
119
84
  def hash_for(asset)
120
85
  result = {}
121
86
  self.class.columns.each do |column|
122
- result[column.name] = column.value(asset)
87
+ result[column.name] = column.value(asset, self)
123
88
  end
124
89
  result
125
90
  end
@@ -144,15 +109,20 @@ module Datagrid
144
109
  result = super
145
110
  if self.order
146
111
  column = column_by_name(self.order)
147
- raise Datagrid::OrderUnsupported, "Can not sort #{self.inspect} by #{name.inspect}" unless column
148
112
  result = result.order(self.descending ? column.desc_order : column.order)
149
113
  end
150
114
  result
151
115
  end
152
116
 
153
117
  def to_csv(options = {})
154
- require "fastercsv"
155
- FasterCSV.generate(
118
+ klass = if RUBY_VERSION >= "1.9"
119
+ require 'csv'
120
+ CSV
121
+ else
122
+ require "fastercsv"
123
+ FasterCSV
124
+ end
125
+ klass.generate(
156
126
  {:headers => self.header, :write_headers => true}.merge(options)
157
127
  ) do |csv|
158
128
  self.rows.each do |row|
@@ -166,9 +136,7 @@ module Datagrid
166
136
  end
167
137
 
168
138
  def column_by_name(name)
169
- self.columns.find do |col|
170
- col.name.to_sym == name.to_sym
171
- end
139
+ self.class.column_by_name(name)
172
140
  end
173
141
 
174
142
  end # InstanceMethods
@@ -10,15 +10,17 @@ class Datagrid::Columns::Column
10
10
  self.block = block
11
11
  end
12
12
 
13
- def value(object)
14
- value_for(object)
13
+ def value(model, report)
14
+ value_for(model, report)
15
15
  end
16
16
 
17
- def value_for(object)
17
+ def value_for(model, report)
18
18
  if self.block.arity == 1
19
- self.block.call(object)
19
+ self.block.call(model)
20
+ elsif self.block.arity == 2
21
+ self.block.call(model, report)
20
22
  else
21
- object.instance_eval(&self.block)
23
+ model.instance_eval(&self.block)
22
24
  end
23
25
  end
24
26
 
@@ -32,7 +34,7 @@ class Datagrid::Columns::Column
32
34
 
33
35
  def header
34
36
  self.options[:header] ||
35
- I18n.translate(self.name, :scope => "reports.#{self.grid}.columns", :default => self.name.to_s.humanize )
37
+ I18n.translate(self.name, :scope => "reports.#{self.grid.param_name}.columns", :default => self.name.to_s.humanize )
36
38
  end
37
39
 
38
40
  def order
@@ -10,10 +10,11 @@ module Datagrid
10
10
  require "datagrid/filters/filter_eval"
11
11
  require "datagrid/filters/integer_filter"
12
12
  require "datagrid/filters/composite_filters"
13
+ require "datagrid/filters/string_filter"
13
14
 
14
15
  FILTER_TYPES = {
15
16
  :date => Filters::DateFilter,
16
- :string => Filters::DefaultFilter,
17
+ :string => Filters::StringFilter,
17
18
  :default => Filters::DefaultFilter,
18
19
  :eboolean => Filters::BooleanEnumFilter ,
19
20
  :boolean => Filters::BooleanFilter ,
@@ -45,62 +46,9 @@ module Datagrid
45
46
  end
46
47
 
47
48
 
48
- # Defines the accessible attribute that is used to filter
49
- # scope by the specified value with specified code.
50
- #
51
- # Example:
52
- #
53
- # class UserGrid
54
- # include Datagrid
55
- #
56
- # scope do
57
- # User.order("users.created_at desc")
58
- # end
59
- #
60
- # filter(:name)
61
- # filter(:posts_count, :integer) do |value|
62
- # self.where(["posts_count >= ?", value])
63
- # end
64
- #
65
- # end
66
- #
67
- # Each filter becomes grid attribute.
68
- # In order to create grid that display all users with name 'John' that have more than zero posts:
69
- #
70
- # grid = UserGrid.new(:posts_count => 1, :name => "John")
71
- # grid.assets # SELECT * FROM users WHERE users.posts_count > 1 AND name = 'John'
72
- #
73
- # Important! Take care about non-breaking the filter chain and force objects loading in filter.
74
- # The filter block should always return a <tt>ActiveRecord::Scope</tt> rather than <tt>Array</tt>
75
- #
76
- # = Default filter block
77
- #
78
- # If no block given filter is generated automatically as simple select by filter name from scope.
79
- #
80
- # = Filter types
81
- #
82
- # Filter does types conversion automatically.
83
- # The following filter types are supported:
84
- #
85
- # * <tt>:default</tt> (default) - leave value as is
86
- # * <tt>:date</tt> - converts value to date using date parser
87
- # * <tt>:enum</tt> - designed to be collection select. Additional options for easy form generation:
88
- # * <tt>:select</tt> (required) - collection of values to match against.
89
- # * <tt>:boolean</tt> - converts value to true or false depending on whether it looks truly or not
90
- # * <tt>:integer</tt> - converts given value to integer.
91
- # * <tt>:eboolean</tt> - subtype of enum filter that provides select of "Yes", "No" and "Any". Could be useful.
92
- #
93
- # = Default filter options
94
- #
95
- # Options that could be passed to any filter type:
96
- #
97
- # * <tt>:header</tt> - human readable name of the filter. Default: generated from the filter name.
98
- # * <tt>:default</tt> - default value of the filter. Default: nil.
99
- # * <tt>:multiple</tt> - if true multiple values can be assigned to this filter. Default: false.
100
- # * <tt>:allow_nil</tt> - determines if filter should be called if filter value is nil. Default: false.
101
- # * <tt>:allow_blank</tt> - determines if filter should be called if filter value is #blank?. Default: false.
102
- #
103
- def filter(attribute, type = :string, options = {}, &block)
49
+ def filter(attribute, *args, &block)
50
+ options = args.extract_options!
51
+ type = args.shift || :default
104
52
 
105
53
  klass = type.is_a?(Class) ? type : FILTER_TYPES[type]
106
54
  raise ConfigurationError, "filter class #{type.inspect} not found" unless klass
@@ -119,12 +67,8 @@ module Datagrid
119
67
  protected
120
68
  def default_filter(attribute)
121
69
  check_scope_defined!("Scope should be defined before filters")
122
- if self.scope.column_names.include?(attribute.to_s)
123
- lambda do |value|
124
- self.scoped(:conditions => {attribute => value})
125
- end
126
- else
127
- raise ConfigurationError, "Not able to generate default filter. No column '#{attribute}' in #{self.scope.table_name}."
70
+ lambda do |value|
71
+ self.scoped(:conditions => {attribute => value})
128
72
  end
129
73
  end
130
74
 
@@ -22,6 +22,9 @@ class Datagrid::Filters::BaseFilter
22
22
  end
23
23
 
24
24
  def format_values(value)
25
+ if !self.multiple && value.is_a?(Array)
26
+ raise Datagrid::ArgumentError, "#{grid.class}.#{name} filter can not accept Array argument. Use :multiple option."
27
+ end
25
28
  values = Array(value)
26
29
  values.map! do |value|
27
30
  self.format(value)
@@ -31,7 +34,7 @@ class Datagrid::Filters::BaseFilter
31
34
 
32
35
  def header
33
36
  options[:header] ||
34
- I18n.translate(self.name, :scope => "datagrid.#{grid.class.to_s.underscore.split("/").last}.filters", :default => self.name.to_s.humanize)
37
+ I18n.translate(self.name, :scope => "datagrid.#{grid.param_name}.filters", :default => self.name.to_s.humanize)
35
38
  end
36
39
 
37
40
  def default
@@ -5,7 +5,6 @@ class Datagrid::Filters::BooleanEnumFilter < Datagrid::Filters::EnumFilter
5
5
  VALUES = {YES => true, NO => false}
6
6
 
7
7
  def initialize(report, attribute, options = {}, &block)
8
- options[:allow_blank] = true unless options.has_key?(:allow_blank)
9
8
  options[:select] = VALUES.keys
10
9
  super(report, attribute, options, &block)
11
10
  end
@@ -0,0 +1,5 @@
1
+ class Datagrid::Filters::StringFilter < Datagrid::Filters::BaseFilter
2
+ def format(value)
3
+ value.to_s
4
+ end
5
+ end
@@ -36,11 +36,22 @@ module Datagrid
36
36
 
37
37
  def datagrid_enum_filter(attribute_or_filter, options = {})
38
38
  filter = get_filter(attribute_or_filter)
39
- select filter.name, filter.select || [], {:include_blank => filter.include_blank}, {:multiple => filter.multiple}.merge(options)
39
+ if !options.has_key?(:multiple) && filter.multiple
40
+ options[:multiple] = true
41
+ end
42
+ select filter.name, filter.select || [], {:include_blank => filter.include_blank}, options
40
43
  end
41
44
 
42
45
  def datagrid_integer_filter(attribute_or_filter, options = {})
43
- text_field get_attribute(attribute_or_filter), options
46
+ filter = get_filter(attribute_or_filter)
47
+ if filter.multiple && self.object[filter.name].blank?
48
+ options[:value] = ""
49
+ end
50
+ text_field filter.name, options
51
+ end
52
+
53
+ def datagrid_string_filter(attribute_or_filter, options = {})
54
+ datagrid_default_filter(attribute_or_filter, options)
44
55
  end
45
56
 
46
57
  def get_attribute(attribute_or_filter)
@@ -3,8 +3,8 @@ require "action_view"
3
3
  module Datagrid
4
4
  module Helper
5
5
 
6
- def datagrid_format_value(column, asset)
7
- value = column.value(asset)
6
+ def datagrid_format_value(report, column, asset)
7
+ value = column.value(asset, report)
8
8
  if column.options[:url]
9
9
  link_to(value, column.options[:url].call(asset))
10
10
  else
@@ -24,11 +24,10 @@ module Datagrid
24
24
  assets = report.assets
25
25
  paginate = options[:paginate]
26
26
  assets = assets.paginate(paginate) if paginate
27
- content = content_tag(:tr, datagrid_header(report, options)) + datagrid_rows(report.columns, assets, options)
27
+ content = content_tag(:tr, datagrid_header(report, options)) + datagrid_rows(report, assets, options)
28
28
  content_tag(:table, content, html)
29
29
  end
30
30
 
31
- protected
32
31
 
33
32
  def datagrid_header(grid, options = {})
34
33
  header = empty_string
@@ -43,12 +42,13 @@ module Datagrid
43
42
  header
44
43
  end
45
44
 
46
- def datagrid_rows(columns, assets, options)
45
+ def datagrid_rows(report, assets, options)
46
+ columns = report.columns
47
47
  result = assets.map do |asset|
48
48
  content = columns.map do |column|
49
- content_tag(:td, datagrid_format_value(column, asset))
49
+ content_tag(:td, datagrid_format_value(report, column, asset))
50
50
  end.join(empty_string)
51
- content_tag(:tr, _safe(content), :class => cycle("odd", "even"))
51
+ content_tag(:tr, _safe(content), :class => options[:cycle] && cycle(*options[:cycle]))
52
52
  end.join(empty_string)
53
53
  _safe(result)
54
54
  end
@@ -27,4 +27,39 @@ describe Datagrid::Columns do
27
27
  it "should support csv export" do
28
28
  subject.to_csv.should == "Group,Name\nPop,Star\n"
29
29
  end
30
+
31
+ it "should support columns with model and report arguments" do
32
+ report = test_report(:category => "foo") do
33
+ scope {Entry.order(:category)}
34
+ filter(:category) do |value|
35
+ where("category LIKE '%#{value}%'")
36
+ end
37
+
38
+ column(:exact_category) do |entry, report|
39
+ entry.category == report.category
40
+ end
41
+ end
42
+ Entry.create!(:category => "foo")
43
+ Entry.create!(:category => "foobar")
44
+ report.rows.first.first.should be_true
45
+ report.rows.last.first.should be_false
46
+ end
47
+
48
+
49
+ it "should raise error if ordered by not existing column" do
50
+ lambda {
51
+ test_report(:order => :hello)
52
+ }.should raise_error(Datagrid::OrderUnsupported)
53
+ end
54
+
55
+ it "should raise error if ordered by column without order" do
56
+ lambda {
57
+ test_report(:order => :category) do
58
+ filter(:category, :default, :order => false) do |value|
59
+ self
60
+ end
61
+ end
62
+ }.should raise_error(Datagrid::OrderUnsupported)
63
+ end
64
+
30
65
  end
@@ -8,5 +8,28 @@ describe Datagrid::Filters do
8
8
  filter(:created_at, :date, :default => proc { Date.today } )
9
9
  end.created_at.should == Date.today
10
10
  end
11
+
12
+ it "should not support array argument for not multiple filter" do
13
+ report = test_report do
14
+ scope {Entry}
15
+ filter(:group_id, :integer)
16
+ end
17
+ lambda {
18
+ report.group_id = [1,2]
19
+ }.should raise_error(Datagrid::ArgumentError)
20
+ end
21
+
22
+
23
+ it "should initialize report Scope table not exists" do
24
+ class ModelWithoutTable < ActiveRecord::Base; end
25
+ class TheReport
26
+ include Datagrid
27
+
28
+ scope {ModelWithoutTable}
29
+
30
+ filter(:name)
31
+ end
32
+
33
+ end
11
34
 
12
35
  end
@@ -36,7 +36,7 @@ describe Datagrid::FormBuilder do
36
36
  context "with enum filter type" do
37
37
  let(:_filter) { :category }
38
38
  it { should equal_to_dom(
39
- '<select class="category enum_filter" id="report_category" name="report[category][]"><option value=""></option>
39
+ '<select class="category enum_filter" id="report_category" name="report[category]"><option value=""></option>
40
40
  <option value="first">first</option>
41
41
  <option value="second">second</option></select>'
42
42
  )}
@@ -45,7 +45,7 @@ describe Datagrid::FormBuilder do
45
45
  grid.category = "first"
46
46
  end
47
47
  it { should equal_to_dom(
48
- '<select class="category enum_filter" id="report_category" name="report[category][]"><option value=""></option>
48
+ '<select class="category enum_filter" id="report_category" name="report[category]"><option value=""></option>
49
49
  <option value="first" selected="true">first</option>
50
50
  <option value="second">second</option></select>'
51
51
  )}
@@ -55,11 +55,39 @@ describe Datagrid::FormBuilder do
55
55
  context "with eboolean filter type" do
56
56
  let(:_filter) { :disabled }
57
57
  it { should equal_to_dom(
58
- '<select class="disabled boolean_enum_filter" id="report_disabled" name="report[disabled][]"><option value=""></option>
59
- <option value="NO">NO</option>
60
- <option value="YES">YES</option></select>'
58
+ '<select class="disabled boolean_enum_filter" id="report_disabled" name="report[disabled]"><option value=""></option>
59
+ <option value="YES">YES</option>
60
+ <option value="NO">NO</option></select>'
61
61
  )}
62
62
  end
63
+ context "with string filter" do
64
+ let(:grid) do
65
+ test_report do
66
+ scope {Entry}
67
+ filter(:name, :string)
68
+ end
69
+ end
70
+
71
+ let(:_filter) { :name }
72
+
73
+ it {should equal_to_dom('<input class="name string_filter" id="report_name" name="report[name]" size="30" type="text">')}
74
+ end
75
+
76
+ context "with non multiple filter" do
77
+ let(:grid) do
78
+ test_report do
79
+ scope {Entry}
80
+ filter(
81
+ :name, :enum,
82
+ :include_blank => false,
83
+ :multiple => false,
84
+ :select => []
85
+ )
86
+ end
87
+ end
88
+ let(:_filter) { :name }
89
+ it {should equal_to_dom('<select class="name enum_filter" id="report_name" name="report[name]"></select>')}
90
+ end
63
91
  end
64
92
 
65
93
  describe ".datagrid_label" do
@@ -69,6 +97,9 @@ describe Datagrid::FormBuilder do
69
97
  )
70
98
  end
71
99
  end
100
+
101
+
102
+
72
103
  end
73
104
 
74
105
 
@@ -34,12 +34,21 @@ describe Datagrid::Helper do
34
34
  </th>
35
35
  </tr>
36
36
 
37
- <tr class="odd">
37
+ <tr>
38
38
  <td>Pop</td>
39
39
  <td>Star</td>
40
40
  </tr>
41
41
  </table>')
42
42
  end
43
+
44
+ it "should support cycle option" do
45
+ subject.datagrid_rows(grid, [entry], :cycle => ["odd", "even"]).should equal_to_dom(
46
+ '<tr class="odd">
47
+ <td>Pop</td>
48
+ <td>Star</td>
49
+ </tr>'
50
+ )
51
+ end
43
52
  end
44
53
 
45
54
 
@@ -2,9 +2,9 @@ require 'spec_helper'
2
2
  require "datagrid/rspec"
3
3
 
4
4
 
5
- describe Datagrid do
5
+ describe SimpleReport do
6
6
 
7
- #it_should_behave_like 'Datagrid'
7
+ it_should_behave_like 'Datagrid'
8
8
 
9
9
  let(:group) { Group.create!(:name => "Pop") }
10
10
 
@@ -10,11 +10,14 @@ end
10
10
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
11
11
  $LOAD_PATH.unshift(File.dirname(__FILE__))
12
12
 
13
- require 'rspec'
14
13
  require "active_record"
15
14
  require "will_paginate"
16
15
  require 'datagrid'
17
- require 'ruby-debug'
16
+ begin
17
+ #require 'ruby-debug'
18
+ rescue
19
+ end
20
+ require 'rspec'
18
21
 
19
22
 
20
23
  RSpec.configure do |config|
@@ -16,7 +16,7 @@ class IncludeDom
16
16
 
17
17
  def matches?(text)
18
18
  @matcher = Nokogiri::HTML::DocumentFragment.parse(text).to_s
19
- @matcher.include?(@expectation)
19
+ @matcher == @expectation
20
20
  end
21
21
 
22
22
  def failure_message
@@ -17,8 +17,8 @@ ActiveRecord::Schema.define(:version => 1) do
17
17
  t.integer :group_id
18
18
  t.string :name
19
19
  t.string :category
20
- t.boolean :disabled, :null => false, :default => nil
21
- t.boolean :confirmed, :null => false, :default => nil
20
+ t.boolean :disabled, :null => false, :default => false
21
+ t.boolean :confirmed, :null => false, :default => false
22
22
  t.timestamps
23
23
  end
24
24
 
@@ -1,12 +1,14 @@
1
1
 
2
2
 
3
- def test_report(&block)
3
+ def test_report(attributes = {}, &block)
4
4
  klass = Class.new
5
5
  klass.class_eval do
6
6
  include Datagrid
7
7
  end
8
- klass.class_eval(&block)
9
- klass.new
8
+ if block
9
+ klass.class_eval(&block)
10
+ end
11
+ klass.new(attributes)
10
12
  end
11
13
 
12
14
  class SimpleReport
metadata CHANGED
@@ -1,13 +1,8 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: datagrid
3
3
  version: !ruby/object:Gem::Version
4
- hash: 23
5
- prerelease: false
6
- segments:
7
- - 0
8
- - 2
9
- - 0
10
- version: 0.2.0
4
+ prerelease:
5
+ version: 0.3.0
11
6
  platform: ruby
12
7
  authors:
13
8
  - Bogdan Gusiev
@@ -15,187 +10,141 @@ autorequire:
15
10
  bindir: bin
16
11
  cert_chain: []
17
12
 
18
- date: 2011-06-22 00:00:00 +03:00
13
+ date: 2011-07-01 00:00:00 +03:00
19
14
  default_executable:
20
15
  dependencies:
21
16
  - !ruby/object:Gem::Dependency
22
- version_requirements: &id001 !ruby/object:Gem::Requirement
17
+ name: rails
18
+ requirement: &id001 !ruby/object:Gem::Requirement
23
19
  none: false
24
20
  requirements:
25
21
  - - ">="
26
22
  - !ruby/object:Gem::Version
27
- hash: 3
28
- segments:
29
- - 0
30
23
  version: "0"
31
- requirement: *id001
32
24
  type: :runtime
33
- name: rails
34
25
  prerelease: false
26
+ version_requirements: *id001
35
27
  - !ruby/object:Gem::Dependency
36
- version_requirements: &id002 !ruby/object:Gem::Requirement
28
+ name: rake
29
+ requirement: &id002 !ruby/object:Gem::Requirement
37
30
  none: false
38
31
  requirements:
39
32
  - - "="
40
33
  - !ruby/object:Gem::Version
41
- hash: 49
42
- segments:
43
- - 0
44
- - 8
45
- - 7
46
34
  version: 0.8.7
47
- requirement: *id002
48
35
  type: :development
49
- name: rake
50
36
  prerelease: false
37
+ version_requirements: *id002
51
38
  - !ruby/object:Gem::Dependency
52
- version_requirements: &id003 !ruby/object:Gem::Requirement
39
+ name: mocha
40
+ requirement: &id003 !ruby/object:Gem::Requirement
53
41
  none: false
54
42
  requirements:
55
43
  - - ">="
56
44
  - !ruby/object:Gem::Version
57
- hash: 3
58
- segments:
59
- - 0
60
45
  version: "0"
61
- requirement: *id003
62
46
  type: :development
63
- name: mocha
64
47
  prerelease: false
48
+ version_requirements: *id003
65
49
  - !ruby/object:Gem::Dependency
66
- version_requirements: &id004 !ruby/object:Gem::Requirement
50
+ name: rspec
51
+ requirement: &id004 !ruby/object:Gem::Requirement
67
52
  none: false
68
53
  requirements:
69
54
  - - "="
70
55
  - !ruby/object:Gem::Version
71
- hash: 23
72
- segments:
73
- - 2
74
- - 6
75
- - 0
76
56
  version: 2.6.0
77
- requirement: *id004
78
57
  type: :development
79
- name: rspec
80
58
  prerelease: false
59
+ version_requirements: *id004
81
60
  - !ruby/object:Gem::Dependency
82
- version_requirements: &id005 !ruby/object:Gem::Requirement
61
+ name: bundler
62
+ requirement: &id005 !ruby/object:Gem::Requirement
83
63
  none: false
84
64
  requirements:
85
65
  - - ~>
86
66
  - !ruby/object:Gem::Version
87
- hash: 23
88
- segments:
89
- - 1
90
- - 0
91
- - 0
92
67
  version: 1.0.0
93
- requirement: *id005
94
68
  type: :development
95
- name: bundler
96
69
  prerelease: false
70
+ version_requirements: *id005
97
71
  - !ruby/object:Gem::Dependency
98
- version_requirements: &id006 !ruby/object:Gem::Requirement
72
+ name: jeweler
73
+ requirement: &id006 !ruby/object:Gem::Requirement
99
74
  none: false
100
75
  requirements:
101
76
  - - ~>
102
77
  - !ruby/object:Gem::Version
103
- hash: 15
104
- segments:
105
- - 1
106
- - 6
107
- - 0
108
78
  version: 1.6.0
109
- requirement: *id006
110
79
  type: :development
111
- name: jeweler
112
80
  prerelease: false
81
+ version_requirements: *id006
113
82
  - !ruby/object:Gem::Dependency
114
- version_requirements: &id007 !ruby/object:Gem::Requirement
83
+ name: rcov
84
+ requirement: &id007 !ruby/object:Gem::Requirement
115
85
  none: false
116
86
  requirements:
117
87
  - - ">="
118
88
  - !ruby/object:Gem::Version
119
- hash: 3
120
- segments:
121
- - 0
122
89
  version: "0"
123
- requirement: *id007
124
90
  type: :development
125
- name: rcov
126
91
  prerelease: false
92
+ version_requirements: *id007
127
93
  - !ruby/object:Gem::Dependency
128
- version_requirements: &id008 !ruby/object:Gem::Requirement
94
+ name: ruby-debug
95
+ requirement: &id008 !ruby/object:Gem::Requirement
129
96
  none: false
130
97
  requirements:
131
98
  - - ">="
132
99
  - !ruby/object:Gem::Version
133
- hash: 3
134
- segments:
135
- - 0
136
100
  version: "0"
137
- requirement: *id008
138
101
  type: :development
139
- name: ruby-debug
140
102
  prerelease: false
103
+ version_requirements: *id008
141
104
  - !ruby/object:Gem::Dependency
142
- version_requirements: &id009 !ruby/object:Gem::Requirement
105
+ name: sqlite3-ruby
106
+ requirement: &id009 !ruby/object:Gem::Requirement
143
107
  none: false
144
108
  requirements:
145
109
  - - ">="
146
110
  - !ruby/object:Gem::Version
147
- hash: 3
148
- segments:
149
- - 0
150
111
  version: "0"
151
- requirement: *id009
152
112
  type: :development
153
- name: sqlite3-ruby
154
113
  prerelease: false
114
+ version_requirements: *id009
155
115
  - !ruby/object:Gem::Dependency
156
- version_requirements: &id010 !ruby/object:Gem::Requirement
116
+ name: fastercsv
117
+ requirement: &id010 !ruby/object:Gem::Requirement
157
118
  none: false
158
119
  requirements:
159
120
  - - ">="
160
121
  - !ruby/object:Gem::Version
161
- hash: 3
162
- segments:
163
- - 0
164
122
  version: "0"
165
- requirement: *id010
166
123
  type: :development
167
- name: fastercsv
168
124
  prerelease: false
125
+ version_requirements: *id010
169
126
  - !ruby/object:Gem::Dependency
170
- version_requirements: &id011 !ruby/object:Gem::Requirement
127
+ name: nokogiri
128
+ requirement: &id011 !ruby/object:Gem::Requirement
171
129
  none: false
172
130
  requirements:
173
131
  - - ">="
174
132
  - !ruby/object:Gem::Version
175
- hash: 3
176
- segments:
177
- - 0
178
133
  version: "0"
179
- requirement: *id011
180
134
  type: :development
181
- name: nokogiri
182
135
  prerelease: false
136
+ version_requirements: *id011
183
137
  - !ruby/object:Gem::Dependency
184
- version_requirements: &id012 !ruby/object:Gem::Requirement
138
+ name: will_paginate
139
+ requirement: &id012 !ruby/object:Gem::Requirement
185
140
  none: false
186
141
  requirements:
187
142
  - - "="
188
143
  - !ruby/object:Gem::Version
189
- hash: 29
190
- segments:
191
- - 2
192
- - 3
193
- - 15
194
144
  version: 2.3.15
195
- requirement: *id012
196
145
  type: :development
197
- name: will_paginate
198
146
  prerelease: false
147
+ version_requirements: *id012
199
148
  description: This allows you to easily build datagrid aka data tables with sortable columns and filters
200
149
  email: agresso@gmail.com
201
150
  executables: []
@@ -228,6 +177,7 @@ files:
228
177
  - lib/datagrid/filters/enum_filter.rb
229
178
  - lib/datagrid/filters/filter_eval.rb
230
179
  - lib/datagrid/filters/integer_filter.rb
180
+ - lib/datagrid/filters/string_filter.rb
231
181
  - lib/datagrid/form_builder.rb
232
182
  - lib/datagrid/helper.rb
233
183
  - lib/datagrid/rspec.rb
@@ -255,7 +205,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
255
205
  requirements:
256
206
  - - ">="
257
207
  - !ruby/object:Gem::Version
258
- hash: 3
208
+ hash: -315143401371934304
259
209
  segments:
260
210
  - 0
261
211
  version: "0"
@@ -264,14 +214,11 @@ required_rubygems_version: !ruby/object:Gem::Requirement
264
214
  requirements:
265
215
  - - ">="
266
216
  - !ruby/object:Gem::Version
267
- hash: 3
268
- segments:
269
- - 0
270
217
  version: "0"
271
218
  requirements: []
272
219
 
273
220
  rubyforge_project:
274
- rubygems_version: 1.3.7
221
+ rubygems_version: 1.6.2
275
222
  signing_key:
276
223
  specification_version: 3
277
224
  summary: Ruby gem to create datagrids