Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

WIP: dsl refactoring

milestone: all tests pass
  • Loading branch information...
commit dd8b1564efdf96a251ab39843af0ba50b3224069 1 parent 3317182
@bbenezech bbenezech authored
View
6 app/helpers/rails_admin/form_builder.rb
@@ -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
View
6 app/views/rails_admin/main/export.html.haml
@@ -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
View
14 lib/rails_admin/config.rb
@@ -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
#
@@ -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 = []
View
28 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)
@@ -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
@@ -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)
View
1  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|
View
10 lib/rails_admin/config/fields/group.rb
@@ -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
@@ -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)
@@ -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
@@ -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.
View
15 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
@@ -17,12 +15,7 @@ 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
@@ -30,8 +23,12 @@ def initialize(parent, name, properties)
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
View
83 lib/rails_admin/config/has_fields.rb
@@ -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
@@ -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
@@ -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
@@ -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
@@ -72,6 +72,7 @@ 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
@@ -79,39 +80,55 @@ def include_all_fields
#
# 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
View
26 lib/rails_admin/config/has_groups.rb
@@ -2,37 +2,21 @@
module RailsAdmin
module Config
- module HasGroups
- # Access fields by their group
- def fields_of_group(group, &block)
- selected = @fields.select {|f| group == f.group }
- if block
- selected.each {|f| f.instance_eval &block }
- end
- selected
- end
-
+ module HasGroups
# Accessor for a group
#
# If group with given name does not yet exist it will be created. If a
# block is passed it will be evaluated in the context of the group
def group(name, &block)
- group = @groups.find {|g| name == g.name }
- if group.nil?
- group = (@groups << RailsAdmin::Config::Fields::Group.new(self, name)).last
- end
- group.instance_eval &block if block
+ group = parent.groups.find {|g| name == g.name }
+ group ||= (parent.groups << RailsAdmin::Config::Fields::Group.new(self, name)).last
+ group.tap{|g| g.section = self}.instance_eval &block if block
group
end
- # Reader for groups
- def groups
- @groups
- end
-
# Reader for groups that are marked as visible
def visible_groups
- groups.select {|g| g.visible? }
+ parent.groups.map {|f| f.section = self; f.with(bindings) }.select(&:visible)
end
end
end
View
2  lib/rails_admin/config/hideable.rb
@@ -5,7 +5,7 @@ module Hideable
# Visibility defaults to true.
def self.included(klass)
klass.register_instance_option(:visible?) do
- !root.excluded?
+ !root.try :excluded?
end
end
View
33 lib/rails_admin/config/model.rb
@@ -1,5 +1,10 @@
require 'rails_admin/config'
require 'rails_admin/config/base'
+require 'rails_admin/config/hideable'
+require 'rails_admin/config/has_groups'
+require 'rails_admin/config/fields/group'
+require 'rails_admin/config/fields'
+require 'rails_admin/config/has_fields'
require 'rails_admin/config/sections'
module RailsAdmin
@@ -8,7 +13,10 @@ module Config
class Model < RailsAdmin::Config::Base
include RailsAdmin::Config::Hideable
include RailsAdmin::Config::Sections
-
+
+ attr_reader :abstract_model
+ attr_accessor :groups
+
def initialize(entity)
@abstract_model = begin
if entity.kind_of?(RailsAdmin::AbstractModel)
@@ -19,6 +27,8 @@ def initialize(entity)
RailsAdmin::AbstractModel.new(entity.class)
end
end
+
+ @groups = [ RailsAdmin::Config::Fields::Group.new(self, :default).tap {|g| g.label{I18n.translate("admin.new.basic_info")} } ]
@bindings = {}
@parent = nil
@root = self
@@ -28,15 +38,6 @@ def excluded?
@excluded ||= !RailsAdmin::AbstractModel.all.map(&:model).include?(abstract_model.model)
end
- # Configure create and update views as a bulk operation with given block
- # or get update view's configuration if no block is given
- def edit(&block)
- return send(:update) unless block_given?
- [:create, :update].each do |s|
- send(s, &block)
- end
- end
-
def object_label
bindings[:object].send object_label_method
end
@@ -69,18 +70,10 @@ def object_label
false
end
- # Act as a proxy for the section configurations that actually
+ # Act as a proxy for the base section configuration that actually
# store the configurations.
def method_missing(m, *args, &block)
- responded_to = false
- [:create, :list, :show, :update, :export].each do |s|
- section = send(s)
- if section.respond_to?(m)
- responded_to = true
- section.send(m, *args, &block)
- end
- end
- raise NoMethodError.new("#{self} has no method #{m}") unless responded_to
+ self.send(:base).send(m, *args, &block)
end
end
end
View
11 lib/rails_admin/config/sections.rb
@@ -1,10 +1,14 @@
require 'active_support/core_ext/string/inflections'
+require 'rails_admin/config/sections/base'
+require 'rails_admin/config/sections/edit'
+require 'rails_admin/config/sections/update'
require 'rails_admin/config/sections/create'
+require 'rails_admin/config/sections/nested'
require 'rails_admin/config/sections/list'
-require 'rails_admin/config/sections/update'
require 'rails_admin/config/sections/export'
require 'rails_admin/config/sections/show'
+
module RailsAdmin
module Config
# Sections describe different views in the RailsAdmin engine. Configurable sections are
@@ -22,9 +26,7 @@ def self.included(klass)
name = name.to_s.downcase.to_sym
klass.send(:define_method, name) do |&block|
@sections = {} unless @sections
- unless @sections[name]
- @sections[name] = section.new(self)
- end
+ @sections[name] = section.new(self) unless @sections[name]
@sections[name].instance_eval &block if block
@sections[name]
end
@@ -33,3 +35,4 @@ def self.included(klass)
end
end
end
+
View
19 lib/rails_admin/config/sections/base.rb
@@ -0,0 +1,19 @@
+require 'rails_admin/config/base'
+require 'rails_admin/config/has_fields'
+require 'rails_admin/config/has_groups'
+
+module RailsAdmin
+ module Config
+ module Sections
+ # Configuration of the show view for a new object
+ class Base < RailsAdmin::Config::Base
+ include RailsAdmin::Config::HasFields
+ include RailsAdmin::Config::HasGroups
+
+ def initialize(parent)
+ super(parent)
+ end
+ end
+ end
+ end
+end
View
4 lib/rails_admin/config/sections/create.rb
@@ -1,10 +1,10 @@
-require 'rails_admin/config/sections/update'
+require 'rails_admin/config/sections/edit'
module RailsAdmin
module Config
module Sections
# Configuration of the edit view for a new object
- class Create < RailsAdmin::Config::Sections::Update
+ class Create < RailsAdmin::Config::Sections::Edit
end
end
end
View
11 lib/rails_admin/config/sections/edit.rb
@@ -0,0 +1,11 @@
+require 'rails_admin/config/sections/base'
+
+module RailsAdmin
+ module Config
+ module Sections
+ # Configuration of the edit view for an existing object
+ class Edit < RailsAdmin::Config::Sections::Base
+ end
+ end
+ end
+end
View
11 lib/rails_admin/config/sections/export.rb
@@ -1,17 +1,10 @@
-require 'rails_admin/config/base'
-require 'rails_admin/config/hideable'
+require 'rails_admin/config/sections/base'
module RailsAdmin
module Config
module Sections
# Configuration of the navigation view
- class Export < RailsAdmin::Config::Base
- include RailsAdmin::Config::HasFields
-
- def initialize(parent)
- super(parent)
- @fields = RailsAdmin::Config::Fields.factory(self)
- end
+ class Export < RailsAdmin::Config::Sections::Base
end
end
end
View
20 lib/rails_admin/config/sections/list.rb
@@ -1,26 +1,10 @@
-require 'rails_admin/config/base'
-require 'rails_admin/config/hideable'
-require 'rails_admin/config/fields'
-require 'rails_admin/config/has_fields'
+require 'rails_admin/config/sections/base'
module RailsAdmin
module Config
module Sections
# Configuration of the list view
- class List < RailsAdmin::Config::Base
- include RailsAdmin::Config::HasFields
-
- def initialize(parent)
- super(parent)
- # Populate @fields instance variable with model's properties
- @fields = RailsAdmin::Config::Fields.factory(self)
- @fields.each do |f|
- if f.association? && !f.kind_of?(RailsAdmin::Config::Fields::Types::BelongsToAssociation)
- f.visible false
- end
- end
- end
-
+ class List < RailsAdmin::Config::Sections::Base
register_instance_option :filters do
[]
end
View
10 lib/rails_admin/config/sections/nested.rb
@@ -0,0 +1,10 @@
+require 'rails_admin/config/sections/edit'
+
+module RailsAdmin
+ module Config
+ module Sections
+ class Nested < RailsAdmin::Config::Sections::Edit
+ end
+ end
+ end
+end
View
28 lib/rails_admin/config/sections/show.rb
@@ -1,33 +1,9 @@
-require 'rails_admin/config/base'
-require 'rails_admin/config/hideable'
-require 'rails_admin/config/fields'
-require 'rails_admin/config/has_fields'
-require 'rails_admin/config/has_groups'
-require 'rails_admin/config/fields/group'
+require 'rails_admin/config/sections/base'
module RailsAdmin
module Config
module Sections
- # Configuration of the show view for a new object
- class Show < RailsAdmin::Config::Base
- include RailsAdmin::Config::HasFields
- include RailsAdmin::Config::HasGroups
-
- def initialize(parent)
- super(parent)
- # Populate @fields instance variable with model's properties
- @groups = [ RailsAdmin::Config::Fields::Group.new(self, :default) ]
- @groups.first.label do
- I18n.translate("admin.new.basic_info")
- end
- @fields = RailsAdmin::Config::Fields.factory(self)
- @fields.each do |f|
- f.group :default
- if f.serial? || RailsAdmin::Config.default_hidden_fields.include?(f.name)
- f.hide
- end
- end
- end
+ class Show < RailsAdmin::Config::Sections::Base
end
end
end
View
5 lib/rails_admin/config/sections/update.rb
@@ -1,10 +1,9 @@
-require 'rails_admin/config/sections/show'
+require 'rails_admin/config/sections/edit'
module RailsAdmin
module Config
module Sections
- # Configuration of the edit view for an existing object
- class Update < RailsAdmin::Config::Sections::Show
+ class Update < RailsAdmin::Config::Sections::Edit
end
end
end
View
46 spec/lib/rails_admin_spec.rb
@@ -145,6 +145,52 @@
end
end
end
+
+
+ describe "DSL inheritance" do
+ it 'should be battle tested' do
+ RailsAdmin.config do |config|
+ config.model Fan do
+ field :name do
+ label do
+ @label ||= "modified base #{label}"
+ end
+ end
+ list do
+ field :name do
+ label do
+ @label ||= "modified list #{label}"
+ end
+ end
+ end
+ edit do
+ field :name do
+ label do
+ @label ||= "modified edit #{label}"
+ end
+ end
+ end
+ create do
+ field :name do
+ label do
+ @label ||= "modified create #{label}"
+ end
+ end
+ end
+ end
+
+ end
+ RailsAdmin.config(Fan).visible_fields.count.should == 1
+ RailsAdmin.config(Fan).visible_fields.first.label.should == 'modified base His Name'
+ RailsAdmin.config(Fan).list.visible_fields.first.label.should == 'modified list His Name'
+ RailsAdmin.config(Fan).export.visible_fields.first.label.should == 'modified base His Name'
+ RailsAdmin.config(Fan).edit.visible_fields.first.label.should == 'modified edit His Name'
+ RailsAdmin.config(Fan).create.visible_fields.first.label.should == 'modified create His Name'
+ RailsAdmin.config(Fan).update.visible_fields.first.label.should == 'modified edit His Name'
+ end
+
+ end
+
end
module ExampleModule
Please sign in to comment.
Something went wrong with that request. Please try again.