gridify 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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