sorting_table_for 0.2.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -6,8 +6,7 @@ module SortingTableFor
6
6
 
7
7
  class TableBuilder
8
8
 
9
- include ::ActionView::Helpers::TagHelper
10
- include ::ActionView::Helpers::NumberHelper
9
+ include ::ActionView::Helpers
11
10
 
12
11
  class_inheritable_accessor :reserved_columns, :currency_columns,
13
12
  :default_boolean, :show_total_entries,
@@ -31,7 +30,7 @@ module SortingTableFor
31
30
  def initialize(collection, object_or_array, template, options, params)
32
31
  @collection, @@object_or_array, @@template, @@options, @@params = collection, object_or_array, template, options, params
33
32
  set_default_global_options
34
- I18n.set_options(params, model_name(@collection.first), object_or_array.first, @@options[:i18n])
33
+ I18n.set_options(params, model_name(@collection.first), @@options[:i18n])
35
34
  @lines = []
36
35
  end
37
36
 
@@ -135,7 +134,7 @@ module SortingTableFor
135
134
  column_options, html_options = get_column_and_html_options( args.extract_options! )
136
135
  if block_given?
137
136
  @header_line = FormatLine.new(args, column_options, html_options, nil, :thead)
138
- @@template.capture(&block)
137
+ capture(&block)
139
138
  else
140
139
  @header_line = FormatLine.new(args, column_options, html_options, @collection.first, :thead)
141
140
  end
@@ -184,7 +183,7 @@ module SortingTableFor
184
183
  #
185
184
  def header(*args, &block)
186
185
  if block_given?
187
- block = @@template.capture(&block)
186
+ block = capture(&block)
188
187
  @header_line.add_cell(@collection.first, args, nil, block)
189
188
  else
190
189
  @header_line.add_cell(@collection.first, args)
@@ -392,7 +391,7 @@ module SortingTableFor
392
391
  #
393
392
  def column(*args, &block)
394
393
  if block_given?
395
- block = @@template.capture(&block)
394
+ block = capture(&block)
396
395
  @lines.last.add_cell(@current_object, args, nil, block)
397
396
  else
398
397
  @lines.last.add_cell(@current_object, args)
@@ -451,7 +450,7 @@ module SortingTableFor
451
450
  column_options, html_options = get_column_and_html_options( args.extract_options! )
452
451
  if block_given?
453
452
  @footer_line = FormatLine.new(args, column_options, html_options, nil, :tfoot)
454
- @@template.capture(&block)
453
+ capture(&block)
455
454
  else
456
455
  @footer_line = FormatLine.new(args, column_options, html_options, @collection.first, :tfoot) if !args.empty?
457
456
  end
@@ -506,7 +505,7 @@ module SortingTableFor
506
505
  #
507
506
  def footer(*args, &block)
508
507
  if block_given?
509
- block = @@template.capture(&block)
508
+ block = capture(&block)
510
509
  @footer_line.add_cell(@collection.first, args, nil, block)
511
510
  else
512
511
  @footer_line.add_cell(@collection.first, args)
@@ -557,7 +556,7 @@ module SortingTableFor
557
556
  def caption(*args, &block)
558
557
  @caption[:option], @caption[:html] = get_column_and_html_options( args.extract_options! )
559
558
  if block_given?
560
- @caption[:value] = @@template.capture(&block)
559
+ @caption[:value] = capture(&block)
561
560
  else
562
561
  @caption[:value] = (args.empty?) ? I18n.t(:table_caption) : args.first;
563
562
  end
@@ -571,6 +570,11 @@ module SortingTableFor
571
570
  object.present? ? object.class.name : object.to_s.classify
572
571
  end
573
572
 
573
+ # Send method to ActionView
574
+ def method_missing(name, *args, &block)
575
+ @@template.send(name, *args, &block)
576
+ end
577
+
574
578
  private
575
579
 
576
580
  def render_caption
