gridify 0.1.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/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ # spec/.rspec
2
+ --color
3
+ --format nested
data/Gemfile ADDED
@@ -0,0 +1,12 @@
1
+ source "http://rubygems.org"
2
+ # Add dependencies required to use your gem here.
3
+ # Example:
4
+ # gem "activesupport", ">= 2.3.5"
5
+
6
+ # Add dependencies to develop your gem here.
7
+ # Include everything needed to run rake, tests, features, etc.
8
+ group :development do
9
+ gem "bundler", "~> 1.0.0"
10
+ gem "jeweler", "~> 1.5.2"
11
+ gem "rspec"
12
+ end
@@ -0,0 +1,26 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ diff-lcs (1.1.2)
5
+ git (1.2.5)
6
+ jeweler (1.5.2)
7
+ bundler (~> 1.0.0)
8
+ git (>= 1.2.5)
9
+ rake
10
+ rake (0.8.7)
11
+ rspec (2.4.0)
12
+ rspec-core (~> 2.4.0)
13
+ rspec-expectations (~> 2.4.0)
14
+ rspec-mocks (~> 2.4.0)
15
+ rspec-core (2.4.0)
16
+ rspec-expectations (2.4.0)
17
+ diff-lcs (~> 1.1.2)
18
+ rspec-mocks (2.4.0)
19
+
20
+ PLATFORMS
21
+ ruby
22
+
23
+ DEPENDENCIES
24
+ bundler (~> 1.0.0)
25
+ jeweler (~> 1.5.2)
26
+ rspec
@@ -0,0 +1,264 @@
1
+ = Gridify
2
+
3
+ A Ruby wrapper and Rails plugin for jqGrid.
4
+
5
+ jqGrid is a rich featured data grid built with the jQuery javascript library. http://www.trirand.com/jqgridwiki/doku.php
6
+
7
+ Gridify defines a simplified, more consistent API for jqGrid rather than directly emulate the jqGrid api and options in Ruby.
8
+
9
+ Gridify tries to respect the MVC (model-view-controller) architecture of your application. This is challenging because grid features span all three areas: it's clearly part of the "view" as it mostly resides in the browser; columns in the table often directly map to columns in the model (database); and grid's ajax requests are handled by controllers. Gridfy gives you some flexibility in managing grids within MVC.
10
+
11
+ == Installation
12
+
13
+ $ script/plugin install git://github.com/linoj/gridify.git
14
+
15
+ == Scripts
16
+
17
+ Be sure to include all the javascripts and stylesheets in the +<head>+ section of your layouts which use the grid, for example
18
+
19
+ <%= stylesheet_link_tag 'application' %>
20
+ <%= stylesheet_link_tag 'ui/start/jquery-ui-1.7.2.custom' %>
21
+ <%= stylesheet_link_tag 'ui.jqgrid' %>
22
+ <%= stylesheet_link_tag 'ui.multiselect' %>
23
+
24
+ <%= javascript_include_tag 'jquery-1.3.2.min' %>
25
+ <%= javascript_include_tag 'jquery-ui-1.7.2.custom.min' %>
26
+ <%= javascript_include_tag 'grid.locale-en' %>
27
+ <%= javascript_include_tag 'jquery.jqGrid' %>
28
+ <%= javascript_include_tag 'ui.multiselect' %>
29
+
30
+ Note: When you download jqGrid, jQuery, and jqUI grab all the bits you'll be using (or just package everything)
31
+
32
+ == Examples
33
+
34
+ === Example 1
35
+
36
+ Lets say we have an ActiveRecord model "Note" which we want to display in a grid.
37
+
38
+ In app/models/note.rb,
39
+
40
+ class Note < ActiveRecord::Base
41
+ gridify
42
+ end
43
+
44
+ In the NotesController,
45
+
46
+ def index
47
+ if request.xhr?
48
+ records = Note.find_for_grid :grid, params
49
+ render :xml => Note.grid.encode_records(records)
50
+ else
51
+ @grid = Note.grid
52
+ end
53
+ end
54
+
55
+ In the app/views/notes/index.html.erb,
56
+
57
+ <%= @grid %>
58
+ <h1>Notes Grid<h1>
59
+ <table id="notes_grid"></table>
60
+ <div id="notes_grid_pager"></div>
61
+
62
+ In this example, +gridify+ creates a default grid named "grid" for the Notes model. In the controller, the #index html action supplies the +@grid+ object used by the view; the #index xml action responds to request +params+ with the encoded data. In the view, +@grid.to_s+ generates the javascript code needed for the grid, which populates the table and pager div.
63
+
64
+ === Example 2
65
+
66
+ Here we add some options, including
67
+
68
+ * use a grid named "mylist" (allowing multiple grids on a model)
69
+ * limit to specific grid columns
70
+ * ajax requests in json format (instead of xml)
71
+ * enable user resizing the grid width and height
72
+ * enable user arranging and resizing columns
73
+ * enable the search toolbar (search fields atop each column when search button is toggled)
74
+
75
+ In app/models/note.rb,
76
+
77
+ class Note < ActiveRecord::Base
78
+ gridify :mylist,
79
+ :only => [:title, :body, :updated_at],
80
+ :data_type => :json,
81
+ :resizeable => true,
82
+ :arranger => [:sortable, :hide_show],
83
+ :search_toolbar => true
84
+ end
85
+
86
+ In the NotesController is same as Example 1 except returns json instead of xml (all the search and sort params are handled by find_for_grid)
87
+
88
+ def index
89
+ if request.xhr?
90
+ records = Note.find_for_grid :mylist, params
91
+ render :json => Note.grid.encode_records(records)
92
+ else
93
+ @grid = Note.grid :mylist
94
+ end
95
+ end
96
+
97
+ In the app/views/notes/index.html.erb is the same as Example 1, except uses "mylist" name
98
+
99
+ <%= @grid %>
100
+ <h1>My Notes List<h1>
101
+ <table id="notes_mylist"></table>
102
+ <div id="notes_mylist_pager"></div>
103
+
104
+ === Example 3
105
+
106
+ Here we progressively enhance an html table into a grid. Grid is independent of the ActiveRecord model. No ajax requests.
107
+
108
+ In app/views/notes/index.html.erb,
109
+
110
+ <%= Grid.new( Note, :dom_id => "list", :table_to_grid => true ) %>
111
+ <h1>Notes List</h1>
112
+ <table id="list">
113
+ <tr>
114
+ <th>Title</th>
115
+ <th>Body</th>
116
+ </tr>
117
+ <tbody>
118
+ <% for note in @notes %>
119
+ <tr>
120
+ <td><%=h note.title %></td>
121
+ <td><%=h note.body %></td>
122
+ </tr>
123
+ <% end %>
124
+ </tbody>
125
+ </table>
126
+ <div id="list_pager"></div>
127
+
128
+ NotesController#index is standard html response, for example,
129
+
130
+ def index
131
+ @notes = Note.all
132
+ end
133
+
134
+ === Example 4
135
+
136
+ In the more complex example we take more control of individual columns, including
137
+ * initially hide the created_at column
138
+ * the title column is not resizable
139
+
140
+ and allow record (row) editing, adding, and delete via RESTful requests
141
+
142
+ In app/models/note.rb,
143
+
144
+ class Note < ActiveRecord::Base
145
+ gridify :editable => true,
146
+ :pager => true, :edit_button => true, :add_button => true, :delete_button => true do |grid|
147
+ grid.column :created_at, :hidden => true
148
+ grid.column :title, :resizable => false
149
+ end
150
+ end
151
+
152
+ In the NotesController is same as Example 1, with other actions
153
+
154
+ def index
155
+ if request.xhr?
156
+ records = Note.find_for_grid :grid, params
157
+ render :xml => Note.grid.encode_records(records)
158
+ else
159
+ @grid = Note.grid
160
+ end
161
+ end
162
+
163
+ def create
164
+ if request.xhr?
165
+ note_params = Note.grid.member_params(params)
166
+ @note = Note.new( note_params )
167
+ # must return nothing on success (until we setup a format for returning ok vs error)
168
+ msg = ""
169
+ unless @note.save
170
+ @note.errors.entries.each do |error|
171
+ msg << "<strong>#{error[0]}</strong> : #{error[1]}<br/>"
172
+ end
173
+ end
174
+ render :text => msg
175
+ else
176
+ @note = Note.new(params[:note])
177
+ if @note.save
178
+ flash[:notice] = "Successfully created note."
179
+ redirect_to @note
180
+ else
181
+ render :action => 'new'
182
+ end
183
+ end
184
+ end
185
+
186
+ def update
187
+ @note = Note.find(params[:id])
188
+ if request.xhr?
189
+ note_params = Note.grid.member_params(params)
190
+ msg = "success"
191
+ unless @note.update_attributes( note_params )
192
+ @note.errors.entries.each do |error|
193
+ msg << "<strong>#{error[0]}</strong> : #{error[1]}<br/>"
194
+ end
195
+ end
196
+ render :text => msg
197
+ else
198
+ if @note.update_attributes(params[:note])
199
+ flash[:notice] = "Successfully updated note."
200
+ redirect_to @note
201
+ else
202
+ render :action => 'edit'
203
+ end
204
+ end
205
+ end
206
+
207
+ def destroy
208
+ # NOTE: if allow multiselect should check :id for string of comma delimited id's
209
+ @note = Note.find(params[:id])
210
+ @note.destroy
211
+ if request.xhr?
212
+ render :nothing => true
213
+ else
214
+ flash[:notice] = "Successfully destroyed note."
215
+ redirect_to notes_url
216
+ end
217
+ end
218
+
219
+
220
+ In the app/views/notes/index.html.erb is the same as Example 1
221
+
222
+ <%= @grid %>
223
+ <h1>Notes Grid<h1>
224
+ <table id="notes_grid"></table>
225
+ <div id="notes_grid_pager"></div>
226
+
227
+ For this to work, you should use my fork of jqgrid http://github.com/linoj/jqGrid which adds support for RESTful routes (see http://www.vaporbase.com/postings/jqGrid_for_RESTful_Rails ) until it gets merged.
228
+
229
+ The #member_params method maps the attribute parameters into a hash as expected by update_attributes.
230
+
231
+ === Example 5
232
+
233
+ By way of better practices, I recommend you ensure the grid javascript is placed in the document header. For example,
234
+
235
+ In views/layouts/application.rb, the +<header>+ should include
236
+
237
+ <header>
238
+ ...
239
+ <%= yield :head %>
240
+ </header>
241
+
242
+ And in the views, say,
243
+
244
+ <% content_for :head %>
245
+ <%= @grid %>
246
+ <% end
247
+ <h1>Notes Grid<h1>
248
+ <table id="notes_grid"></table>
249
+ <div id="notes_grid_pager"></div>
250
+
251
+ If it bothers you to put view-specific options in the model, these can be added later (e.g. in the view or in a view helper) using #update. For example,
252
+
253
+ <%= @grid.update( :search_toolbar => false ) %>
254
+
255
+ == API
256
+
257
+ See the source code for all the options. For most of the grid and view options, see grid_options.rb. For column model options, see grid_column.rb.
258
+
259
+ You can escape the Gridify api and use the jqGrid native options directly.
260
+
261
+
262
+ -----
263
+
264
+ Copyright (c) 2010 Jonathan Linowes, released under the MIT license
@@ -0,0 +1,47 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ require 'rake'
4
+ require 'rspec/core/rake_task'
5
+
6
+ begin
7
+ Bundler.setup(:default, :development)
8
+ rescue Bundler::BundlerError => e
9
+ $stderr.puts e.message
10
+ $stderr.puts "Run `bundle install` to install missing gems"
11
+ exit e.status_code
12
+ end
13
+ require 'rake'
14
+
15
+ require 'jeweler'
16
+ Jeweler::Tasks.new do |gem|
17
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
18
+ gem.name = "gridify"
19
+ gem.homepage = "http://github.com/protectedmethod/gridify"
20
+ gem.license = "MIT"
21
+ gem.summary = %Q{Rails wrapper around jqGrid javascript library.}
22
+ gem.description = %Q{Rails wrapper around jqGrid javascript library.}
23
+ gem.email = "swalke16@gmail.com"
24
+ gem.authors = ["swalke16"]
25
+ # Include your dependencies below. Runtime dependencies are required when using your gem,
26
+ # and development dependencies are only needed for development (ie running rake tasks, tests, etc)
27
+ # gem.add_runtime_dependency 'jabber4r', '> 0.1'
28
+ # gem.add_development_dependency 'rspec', '> 1.2.3'
29
+ end
30
+ Jeweler::RubygemsDotOrgTasks.new
31
+
32
+ desc 'Run the specs'
33
+ RSpec::Core::RakeTask.new do |t|
34
+ t.pattern = "./spec/**/*_spec.rb" # don't need this, it's default.
35
+ end
36
+
37
+ task :default => :spec
38
+
39
+ require 'rake/rdoctask'
40
+ Rake::RDocTask.new do |rdoc|
41
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
42
+
43
+ rdoc.rdoc_dir = 'rdoc'
44
+ rdoc.title = "gridify #{version}"
45
+ rdoc.rdoc_files.include('README*')
46
+ rdoc.rdoc_files.include('lib/**/*.rb')
47
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
@@ -0,0 +1,5 @@
1
+ $:.push(File.join(File.dirname(__FILE__), %w[.. .. rspec]))
2
+
3
+ Autotest.add_discovery do
4
+ "rspec"
5
+ end
data/init.rb ADDED
@@ -0,0 +1 @@
1
+ require 'gridify'
@@ -0,0 +1,44 @@
1
+ require 'gridify/grid'
2
+
3
+ module Gridify
4
+
5
+ def self.included(base)
6
+ base.extend(ClassMethods)
7
+ end
8
+
9
+ module ClassMethods
10
+ attr_accessor :grids
11
+
12
+ def gridify(*args, &block)
13
+ # debugger
14
+ grid = Gridify::Grid.new( self, *args, &block)
15
+ @grids ||= {}
16
+ @grids[grid.name.to_sym] = grid
17
+
18
+ unless self.respond_to?(:find_for_grid)
19
+ class_eval <<-EOV
20
+ named_scope :find_for_grid, lambda {|name, params|
21
+ grid = grids[name]
22
+ grid.update_from_params( params )
23
+ grid.current_scope
24
+ }
25
+ EOV
26
+ end
27
+ end
28
+
29
+ def grids
30
+ @grids || {}
31
+ end
32
+
33
+ def grid
34
+ grids[:grid]
35
+ end
36
+
37
+
38
+ end
39
+ end
40
+
41
+ class ActiveRecord::Base
42
+ include Gridify
43
+ end
44
+
@@ -0,0 +1,37 @@
1
+ # lifted from state_machine plugin
2
+ module Gridify
3
+ # Provides a set of helper methods for making assertions about the content
4
+ # of various objects
5
+ module Assertions
6
+ # Validates that the given hash *only* includes the specified valid keys.
7
+ # If any invalid keys are found, an ArgumentError will be raised.
8
+ #
9
+ # == Examples
10
+ #
11
+ # options = {:name => 'John Smith', :age => 30}
12
+ #
13
+ # assert_valid_keys(options, :name) # => ArgumentError: Invalid key(s): age
14
+ # assert_valid_keys(options, 'name', 'age') # => ArgumentError: Invalid key(s): age, name
15
+ # assert_valid_keys(options, :name, :age) # => nil
16
+ def assert_valid_keys(hash, *valid_keys)
17
+ invalid_keys = hash.keys - valid_keys
18
+ raise ArgumentError, "Invalid key(s): #{invalid_keys.join(', ')}" unless invalid_keys.empty?
19
+ end
20
+
21
+ # Validates that the given hash only includes at *most* one of a set of
22
+ # exclusive keys. If more than one key is found, an ArgumentError will be
23
+ # raised.
24
+ #
25
+ # == Examples
26
+ #
27
+ # options = {:only => :on, :except => :off}
28
+ # assert_exclusive_keys(options, :only) # => nil
29
+ # assert_exclusive_keys(options, :except) # => nil
30
+ # assert_exclusive_keys(options, :only, :except) # => ArgumentError: Conflicting keys: only, except
31
+ # assert_exclusive_keys(options, :only, :except, :with) # => ArgumentError: Conflicting keys: only, except
32
+ def assert_exclusive_keys(hash, *exclusive_keys)
33
+ conflicting_keys = exclusive_keys & hash.keys
34
+ raise ArgumentError, "Conflicting keys: #{conflicting_keys.join(', ')}" unless conflicting_keys.length <= 1
35
+ end
36
+ end
37
+ end