Skip to content

Commit

Permalink
WIP: dsl refactoring
Browse files Browse the repository at this point in the history
milestone: all tests pass
  • Loading branch information
bbenezech committed Dec 26, 2011
1 parent 3317182 commit dd8b156
Show file tree
Hide file tree
Showing 21 changed files with 221 additions and 168 deletions.
6 changes: 3 additions & 3 deletions app/helpers/rails_admin/form_builder.rb
Expand Up @@ -10,15 +10,15 @@ def generate(options = {})
:model_config => @template.instance_variable_get(:@model_config),
:nested_in => false
})

options[:model_config].send(options[:action]).with(:form => self, :object => @object, :view => @template).visible_groups.map do |fieldset|
groups = options[:model_config].send(options[:action]).with(:form => self, :object => @object, :view => @template).visible_groups
groups.map do |fieldset|
fieldset_for fieldset, options[:nested_in]
end.join.html_safe +
(options[:nested_in] ? '' : @template.render(:partial => 'submit_buttons'))
end

def fieldset_for fieldset, nested_in
if (fields = fieldset.fields.map{ |f| f.with(:form => self, :object => @object, :view => @template) }.select(&:visible?)).length > 0
if (fields = fieldset.with(:form => self, :object => @object, :view => @template).visible_fields).length > 0
@template.content_tag :fieldset do
@template.content_tag(:legend, fieldset.label.html_safe + (fieldset.help.present? ? @template.content_tag(:small, fieldset.help) : ''), :style => "#{fieldset.label == I18n.translate("admin.new.basic_info") ? 'display:none' : ''}") +
fields.map{ |field| field_wrapper_for(field, nested_in) }.join.html_safe
Expand Down
6 changes: 3 additions & 3 deletions app/views/rails_admin/main/export.html.haml
Expand Up @@ -17,15 +17,15 @@
- if field.association? && field.association[:polymorphic]
%label{:for => "schema_#{list}_#{field.method_name}"}
= check_box_tag "schema[#{list}][]", field.method_name, true, { :id => "schema_#{list}_#{field.method_name}" }
%strong= @abstract_model.model.human_attribute_name(field.method_name)
%strong= field.label + " [id]"
- polymorphic_type_column_name = @abstract_model.properties.find {|p| field.association[:foreign_type] == p[:name] }[:name]
%label{:for => "schema_#{list}_#{polymorphic_type_column_name}"}
= check_box_tag "schema[#{list}][]", polymorphic_type_column_name, true, { :id => "schema_#{list}_#{polymorphic_type_column_name}" }
%strong= @abstract_model.model.human_attribute_name(polymorphic_type_column_name)
%strong= field.label + " [type]"
- else
%label{:for => "schema_#{list}_#{field.name}"}
= check_box_tag "schema[#{list}][]", field.name, true, { :id => "schema_#{list}_#{field.name}" }
%strong= @abstract_model.model.human_attribute_name(field.name)
%strong= field.label
- visible_fields.select{ |f| f.association? && !f.association[:polymorphic] }.each do |field|
.span5.clearfix{:style => 'float:left;'}
- association = field.association
Expand Down
14 changes: 13 additions & 1 deletion lib/rails_admin/config.rb
Expand Up @@ -210,6 +210,16 @@ def model(entity, &block)
config.instance_eval(&block) if block
config
end

def default_hidden_fields=(fields)
if fields.is_a?(Array)
@default_hidden_fields = {}
@default_hidden_fields[:edit] = fields
@default_hidden_fields[:show] = fields
else
@default_hidden_fields = fields
end
end

# Returns all model configurations
#
Expand All @@ -229,7 +239,9 @@ def reset
@authenticate = nil
@authorize = nil
@current_user = nil
@default_hidden_fields = [:id, :created_at, :created_on, :deleted_at, :updated_at, :updated_on, :deleted_on]
@default_hidden_fields = {}
@default_hidden_fields[:edit] = [:id, :created_at, :created_on, :deleted_at, :updated_at, :updated_on, :deleted_on]
@default_hidden_fields[:show] = [:id, :created_at, :created_on, :deleted_at, :updated_at, :updated_on, :deleted_on]
@default_items_per_page = 20
@default_search_operator = 'default'
@excluded_models = []
Expand Down
28 changes: 18 additions & 10 deletions lib/rails_admin/config/fields/base.rb
@@ -1,17 +1,17 @@
require 'active_support/core_ext/string/inflections'
require 'rails_admin/config/base'
require 'rails_admin/config/hideable'
require 'rails_admin/config/has_groups'
require 'rails_admin/config/fields'
require 'rails_admin/config/fields/groupable'
require 'rails_admin/config/fields/association'
require 'rails_admin/config/fields/groupable'


module RailsAdmin
module Config
module Fields
class Base < RailsAdmin::Config::Base
attr_reader :name, :properties
attr_accessor :defined, :order
attr_accessor :defined, :order, :section