@@ -595,6 +599,7 @@ module SortingTableFor
595
599
  def render_tbody
596
600
  if @lines and @lines.size > 0
597
601
  return Tools::html_safe(content_tag(:tbody, render_total_entries + Tools::html_safe(@lines.collect { |line| line.render_line }.join)))
602
+ return Tools::html_safe(content_tag(:tr, content_tag(:td, I18n.t(:total_entries, :scope => :sorting_table_for, :value => total_entries), {:colspan => max_cells}), { :class => 'total-entries' }))
598
603
  end
599
604
  ''
600
605
  end
@@ -624,7 +629,7 @@ module SortingTableFor
624
629
  total_entries = @collection.total_entries rescue @collection.size
625
630
  header_total_cells = @header_line ? @header_line.total_cells : 0
626
631
  max_cells = (@lines.first.total_cells > header_total_cells) ? @lines.first.total_cells : header_total_cells
627
- return Tools::html_safe(content_tag(:tr, content_tag(:td, I18n.t(:total_entries, :scope => :sorting_table_for, :value => total_entries), {:colspan => max_cells}), { :class => 'total-entries' }))
632
+ return Tools::html_safe(content_tag(:tr, content_tag(:td, I18n.t(:total_entries, :value => total_entries), {:colspan => max_cells}), { :class => 'total-entries' }))
628
633
  end
629
634
  ''
630
635
  end
@@ -635,300 +640,4 @@ module SortingTableFor
635
640
  end
636
641
 
637
642
  end
