Skip to content

Commit 83df1d2

Browse files
committed
Added support for belongs_to columns. Version 0.3.16
1 parent 9609d33 commit 83df1d2

File tree

3 files changed

+52
-11
lines changed

3 files changed

+52
-11
lines changed

README.md

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,8 @@ module Effective
140140

141141
table_column :updated_at, :proc => Proc.new { |post| nicetime(post.updated_at) } # just a standard helper as defined in helpers/application_helper.rb
142142

143+
table_column :user
144+
143145
table_column :post_category_id, :filter => {:type => :select, :values => Proc.new { PostCategory.all } } do |post|
144146
post.post_category.name.titleize
145147
end
@@ -214,6 +216,16 @@ table_column :stripe_customer_id, :column => 'customers.stripe_customer_id'
214216
# Any SQL used to search this field will take the form of
215217
# "to_char(#{column} AT TIME ZONE 'GMT', 'YYYY-MM-DD HH24:MI') ILIKE '%?%'"
216218
table_column :created_at
219+
220+
# If the name of the table column matches a belongs_to in our collection's main class
221+
# This column will be detected as a belongs_to and some predefined filters will be set up
222+
# So declaring the following
223+
table_column :user
224+
225+
# Will have the same behaviour as declaring
226+
table_column :user_id, :if => Proc.new { attributes[:user_id].blank? }, :filter => {:type => :select, :values => Proc.new { User.all.map { |user| [user.id, user.to_s] }.sort { |x, y| x[1] <=> y[1] } } } do |post|
227+
post.user.to_s
228+
end
217229
```
218230

219231
All table_columns are :visible => true, :sortable => true by default.
@@ -398,14 +410,16 @@ end
398410
and/or your table_column definition:
399411

400412
```ruby
401-
table_column :user, :if => Proc.new { attributes[:user_id].blank? }
413+
table_column :user_id, :if => Proc.new { attributes[:user_id].blank? } do |post|
414+
post.user.email
415+
end
402416
```
403417

404418
## Array Backed collection
405419

406420
Don't want to use ActiveRecord? Not a problem.
407421

408-
Define your collection as an Array of Arrays, and only array_columns, everything works as expected.
422+
Define your collection as an Array of Arrays, declare only array_columns, and everything works as expected.
409423

410424
```ruby
411425
module Effective
@@ -440,13 +454,13 @@ The finalize method provides a hook to process the final collection as an Array
440454

441455
This final collection is available after searching, sorting and pagination.
442456

443-
I can't think of any reason you would actually need or want this:
457+
As you have full control over the table_column presentation, I can't think of any reason you would actually need or want this:
444458

445459
```ruby
446460
def finalize(collection)
447461
collection.each do |row|
448-
row.each do |col|
449-
col.gsub!('horse', 'force') if col.kind_of?(String)
462+
row.each do |column|
463+
column.gsub!('horse', 'force') if column.kind_of?(String)
450464
end
451465
end
452466
end

app/models/effective/datatable.rb

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,8 @@ def arrayize(collection)
216216
view.instance_exec(obj, collection, self, &opts[:block])
217217
elsif opts[:proc]
218218
view.instance_exec(obj, collection, self, &opts[:proc])
219+
elsif opts[:type] == :belongs_to
220+
val = (obj.send(name) rescue nil).to_s
219221
else
220222
val = (obj.send(name) rescue nil)
221223
val = (obj[opts[:index]] rescue nil) if val == nil
@@ -266,9 +268,27 @@ def table_columns_with_defaults
266268

267269
def initalize_table_columns(cols)
268270
sql_table = (collection.table rescue nil)
271+
272+
# Here we identify all belongs_to associations and build up a Hash like:
273+
# {:user => {:foreign_key => 'user_id', :klass => User}, :order => {:foreign_key => 'order_id', :klass => Effective::Order}}
274+
belong_tos = (collection.ancestors.first.reflect_on_all_associations(:belongs_to) rescue []).inject(HashWithIndifferentAccess.new()) do |retval, bt|
275+
klass = bt.klass || (bt.foreign_type.gsub('_type', '').classify.safe_constantize rescue nil)
276+
277+
if bt.foreign_key.present? && klass.present?
278+
retval[bt.name] = {:foreign_key => bt.foreign_key, :klass => klass} # Set the value into our Hash
279+
end
280+
281+
retval
282+
end
283+
269284
index = -1
270285

271286
cols.each do |name, _|
287+
# If this is a belongs_to, add an :if clause specifying a collection scope if
288+
if belong_tos.key?(name)
289+
cols[name][:if] ||= Proc.new { attributes[belong_tos[name][:foreign_key]].blank? } # :if => Proc.new { attributes[:user_id].blank? }
290+
end
291+
272292
# If an :if => ... option is passed, evaluate it now.
273293
# if the value is false, skip setting up this table_column and ensure col[name][:index] is nil
274294
# in table_column_with_defaults, we will select only table columns with an index
@@ -277,27 +297,28 @@ def initalize_table_columns(cols)
277297
next
278298
end
279299

280-
sql_column = (collection.columns rescue []).find { |column| column.name == name.to_s }
300+
sql_column = (collection.columns rescue []).find do |column|
301+
column.name == name.to_s || (belong_tos.key?(name) && column.name == belong_tos[name][:foreign_key])
302+
end
281303

282304
cols[name][:index] = (index += 1) # So first one is assigned 0
283305
cols[name][:array_column] ||= false
284306

285307
cols[name][:name] ||= name
286308
cols[name][:label] ||= name.titleize
287309
cols[name][:column] ||= (sql_table && sql_column) ? "\"#{sql_table.name}\".\"#{sql_column.name}\"" : name
288-
cols[name][:type] ||= sql_column.try(:type) || :string
310+
cols[name][:type] ||= (belong_tos.key?(name) ? :belongs_to : sql_column.try(:type)).presence || :string
289311
cols[name][:width] ||= nil
290312
cols[name][:sortable] = true if cols[name][:sortable] == nil
291-
cols[name][:filter] = initialize_table_column_filter(cols[name][:filter], cols[name][:type])
313+
cols[name][:filter] = initialize_table_column_filter(cols[name][:filter], cols[name][:type], belong_tos[name])
292314

293315
if cols[name][:partial]
294316
cols[name][:partial_local] ||= (sql_table.try(:name) || cols[name][:partial].split('/').last(2).first.presence || 'obj').singularize.to_sym
295317
end
296318
end
297-
298319
end
299320

300-
def initialize_table_column_filter(filter, col_type)
321+
def initialize_table_column_filter(filter, col_type, belongs_to)
301322
return {:type => :null, :when_hidden => false} if filter == false
302323

303324
if filter.kind_of?(Symbol)
@@ -309,6 +330,12 @@ def initialize_table_column_filter(filter, col_type)
309330
end
310331

311332
case col_type # null, number, select, number-range, date-range, checkbox, text(default)
333+
when :belongs_to
334+
{
335+
:type => :select,
336+
:when_hidden => false,
337+
:values => Proc.new { belongs_to[:klass].all.map { |obj| [obj.id, obj.to_s] }.sort { |x, y| x[1] <=> y[1] } }
338+
}.merge(filter)
312339
when :integer
313340
{:type => :number, :when_hidden => false}.merge(filter)
314341
when :boolean

lib/effective_datatables/version.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
module EffectiveDatatables
2-
VERSION = "0.3.15"
2+
VERSION = "0.3.16"
33
end

0 commit comments

Comments
 (0)