def self.inherited(klass)
klass.instance_variable_set("@view_helper", :text_field)
Expand All @@ -21,16 +21,14 @@ def self.inherited(klass)

def initialize(parent, name, properties)
super(parent)

@defined = false
@name = name
@order = 0
@properties = properties

# If parent is able to group fields the field should be aware of it
if parent.kind_of?(RailsAdmin::Config::HasGroups)
extend RailsAdmin::Config::Fields::Groupable
end
@section = parent

extend RailsAdmin::Config::Fields::Groupable
end

register_instance_option(:css_class) do
Expand Down Expand Up @@ -185,7 +183,17 @@ def virtual?
register_instance_option :read_only do
not editable
end


register_instance_option :visible? do
returned = true
(RailsAdmin.config.default_hidden_fields || {}).each do |section, fields|
if self.section.is_a?("RailsAdmin::Config::Sections::#{section.to_s.camelize}".constantize)
returned = false if fields.include?(self.name)
end
end
returned
end

def editable
return false if @properties && @properties[:read_only]
role = bindings[:view].controller.send(:_attr_accessible_role)
Expand Down
1 change: 0 additions & 1 deletion lib/rails_admin/config/fields/factories/devise.rb
@@ -1,7 +1,6 @@
require 'rails_admin/config/fields'
require 'rails_admin/config/fields/types'
require 'rails_admin/config/fields/types/password'
require 'rails_admin/config/sections/update'

# Register a custom field factory for devise model
RailsAdmin::Config::Fields.register_factory do |parent, properties, fields|
Expand Down
10 changes: 6 additions & 4 deletions lib/rails_admin/config/fields/group.rb
Expand Up @@ -9,9 +9,11 @@ class Group < RailsAdmin::Config::Base
include RailsAdmin::Config::Hideable

attr_reader :name
attr_accessor :section

def initialize(parent, name)
super(parent)
@section = parent
@name = name.to_s.tr(' ', '_').downcase.to_sym
end

Expand All @@ -20,7 +22,7 @@ def initialize(parent, name)
#
# @see RailsAdmin::Config::Fields.field
def field(name, type = nil, &block)
field = parent.field(name, type, &block)
field = section.field(name, type, &block)
# Directly manipulate the variable instead of using the accessor
# as group probably is not yet registered to the parent object.
field.instance_variable_set("@group", self)
Expand All @@ -29,14 +31,14 @@ def field(name, type = nil, &block)

# Reader for fields attached to this group
def fields
parent.fields.select {|f| self == f.group }
section.fields.select {|f| self == f.group }
end

# Defines configuration for fields by their type
#
# @see RailsAdmin::Config::Fields.fields_of_type
def fields_of_type(type, &block)
selected = fields.select {|f| type == f.type }
selected = section.fields.select {|f| type == f.type }
if block
selected.each {|f| f.instance_eval &block }
end
Expand All @@ -45,7 +47,7 @@ def fields_of_type(type, &block)

# Reader for fields that are marked as visible
def visible_fields
fields.select {|f| f.with(bindings).visible? }.map{|f| f.with(bindings)}
section.visible_fields.map{|f| f.with(bindings)}.select {|f| self == f.group }
end

# Configurable group label which by default is group's name humanized.
Expand Down
15 changes: 6 additions & 9 deletions lib/rails_admin/config/fields/types/password.rb
@@ -1,5 +1,3 @@
require 'rails_admin/config/fields'
require 'rails_admin/config/sections/list'
require 'rails_admin/config/fields/types/string'

module RailsAdmin
Expand All @@ -17,21 +15,20 @@ def self.column_names
@column_names
end

def initialize(parent, name, properties)
super(parent, name, properties)
hide if parent.kind_of?(RailsAdmin::Config::Sections::List)
end

register_instance_option(:formatted_value) do
register_instance_option :formatted_value do
"".html_safe
end

# Password field's value does not need to be read
def value
""
end

register_instance_option :visible do
self.section.is_a?(RailsAdmin::Config::Sections::Edit)
end

register_instance_option(:pretty_value) do
register_instance_option :pretty_value do
'*****'
end
end
Expand Down
83 changes: 50 additions & 33 deletions lib/rails_admin/config/has_fields.rb
Expand Up @@ -4,7 +4,7 @@ module Config
module HasFields
# Defines a configuration for a field.
def field(name, type = nil, add_to_section = true, &block)
field = @fields.find {|f| name == f.name }
field = _fields.find {|f| name == f.name }

# some fields are hidden by default (belongs_to keys, has_many associations in list views.)
# unhide them if config specifically defines them
Expand All @@ -13,26 +13,26 @@ def field(name, type = nil, add_to_section = true, &block)
# Specify field as virtual if type is not specifically set and field was not
# found in default stack
if field.nil? && type.nil?
field = (@fields << RailsAdmin::Config::Fields::Types.load(:string).new(self, name, {})).last
field = (_fields << RailsAdmin::Config::Fields::Types.load(:string).new(self, name, {})).last