638
-
639
- class FormatLine < TableBuilder
640
-
641
- def initialize(args, column_options = {}, html_options = {}, object = nil, type = nil)
642
- @args, @column_options, @html_options, @object, @type = args, column_options, html_options, object, type
643
- @cells = []
644
- if object
645
- @attributes = (args.empty?) ? (get_columns - TableBuilder.reserved_columns) : @args
646
- create_cells
647
- end
648
- end
649
-
650
- # Create a new cell with the class FormatCell
651
- # Add the object in @cells
652
- def add_cell(object, args, type = nil, block = nil)
653
- @cells << FormatCell.new(object, args, type, block)
654
- end
655
-
656
- # Return a tr line based on the type (:thead, :tbody or :tfoot)
657
- def render_line
658
- if @type == :thead
659
- return content_tag(:tr, Tools::html_safe(@cells.collect { |cell| cell.render_cell_thead }.join), @html_options)
660
- elsif @type == :tfoot
661
- return content_tag(:tr, Tools::html_safe(@cells.collect { |cell| cell.render_cell_tfoot }.join), @html_options)
662
- else
663
- content_tag(:tr, Tools::html_safe(@cells.collect { |cell| cell.render_cell_tbody }.join), @html_options.merge(:class => "#{@html_options[:class]} #{@@template.cycle(:odd, :even)}".strip))
664
- end
665
- end
666
-
667
- # Return the number of cells in line
668
- def total_cells
669
- @cells.size
670
- end
671
-
672
- protected
673
-
674
- # Return each column in the model's database table
675
- def content_columns
676
- model_name(@object).constantize.content_columns.collect { |c| c.name.to_sym }.compact rescue []
677
- end
678
-
679
- # Return true if the column is in the model's database table
680
- def model_have_column?(column)
681
- model_name(@object).constantize.content_columns.each do |model_column|
682
- return true if model_column.name == column.to_s
683
- end
684
- false
685
- end
686
-
687
- # Return true if the column is in the model's database table
688
- def can_sort_column?(column)
689
- model_have_column?(column)
690
- end
691
-
692
- # Options only for cells
693
- def only_cell_option?(key)
694
- [:colspan].include? key
695
- end
696
-
697
- # Format ask to send options to cell
698
- def format_options_to_cell(ask, options = @column_options)
699
- options.each do |key, value|
700
- if only_cell_option?(key)
701
- if ask.is_a? Hash
702
- ask.merge!(key => value)
703
- else
704
- ask = [ask] unless ask.is_a? Array
705
- (ask.last.is_a? Hash and ask.last.has_key? :html) ? ask.last[:html].merge!(key => value) : ask << { :html => { key => value }}
706
- end
707
- end
708
- end
709
- ask
710
- end
711
-
712
- private
713
-
714
- # Call after headers or columns with no attributes (table.headers)
715
- # Create all the cells based on each column in the model's database table
716
- # Create cell's actions based on option default_actions or on actions given (:actions => [:edit])
717
- def create_cells
718
- @attributes.each { |ask| add_cell(@object, format_options_to_cell(ask)) }
719
- if @args.empty?
720
- TableBuilder.default_actions.each { |action| add_cell(@object, action, :action) }
721
- else
722
- get_column_actions.each { |action| add_cell(@object, action, :action) }
723
- end
724
- end
725
-
726
- # Return an Array of all actions given to headers or columns (:actions => [:edit, :delete])
727
- def get_column_actions
728
- if @column_options.has_key? :actions
729
- if @column_options[:actions].is_a?(Array)
730
- return @column_options[:actions]
731
- else
732
- return [ @column_options[:actions] ]
733
- end
734
- end
735
- []
736
- end
737
-
738
- # Return an Array of the columns based on options :only or :except
739
- def get_columns
740
- if @column_options.has_key? :only
741
- return @column_options[:only] if @column_options[:only].is_a?(Array)
742
- [ @column_options[:only] ]
743
- elsif @column_options.has_key? :except
744
- return content_columns - @column_options[:except] if @column_options[:except].is_a?(Array)
745
- content_columns - [ @column_options[:except] ]
746
- else
747
- content_columns
748
- end
749
- end
750
-
751
- end
752
-
753
- class FormatCell < FormatLine
754
-
755
- def initialize(object, args, type = nil, block = nil)
756
- @object, @type, @block = object, type, block
757
- if args.is_a? Array
758
- @options, @html_options = get_cell_and_html_options( args.extract_options! )
759
- @ask = args.first
760
- if @ask.nil? and @options.has_key?(:action)
761
- @type = :action
762
- @ask = @options[:action]
763
- end
764
- else
765
- @ask = args
766
- end
767
- set_default_options
768
- @can_sort = true if @options and @options[:sort] and can_sort_column?(@ask)
769
- end
770
-
771
- # Return a td with the formated value or action for columns
772
- def render_cell_tbody
773
- if @type == :action
774
- cell_value = action_link_to(@ask)
775
- elsif @ask
776
- cell_value = (@ask.is_a?(Symbol)) ? format_cell_value(@object[@ask], @ask) : format_cell_value(@ask)
777
- else
778
- cell_value = @block
779
- end
780
- cell_value = action_link_to(@options[:action], cell_value) if @type != :action and @options.has_key?(:action)
781
- content_tag(:td, cell_value, @html_options)
782
- end
783
-
784
- # Return a td with the formated value or action for headers
785
- def render_cell_thead
786
- if @ask
787
- cell_value = (@ask.is_a?(Symbol)) ? I18n.t(@ask, {}, :header) : @ask
788
- else
789
- cell_value = @block
790
- end
791
- if @can_sort and @options[:sort]
792
- @html_options.merge!(:class => "#{@html_options[:class]} #{sorting_html_class}".strip)
793
- content_tag(:th, sort_link_to(cell_value), @html_options)
794
- else
795
- content_tag(:th, cell_value, @html_options)
796
- end
797
- end
798
-
799
- def render_cell_tfoot
800
- if @ask
801
- cell_value = (@ask.is_a?(Symbol)) ? I18n.t(@ask, {}, :footer) : @ask
802
- else
803
- cell_value = @block
804
- end
805
- cell_value = action_link_to(@options[:action], cell_value) if @type != :action and @options.has_key?(:action)
806
- content_tag(:td, cell_value, @html_options)
807
- end
808
-
809
- private
810
-
811
- # Return options and html options for a cell
812
- def get_cell_and_html_options(options)
813
- return options, options.delete(:html) || {}
814
- end
815
-
816
- # Set default options for cell
817
- # Set an empty hash if no html options
818
- # Set an empty hash if no options
819
- # Set sort to true if no options sort
820
- def set_default_options
821
- @html_options = {} unless defined? @html_options
822
- @options = {} unless defined? @options
823
- @html_options = format_options_to_cell(@html_options, @options)
824
- @options[:sort] = @@options[:sort] if !@options.has_key? :sort
825
- end
826
-
827
- # Create the link for actions
828
- # Set the I18n translation or the given block for the link's name
829
- def action_link_to(action, block = nil)
830
- object_or_array = @@object_or_array.clone
831
- object_or_array.push @object
832
- return case action.to_sym
833
- when :delete
834
- create_link_to(block || I18n.t(:delete), object_or_array, @@options[:link_remote], :delete, I18n.t(:confirm_delete))
835
- when :show
836
- create_link_to(block || I18n.t(:show), object_or_array, @@options[:link_remote])
837
- else
838
- object_or_array.insert(0, action)
839
- create_link_to(block || I18n.t(@ask), object_or_array, @@options[:link_remote])
840
- end
841
- end
842
-
843
- # Create sorting link
844
- def sort_link_to(name)
845
- create_link_to(name, sort_url, @@options[:sort_remote])
846
- end
847
-
848
- # Create the link based on object
849
- # Set an ajax link if option link_remote is set to true
850
- # Compatible with rails 2 and 3.
851
- def create_link_to(block, url, remote, method = nil, confirm = nil)
852
- if remote and Tools::rails3?
853
- return @@template.link_to(block, url, :method => method, :confirm => confirm, :remote => true)
854
- elsif remote
855
- method = :get if method.nil?
856
- return @@template.link_to_remote(block, { :url => url, :method => method, :confirm => confirm })
857
- end
858
- @@template.link_to(block, url, :method => method, :confirm => confirm)
859
- end
860
-
861
- # Return a string with html class of sorting for headers
862
- # The html class is based on option: SortingTableFor::TableBuilder.html_sorting_class
863
- def sorting_html_class
864
- return TableBuilder.html_sorting_class.first if current_sorting.nil?
865
- return TableBuilder.html_sorting_class.second if current_sorting == :asc
866
- TableBuilder.html_sorting_class.third
867
- end
868
-
869
- # Return an url for sorting
870
- # Add the param sorting_table[name]=direction to the url
871
- # Add the default direction: :asc
872
- def sort_url
873
- url_params = @@params.clone
874
- if url_params.has_key? TableBuilder.params_sort_table
875
- if url_params[TableBuilder.params_sort_table].has_key? @ask
876
- url_params[TableBuilder.params_sort_table][@ask] = inverse_sorting
877
- return @@template.url_for(url_params)
878
- end
879
- url_params[TableBuilder.params_sort_table].delete @ask
880
- end
881
- url_params[TableBuilder.params_sort_table] = { @ask => :asc }
882
- @@template.url_for(url_params)
883
- end
884
-
885
- # Return a symbol of the current sorting (:asc, :desc, nil)
886
- def current_sorting
887
- if @@params.has_key? TableBuilder.params_sort_table and @@params[TableBuilder.params_sort_table].has_key? @ask
888
- return @@params[TableBuilder.params_sort_table][@ask].to_sym
889
- end
890
- nil
891
- end
892
-
893
- # Return a symbol, the inverse of the current sorting
894
- def inverse_sorting
895
- return :asc if current_sorting.nil?
896
- return :desc if current_sorting == :asc
897
- :asc
898
- end
899
-
900
- # Return the formated cell's value
901
- def format_cell_value(value, attribute = nil)
902
- unless (ret_value = format_cell_value_as_ask(value)).nil?
903
- return ret_value
904
- end
905
- format_cell_value_as_type(value, attribute)
906
- end
907
-
908
- # Format the value if option :as is set
909
- def format_cell_value_as_ask(value)
910
- return nil if !@options or @options.empty? or !@options.has_key?(:as)
911
- return case @options[:as]
912
- when :date then ::I18n.l(value.to_date, :format => @options[:format] || TableBuilder.i18n_default_format_date)
913
- when :time then ::I18n.l(value.to_datetime, :format => @options[:format] || TableBuilder.i18n_default_format_date)
914
- when :currency then number_to_currency(value)
915
- else nil
916
- end
917
- end
918
-
919
- # Format the value based on value's type
920
- def format_cell_value_as_type(value, attribute)
921
- if value.is_a?(Time) or value.is_a?(Date)
922
- return ::I18n.l(value, :format => @options[:format] || TableBuilder.i18n_default_format_date)
923
- elsif TableBuilder.currency_columns.include?(attribute)
924
- return number_to_currency(value)
925
- elsif value.is_a?(TrueClass)
926
- return TableBuilder.default_boolean.first
927
- elsif value.is_a?(FalseClass)
928
- return TableBuilder.default_boolean.second
929
- end
930
- value
931
- end
932
-
933
- end
934
643
  end
