Permalink
Browse files

Changed api for column that accepts a query

  • Loading branch information...
Ionatan Wiznia
Ionatan Wiznia committed Mar 6, 2014
1 parent 87ff679 commit 41977ba573e5a16eae1da95df1ce25cefefe5c7b
View
@@ -9,7 +9,7 @@ group :development do
gem "debugger", :platform => "ruby_19"
- gem "byebug", :platform => "ruby_20"
+ gem "byebug", :platform => ["ruby_20", "ruby_21"]
gem "ruby-debug", :platform => "ruby_18"
gem "rspec"
View
@@ -88,23 +88,23 @@ def columns(*args)
end
# Defines new datagrid column
- #
+ #
# Arguments:
#
# * <tt>name</tt> - column name
# * <tt>options</tt> - hash of options
# * <tt>block</tt> - proc to calculate a column value
#
# Available options:
- #
+ #
# * <tt>:html</tt> - determines if current column should be present in html table and how is it formatted
- # * <tt>:order</tt> - determines if this column could be sortable and how.
- # The value of order is explicitly passed to ORM ordering method.
+ # * <tt>:order</tt> - determines if this column could be sortable and how.
+ # The value of order is explicitly passed to ORM ordering method.
# Ex: <tt>"created_at, id"</tt> for ActiveRecord, <tt>[:created_at, :id]</tt> for Mongoid
- # * <tt>:order_desc</tt> - determines a descending order for given column
+ # * <tt>:order_desc</tt> - determines a descending order for given column
# (only in case when <tt>:order</tt> can not be easily reversed by ORM)
- # * <tt>:order_by_value</tt> - used in case it is easier to perform ordering at ruby level not on database level.
- # Warning: using ruby to order large datasets is very unrecommended.
+ # * <tt>:order_by_value</tt> - used in case it is easier to perform ordering at ruby level not on database level.
+ # Warning: using ruby to order large datasets is very unrecommended.
# If set to true - datagrid will use column value to order by this column
# If block is given - datagrid will use value returned from block
# * <tt>:mandatory</tt> - if true, column will never be hidden with #column_names selection
@@ -113,13 +113,18 @@ def columns(*args)
# * <tt>:after</tt> - determines the position of this column, by adding it after the column passed here
#
# See: https://github.com/bogdan/datagrid/wiki/Columns for examples
- def column(name, options = {}, &block)
+ def column(name, options_or_query = {}, options = {}, &block)
+ if options_or_query.is_a?(String)
+ query = options_or_query
+ else
+ options = options_or_query
+ end
check_scope_defined!("Scope should be defined before columns")
block ||= lambda do |model|
model.send(name)
end
position = Datagrid::Utils.extract_position_from_options(columns_array, options)
- column = Datagrid::Columns::Column.new(self, name, default_column_options.merge(options), &block)
+ column = Datagrid::Columns::Column.new(self, name, query, default_column_options.merge(options), &block)
columns_array.insert(position, column)
end
@@ -148,7 +153,7 @@ def format(value, &block)
end
end
else
- # Ruby Object#format exists.
+ # Ruby Object#format exists.
# We don't want to change the behaviour and overwrite it.
super
end
@@ -212,7 +217,7 @@ def data(*column_names)
self.rows(*column_names).unshift(self.header(*column_names))
end
- # Return Array of Hashes where keys are column names and values are column values
+ # Return Array of Hashes where keys are column names and values are column values
# for each row in filtered datagrid relation.
#
# Example:
@@ -267,7 +272,7 @@ def to_csv(*column_names)
# Returns all columns selected in grid instance
#
# Examples:
- #
+ #
# MyGrid.new.columns # => all defined columns
# grid = MyGrid.new(:column_names => [:id, :name])
# grid.columns # => id and name columns
@@ -301,15 +306,15 @@ def column_by_name(name)
# Gives ability to have a different formatting for CSV and HTML column value.
#
# Example:
- #
+ #
# column(:name) do |model|
# format(model.name) do |value|
# content_tag(:strong, value)
# end
# end
#
# column(:company) do |model|
- # format(model.company.name) do
+ # format(model.company.name) do
# render :partial => "company_with_logo", :locals => {:company => model.company }
# end
# end
@@ -325,7 +330,7 @@ def format(value, &block)
# Allows to access column values
#
# Example:
- #
+ #
# class MyGrid
# scope { User }
# column(:id)
@@ -25,9 +25,9 @@ def html_value(context)
end
end
- attr_accessor :grid_class, :options, :data_block, :name, :html_block
+ attr_accessor :grid_class, :options, :data_block, :name, :html_block, :query
- def initialize(grid_class, name, options = {}, &block)
+ def initialize(grid_class, name, query, options = {}, &block)
self.grid_class = grid_class
self.name = name.to_sym
self.options = options
@@ -40,6 +40,7 @@ def initialize(grid_class, name, options = {}, &block)
self.html_block = options[:html]
end
end
+ self.query = query
end
def data_value(model, grid)
@@ -54,7 +55,7 @@ def label
end
def header
- self.options[:header] ||
+ self.options[:header] ||
I18n.translate(self.name, :scope => "datagrid.#{self.grid_class.param_name}.columns", :default => self.name.to_s.humanize )
end
@@ -84,25 +85,21 @@ def order_by_value?
def order_desc
return nil unless order
- self.options[:order_desc]
+ self.options[:order_desc]
end
def html?
options[:html] != false
end
-
+
def data?
self.data_block != nil
end
-
+
def mandatory?
!! options[:mandatory]
end
- def select
- options[:select]
- end
-
def inspect
"#<Datagird::Columns::Column #{grid_class}##{name} #{options.inspect}>"
end
@@ -4,16 +4,16 @@ class ActiveRecord < AbstractDriver
def self.match?(scope)
return false unless defined?(::ActiveRecord)
- if scope.is_a?(Class)
+ if scope.is_a?(Class)
scope.ancestors.include?(::ActiveRecord::Base)
else
- scope.is_a?(::ActiveRecord::Relation)
+ scope.is_a?(::ActiveRecord::Relation)
end
end
def to_scope(scope, columns = [])
# Model class or Active record association
- # ActiveRecord association class hides itself under an Array
+ # ActiveRecord association class hides itself under an Array
# We can only reveal it by checking if it respond to some specific
# to ActiveRecord method like #scoped
scope = if scope.is_a?(::ActiveRecord::Relation)
@@ -25,10 +25,12 @@ def to_scope(scope, columns = [])
else
scope
end
- select_columns = columns.select(&:select)
- if select_columns.present?
- scope = scope.select("#{scope.quoted_table_name}.*")
- select_columns.each {|column| scope = scope.select(column.select) }
+ query_columns = columns.map(&:query).compact
+ if query_columns.present?
+ if scope.select_values.empty?
+ scope = scope.select(Arel.respond_to?(:star) ? scope.klass.arel_table[Arel.star] : "#{scope.quoted_table_name}.*")
+ end
+ scope = scope.select(*query_columns)
end
scope
end
@@ -104,16 +106,16 @@ def batch_map(scope, batch_size, &block)
end
result
end
-
+
protected
def prefix_table_name(scope, field)
has_column?(scope, field) ? [scope.table_name, field].join(".") : field
end
def contains_predicate
- defined?(::ActiveRecord::ConnectionAdapters::PostgreSQLAdapter) &&
- ::ActiveRecord::Base.connection.is_a?(::ActiveRecord::ConnectionAdapters::PostgreSQLAdapter) ?
+ defined?(::ActiveRecord::ConnectionAdapters::PostgreSQLAdapter) &&
+ ::ActiveRecord::Base.connection.is_a?(::ActiveRecord::ConnectionAdapters::PostgreSQLAdapter) ?
'ilike' : 'like'
end
@@ -17,8 +17,8 @@
end
it "should support specifying select options in columns" do
- Entry.create!
- a = subject.to_scope(Entry.group(:name), [Datagrid::Columns::Column.new(SimpleReport, :sum_id, {:select => 'sum(entries.id) sum_id'})])
- a.first.sum_id.should == 1
+ Entry.create!(:group_id => 1)
+ a = subject.to_scope(Entry.group(:name), [Datagrid::Columns::Column.new(SimpleReport, :sum_group_id, 'sum(entries.group_id) sum_group_id')])
+ a.first.sum_group_id.should == 1
end
end

0 comments on commit 41977ba

Please sign in to comment.