# Register a custom field type if one is provided and it is different from
# one found in default stack
elsif !type.nil? && type != (field.nil? ? nil : field.type)
@fields.delete(field) unless field.nil?
properties = parent.abstract_model.properties.find {|p| name == p[:name] }
field = (@fields << RailsAdmin::Config::Fields::Types.load(type).new(self, name, properties)).last
_fields.delete(field) unless field.nil?
properties = abstract_model.properties.find {|p| name == p[:name] }
field = (_fields << RailsAdmin::Config::Fields::Types.load(type).new(self, name, properties)).last
end

# If field has not been yet defined add some default properties
if add_to_section && !field.defined
field.defined = true
field.order = @fields.select(&:defined).length
field.order = _fields.select(&:defined).length
end

# If a block has been given evaluate it and sort fields after that
if block
field.instance_eval &block
@fields.sort! {|a, b| a.order <=> b.order }
_fields.sort! {|a, b| a.order <=> b.order }
end
field
end
Expand All @@ -46,10 +46,10 @@ def configure(name, type = nil, &block)
# or include fields by conditions if no field names
def include_fields(*field_names, &block)
if field_names.empty?
@fields.select {|f| f.instance_eval &block }.each do |f|
_fields.select {|f| f.instance_eval &block }.each do |f|
unless f.defined
f.defined = true
f.order = @fields.select(&:defined).length
f.order = _fields.select(&:defined).length
end
end
else
Expand All @@ -60,8 +60,8 @@ def include_fields(*field_names, &block)
# exclude fields by name or by condition (block)
def exclude_fields(*field_names, &block)
block ||= lambda { |f| field_names.include?(f.name) }
@fields.each {|f| f.defined = true } if @fields.select(&:defined).empty?
@fields.select {|f| f.instance_eval &block }.each {|f| f.defined = false }
_fields.each {|f| f.defined = true } if _fields.select(&:defined).empty?
_fields.select {|f| f.instance_eval &block }.each {|f| f.defined = false }
end

# API candy
Expand All @@ -72,46 +72,63 @@ def include_all_fields
include_fields_if() { true }
end


# Returns all field configurations for the model configuration instance. If no fields
# have been defined returns all fields. Defined fields are sorted to match their
# order property. If order was not specified it will match the order in which fields
# were defined.
#
# If a block is passed it will be evaluated in the context of each field
def fields(*field_names,&block)
return all_fields if field_names.empty? && !block

if field_names.empty?
defined = @fields.select {|f| f.defined }
defined.sort! {|a, b| a.order <=> b.order }
defined = @fields if defined.empty?
if block
defined.each {|f| f.instance_eval &block }
end
defined
defined = _fields.select {|f| f.defined }
defined = _fields if defined.empty?
else
defined = field_names.map{|field_name| @fields.find {|f| f.name == field_name } }
defined.map do |f|
unless f.defined
f.defined = true
f.order = @fields.select(&:defined).length
end
f.instance_eval(&block) if block
f
defined = field_names.map{|field_name| _fields.find {|f| f.name == field_name } }
end
defined.map do |f|
unless f.defined
f.defined = true
f.order = _fields.select(&:defined).length
end
f.instance_eval(&block) if block
f
end
end

# Defines configuration for fields by their type.
def fields_of_type(type, &block)
selected = @fields.select {|f| type == f.type }
if block
selected.each {|f| f.instance_eval &block }
end
selected
_fields.select {|f| type == f.type }.map! {|f| f.instance_eval &block } if block
end


# Accessor for all fields
def all_fields
fs = _fields(true)
(fs.select{|f| f.defined}.presence || fs)
end

# Get all fields defined as visible.
def visible_fields
fields.select {|f| f.with(bindings).visible? }.map{|f| f.with(bindings)}
all_fields.map {|f| f.with(bindings) }.select(&:visible).sort{|a, b| a.order <=> b.order }
end

protected

# Raw fields.
# Recursively returns parent section's raw fields (ultimatly: Model @fields)
# Duping it if accessed for modification.
def _fields(readonly = false)
return @_fields if @_fields
return @fields_readonly if readonly && @fields_readonly

if self.class == RailsAdmin::Config::Sections::Base # recursion tail
@fields_readonly = @_fields = RailsAdmin::Config::Fields.factory(self).map{|f| f.group :default; f }
else
@fields_readonly ||= parent.send(self.class.superclass.to_s.underscore.split('/').last)._fields(true).map{|f| f.section = self; f}.freeze
end
readonly ? @fields_readonly : (@_fields ||= @fields_readonly.map(&:clone))
end
end
end
Expand Down

0 comments on commit dd8b156

Please sign in to comment.