data/spec/db/schema.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  ActiveRecord::Schema.define(:version => 0) do
2
2
 
3
- create_table :users, :force => true do |t|
3
+ create_table :sorting_table_for_users, :force => true do |t|
4
4
 
5
5
  t.string :username
6
6
  t.string :firstname
@@ -1,4 +1,4 @@
1
- class User < ActiveRecord::Base
1
+ class SortingTableForUser < ActiveRecord::Base
2
2
  if ::SortingTableFor::Tools::rails3?
3
3
  scope :good_position, :conditions => 'position > 3'
4
4
  scope :set_limit, lambda { |limit| { :limit => limit } }
@@ -10,7 +10,7 @@ class User < ActiveRecord::Base
10
10
  end
11
11
 
12
12
  20.times do |n|
13
- User.create(
13
+ SortingTableForUser.create(
14
14
  :username => "my_usename_#{n}",
15
15
  :firstname => "my_firstname_#{n}",
16
16
  :lastname => "my_lastname_#{n}",
@@ -1,16 +1,19 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  require 'spec_helper'
4
- require File.expand_path(File.dirname(__FILE__) + '/../fixtures/user')
4
+ require File.expand_path(File.dirname(__FILE__) + '/../fixtures/sorting_table_for_user')
5
5
 
6
6
  include SortingTableForSpecHelper
7
7
 
8
8
  describe SortingTableFor, :type => :helper do
9
9
 
10
+ before :all do
11
+ (SortingTableFor::Tools::rails3?) ? routes_rails3 : routes_rails2
12
+ end
13
+
10
14
  before :each do
11
- @users = User.all
12
- helper.stub!(:url_for).and_return('fake_link')
13
- helper.stub!(:params).and_return({ :controller => 'fakes', :action => 'index' })
15
+ @users = SortingTableForUser.all
16
+ helper.stub!(:params).and_return({ :controller => 'sorting_table_for_users', :action => 'index' })
14
17
  helper.output_buffer = ''
15
18
  end
16
19
 
@@ -42,7 +45,7 @@ describe SortingTableFor, :type => :helper do
42
45
  end
43
46
  end
44
47
 
45
- it "should no use i18n by default" do
48
+ it "should use i18n by default" do
46
49
  helper.sorting_table_for(@users) do |table|
47
50
  html = table.headers(:username)
48
51
  html.should have_comp_tag("th:nth-child(1)", :text => 'Usernames')