tableize 0.0.1

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.
Files changed (64) hide show
  1. data/README.md +132 -0
  2. data/lib/tableize.rb +4 -0
  3. data/lib/tableize/column_builder.rb +77 -0
  4. data/lib/tableize/helper.rb +8 -0
  5. data/lib/tableize/table_builder.rb +130 -0
  6. data/lib/tableize/utils.rb +11 -0
  7. data/lib/version.rb +7 -0
  8. data/tableize.gemspec +20 -0
  9. data/test/app/.gitignore +5 -0
  10. data/test/app/Gemfile +43 -0
  11. data/test/app/Gemfile.lock +138 -0
  12. data/test/app/README +261 -0
  13. data/test/app/Rakefile +7 -0
  14. data/test/app/app/assets/images/rails.png +0 -0
  15. data/test/app/app/assets/javascripts/application.js +9 -0
  16. data/test/app/app/assets/stylesheets/application.css +7 -0
  17. data/test/app/app/controllers/application_controller.rb +3 -0
  18. data/test/app/app/controllers/posts_controller.rb +5 -0
  19. data/test/app/app/helpers/application_helper.rb +2 -0
  20. data/test/app/app/mailers/.gitkeep +0 -0
  21. data/test/app/app/models/.gitkeep +0 -0
  22. data/test/app/app/models/post.rb +5 -0
  23. data/test/app/app/views/layouts/application.html.erb +14 -0
  24. data/test/app/app/views/posts/index.html.haml +3 -0
  25. data/test/app/config.ru +4 -0
  26. data/test/app/config/application.rb +48 -0
  27. data/test/app/config/boot.rb +6 -0
  28. data/test/app/config/database.yml +25 -0
  29. data/test/app/config/environment.rb +5 -0
  30. data/test/app/config/environments/development.rb +30 -0
  31. data/test/app/config/environments/production.rb +60 -0
  32. data/test/app/config/environments/test.rb +39 -0
  33. data/test/app/config/initializers/backtrace_silencers.rb +7 -0
  34. data/test/app/config/initializers/inflections.rb +10 -0
  35. data/test/app/config/initializers/mime_types.rb +5 -0
  36. data/test/app/config/initializers/secret_token.rb +7 -0
  37. data/test/app/config/initializers/session_store.rb +8 -0
  38. data/test/app/config/initializers/wrap_parameters.rb +14 -0
  39. data/test/app/config/locales/en.yml +10 -0
  40. data/test/app/config/routes.rb +58 -0
  41. data/test/app/db/migrate/20111008184259_create_posts.rb +11 -0
  42. data/test/app/db/schema.rb +24 -0
  43. data/test/app/db/seeds.rb +13 -0
  44. data/test/app/doc/README_FOR_APP +2 -0
  45. data/test/app/lib/assets/.gitkeep +0 -0
  46. data/test/app/lib/tasks/.gitkeep +0 -0
  47. data/test/app/log/.gitkeep +0 -0
  48. data/test/app/public/404.html +26 -0
  49. data/test/app/public/422.html +26 -0
  50. data/test/app/public/500.html +26 -0
  51. data/test/app/public/favicon.ico +0 -0
  52. data/test/app/public/robots.txt +5 -0
  53. data/test/app/script/rails +6 -0
  54. data/test/app/test/fixtures/.gitkeep +0 -0
  55. data/test/app/test/fixtures/posts.yml +11 -0
  56. data/test/app/test/functional/.gitkeep +0 -0
  57. data/test/app/test/integration/.gitkeep +0 -0
  58. data/test/app/test/performance/browsing_test.rb +12 -0
  59. data/test/app/test/test_helper.rb +13 -0
  60. data/test/app/test/unit/.gitkeep +0 -0
  61. data/test/app/test/unit/post_test.rb +7 -0
  62. data/test/app/vendor/assets/stylesheets/.gitkeep +0 -0
  63. data/test/app/vendor/plugins/.gitkeep +0 -0
  64. metadata +109 -0
@@ -0,0 +1,132 @@
1
+ Tableize
2
+ ========
3
+
4
+ Installation
5
+ ------------
6
+ gem install tableize
7
+
8
+ Examples
9
+ -----
10
+ #### Basic
11
+ table_for Post, @posts do |t|
12
+ t.column "Title", :title
13
+ t.column "Author", :author
14
+ end
15
+
16
+ Is the same as:
17
+
18
+ table_for do |t|
19
+ t.columns :title, :author
20
+ end
21
+
22
+ Both examples generate the following html:
23
+
24
+ <table class="posts">
25
+ <thead>
26
+ <tr>
27
+ <th class="title string">Title</th>
28
+ <th class="author string">Author</th>
29
+ </tr>
30
+ </thead>
31
+ <tbody>
32
+ <tr class="post_1">
33
+ <td>Hello World!</td>
34
+ <td>Christian Blais</td>
35
+ </tr>
36
+ </tbody>
37
+ </table>
38
+
39
+ #### Few defaults
40
+ * Inherited Resources
41
+
42
+ By default, `Tableize` will search for both `resource_class` and `collection` methods. So you don't have to specify them each time, unless
43
+ of course you want to override the default behavior. That being said, the following code produce the exact same output as the basic example
44
+ above.
45
+
46
+ table_for do |t|
47
+ t.column "Title", :title
48
+ t.column "Author", :author
49
+ end
50
+
51
+ * I18n
52
+
53
+ By default, `Tableize` will try to internationalised your attribute, so you don't have to name each of your column. So, assuming my
54
+ model responds to `human_attribute_name`, the following example still produces the exact same output.
55
+
56
+ table_for do |t|
57
+ t.column :title
58
+ t.column :author
59
+ end
60
+
61
+ * Columns
62
+
63
+ `Tableize` responds to `defaults` method, which will create a column for each public attribute of your model. Use it like this:
64
+
65
+ table_for do |t|
66
+ t.defaults
67
+ end
68
+
69
+ * Multiple columns, one line
70
+
71
+ table_for do |t|
72
+ t.columns :title, :author
73
+ end
74
+
75
+ #### Advanced features
76
+ * Lambdas
77
+
78
+ You can use lambdas if you want to have a custom column.
79
+
80
+ table_for do |t|
81
+ t.column "Title" do |post|
82
+ post.title + "!"
83
+ end
84
+ end
85
+
86
+ You can also specify a method to be called before the yield.
87
+
88
+ table_for do |t|
89
+ t.column "Title", :title do |title|
90
+ title + "!"
91
+ end
92
+ end
93
+
94
+ * Extras
95
+
96
+ Let's say `author` is a relation, and you want to show his first name and last name as separate columns. The following would works:
97
+
98
+ table_for do |t|
99
+ t.column "First name", :author do |author|
100
+ author.first_name
101
+ end
102
+ t.column "Last name", :author do |author|
103
+ author.last_name
104
+ end
105
+ end
106
+
107
+ But the above code triggers the `author` method twice. In order to avoid that, you could use the `extra` method, which will be executed only
108
+ once per row, yielding the result alongside the resource in each block. You can use more than one extra without any problem.
109
+
110
+ table_for do |t|
111
+ t.extra do |post|
112
+ post.author
113
+ end
114
+
115
+ t.column "First name" do |post, author|
116
+ author.first_name
117
+ end
118
+ t.column "Last name" do |post, author|
119
+ author.last_name
120
+ end
121
+ end
122
+
123
+ * Hashes
124
+
125
+ `Tableize` also accepts hashes instead of regular collections. Use it the same way.
126
+
127
+ collection = [{:title => "Hello World", "author" => "Christian Blais"}]
128
+
129
+ table_for Post, collection do |t|
130
+ t.column :title
131
+ t.column "author"
132
+ end
@@ -0,0 +1,4 @@
1
+ require File.dirname(__FILE__) + "/tableize/helper"
2
+ require File.dirname(__FILE__) + "/tableize/utils"
3
+ require File.dirname(__FILE__) + "/tableize/table_builder"
4
+ require File.dirname(__FILE__) + "/tableize/column_builder"
@@ -0,0 +1,77 @@
1
+ module Tableize
2
+ class ColumnBuilder
3
+
4
+ attr_reader :title, :method
5
+
6
+ def initialize(resource_class, *args, &block)
7
+ @options = args.extract_options!
8
+ @resource_class = resource_class
9
+ @html_options = @options.delete(:html) || {}
10
+ @block = block
11
+ @title = get_title(args)
12
+ @method = get_method(args)
13
+ end
14
+
15
+ def value(resource, extras)
16
+ if @block
17
+ @method ? @block.call(resource.send(@method), *extras) : @block.call(resource, *extras)
18
+ else
19
+ if @method
20
+ if resource.respond_to?(@method)
21
+ resource.send(@method)
22
+ elsif resource.kind_of?(Hash)
23
+ resource[@method]
24
+ end
25
+ end
26
+ end
27
+ end
28
+
29
+ def td_options
30
+ get_options(:td)
31
+ end
32
+
33
+ def th_options
34
+ options = get_options(:th)
35
+
36
+ if @method
37
+ options[:class] = Tableize::convert_to_array(options[:class], @method.to_s.underscore, value_type)
38
+ end
39
+
40
+ options
41
+ end
42
+
43
+ protected
44
+
45
+ def get_options(key)
46
+ @html_options[key] || {}
47
+ end
48
+
49
+ def get_title(args)
50
+ if title = args.first
51
+ if title.kind_of?(String)
52
+ args.shift
53
+ elsif @options.key?(:title)
54
+ @options[:title]
55
+ elsif title.kind_of?(Symbol) && @resource_class.respond_to?(:human_attribute_name)
56
+ @resource_class.send(:human_attribute_name, title)
57
+ else
58
+ title.to_s
59
+ end
60
+ end
61
+ end
62
+
63
+ def get_method(args)
64
+ if method = args.last
65
+ method
66
+ end
67
+ end
68
+
69
+ def value_type
70
+ if @method && @resource_class.respond_to?(:columns)
71
+ if column = @resource_class.columns.detect{ |column| column.name.to_sym == @method }
72
+ column.type
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,8 @@
1
+ module Tableize
2
+ def table_for(*args, &block)
3
+ Tableize::TableBuilder.new(self, *args, &block).render
4
+ end
5
+ alias_method :table, :table_for
6
+ end
7
+
8
+ ActionView::Base.send :include, Tableize
@@ -0,0 +1,130 @@
1
+ module Tableize
2
+ class TableBuilder
3
+
4
+ delegate :content_tag, :to => :@view_context
5
+
6
+ DEFAULT_OPTIONS = {
7
+ :default_table_class => true,
8
+ :default_tr_class => true
9
+ }
10
+
11
+ def initialize(view_context, *args, &block)
12
+ @options = DEFAULT_OPTIONS.merge(args.extract_options!)
13
+ @table_options = @options.delete(:html) || {}
14
+ @tr_options = @table_options.delete(:tr) || {}
15
+ @view_context = view_context
16
+ @block = block
17
+ @resource_class = get_resource_class(args)
18
+ @collection = get_collection(args)
19
+ @columns = []
20
+ @extras = []
21
+ end
22
+
23
+ def defaults
24
+ (@resource_class.new.attributes.keys - @resource_class.protected_attributes.to_a).each do |attribute|
25
+ column(attribute.to_sym)
26
+ end
27
+ end
28
+
29
+ def columns(*args)
30
+ args.each do |arg|
31
+ column(arg)
32
+ end
33
+ end
34
+
35
+ def column(*args, &block)
36
+ @columns << Tableize::ColumnBuilder.new(@resource_class, *args, &block)
37
+ end
38
+
39
+ def extra(&block)
40
+ @extras << block if block_given?
41
+ end
42
+
43
+ def render
44
+ @view_context.capture{ @block.call(self) }
45
+
46
+ content_tag(:table, table_options) do
47
+ [thead, tbody].join.html_safe
48
+ end
49
+ end
50
+
51
+ protected
52
+
53
+ def thead
54
+ content_tag(:thead) do
55
+ content_tag(:tr) do
56
+ @columns.map do |column|
57
+ content_tag(:th, column.th_options) do
58
+ column.title
59
+ end
60
+ end.join.html_safe
61
+ end
62
+ end
63
+ end
64
+
65
+ def tbody
66
+ content_tag(:tbody) do
67
+ @collection.map do |resource|
68
+ extras = @extras.map{ |block| block.call(resource) }
69
+
70
+ content_tag(:tr, tr_options(resource)) do
71
+ @columns.map do |column|
72
+ content_tag(:td, column.td_options) do
73
+ column.value(resource, extras).to_s.html_safe
74
+ end
75
+ end.join.html_safe
76
+ end
77
+ end.join.html_safe
78
+ end
79
+ end
80
+
81
+ def table_options
82
+ options = @table_options.dup
83
+
84
+ if @options[:default_table_class] && @resource_class.respond_to?(:model_name)
85
+ options[:class] = Tableize::convert_to_array(options[:class], @resource_class.model_name.tableize)
86
+ end
87
+
88
+ options
89
+ end
90
+
91
+ def tr_options(resource)
92
+ options = @tr_options.dup
93
+
94
+ if @options[:default_tr_class] && @resource_class.respond_to?(:model_name)
95
+ options[:class] = Tableize::convert_to_array(options[:class], "#{@resource_class.model_name.underscore}_#{get_resource_id(resource)}")
96
+ end
97
+
98
+ options
99
+ end
100
+
101
+ def get_resource_id(resource)
102
+ if resource.respond_to?(:id)
103
+ resource.id
104
+ elsif resource.kind_of?(Hash)
105
+ resource[:id] || resource["id"]
106
+ end
107
+ end
108
+
109
+ def get_resource_class(args)
110
+ if resource_class = args.shift
111
+ resource_class
112
+ elsif @options.key?(:resource_class)
113
+ @options[:resource_class]
114
+ elsif @view_context.respond_to?(:resource_class)
115
+ @view_context.resource_class
116
+ end
117
+ end
118
+
119
+ def get_collection(args)
120
+ if collection = args.shift
121
+ collection
122
+ elsif @options.key?(:collection)
123
+ @options[:collection]
124
+ elsif @view_context.respond_to?(:collection)
125
+ @view_context.collection
126
+ end
127
+ end
128
+
129
+ end
130
+ end
@@ -0,0 +1,11 @@
1
+ module Tableize
2
+ def self.convert_to_array(array, *args)
3
+ array = [array].flatten.compact
4
+
5
+ args.each do |arg|
6
+ array.push(arg)
7
+ end
8
+
9
+ array
10
+ end
11
+ end
@@ -0,0 +1,7 @@
1
+ module Tableize
2
+ MAJOR = 0
3
+ MINOR = 0
4
+ BUILD = 1
5
+
6
+ VERSION = "#{MAJOR}.#{MINOR}.#{BUILD}"
7
+ end
@@ -0,0 +1,20 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib/', __FILE__)
3
+ $:.unshift lib unless $:.include?(lib)
4
+
5
+ require './lib/version'
6
+
7
+ Gem::Specification.new do |s|
8
+ s.name = "tableize"
9
+ s.version = Tableize::VERSION
10
+ s.platform = Gem::Platform::RUBY
11
+ s.authors = ["Christian Blais"]
12
+ s.email = ["christ.blais@gmail.com"]
13
+ s.homepage = "http://github.com/christianblais/tableize"
14
+ s.summary = "Simple table helper"
15
+ s.description = "Simple table helper"
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+
19
+ s.require_paths = ['lib', 'test']
20
+ end
@@ -0,0 +1,5 @@
1
+ .bundle
2
+ db/*.sqlite3
3
+ log/*.log
4
+ tmp/
5
+ .sass-cache/
@@ -0,0 +1,43 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gem 'rails', '3.1.1'
4
+
5
+ # Bundle edge Rails instead:
6
+ # gem 'rails', :git => 'git://github.com/rails/rails.git'
7
+
8
+ gem 'sqlite3'
9
+ gem 'haml'
10
+ gem 'utilities'
11
+ gem 'inherited_resources'
12
+ gem 'tableize', :path => "~/projects/gems/tableize"
13
+
14
+ # Gems used only for assets and not required
15
+ # in production environments by default.
16
+ group :assets do
17
+ gem 'sass-rails', '~> 3.1.4'
18
+ gem 'coffee-rails', '~> 3.1.1'
19
+ gem 'uglifier', '>= 1.0.3'
20
+ end
21
+
22
+ gem 'jquery-rails'
23
+
24
+ # To use ActiveModel has_secure_password
25
+ # gem 'bcrypt-ruby', '~> 3.0.0'
26
+
27
+ # Use unicorn as the web server
28
+ # gem 'unicorn'
29
+
30
+ # Deploy with Capistrano
31
+ # gem 'capistrano'
32
+
33
+ # To use debugger
34
+ # gem 'ruby-debug19', :require => 'ruby-debug'
35
+
36
+ # fixing /gems/execjs-1.2.4/lib/execjs/runtimes.rb:45:in `autodetect': Could not find a JavaScript runtime. See https://github.com/sstephenson/execjs for a list of available runtimes. (ExecJS::RuntimeUnavailable)
37
+ gem 'execjs'
38
+ gem 'therubyracer'
39
+
40
+ group :test do
41
+ # Pretty printed test output
42
+ gem 'turn', :require => false
43
+ end