Skip to content

Commit

Permalink
Add respond_with handling to all model controller actions. Fix up han…
Browse files Browse the repository at this point in the history
…dling of non-`errors-ok` ajax. update lifecycle actions to new style.
  • Loading branch information
bryanlarsen committed Sep 6, 2012
1 parent 5297bab commit b0641b6
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 101 deletions.
8 changes: 8 additions & 0 deletions hobo/CHANGES-1.4.txt
Expand Up @@ -646,6 +646,14 @@ The signature for the function update_response and friends has changed. This s
end
end

## default controller actions now use respond_with

All Hobo model controller actions now use [respond_with](http://apidock.com/rails/ActionController/MimeResponds/respond_with) where appropriate. This means that you can create an API interface for a controller simply by adding:

respond_to :html, :json, :xml

See [respond_to](http://apidock.com/rails/ActionController/MimeResponds/ClassMethods/respond_to) and Google for "respond_with" for more information.

### before-unload

`<form>` has gained a new option, before-unload, which adds an
Expand Down
5 changes: 1 addition & 4 deletions hobo/TODO-1.4.txt
Expand Up @@ -45,9 +45,6 @@ you notice any such omissions, please let us know, it is easy to fix..
* multiple file support for AJAX uploads
* cache: redis support
* fixup deprecation warnings
* port to Rails 3.2 and/or 4.0
* nuke any remaining prototype code
* add a sane default for non-AJAX JSON requests.
* trawl the lighthouse && pull requests
* steal the tags from Portal
* fixup hobo-contrib
Expand All @@ -59,4 +56,4 @@ you notice any such omissions, please let us know, it is easy to fix..
* create a bootstrap theme
* add theme chooser to setup wizard
* add support for has-one
* convert old Hobo plugins: imaginary-dryml, hoboyui
* convert old Hobo plugins: imaginary-dryml, hoboyui, nice theme
9 changes: 0 additions & 9 deletions hobo/lib/hobo/controller.rb
Expand Up @@ -107,15 +107,6 @@ def ajax_update_response(render_specs, results={}, options={})
render :js => page
end

# use this function to send arbitrary bits of javascript
def ajax_response(response, options)
page = options[:preamble] || "var _update = typeof Hobo == 'undefined' ? Element.update : Hobo.updateElement;\n"
page << response
page << options[:postamble] if options[:postamble]
render :js => page
end


# dryml does not use layouts
def action_has_layout?
false
Expand Down
174 changes: 86 additions & 88 deletions hobo/lib/hobo/controller/model.rb
Expand Up @@ -32,6 +32,8 @@ def included(base)
rescue_from Hobo::PermissionDeniedError, :with => :permission_denied
rescue_from Hobo::Model::Lifecycles::LifecycleKeyError, :with => :permission_denied

respond_to :html

alias_method_chain :render, :hobo_model

end
Expand Down Expand Up @@ -386,12 +388,25 @@ def re_render_form(default_action=nil)
end


def destination_after_submit(record=this, destroyed=false)
def destination_after_submit(*args)
options = args.extract_options!
destroyed = args[1]
after_submit = params[:after_submit]

# The after_submit post parameter takes priority
(after_submit == "stay-here" ? url_for_page_path : after_submit) ||

# Then try options[:redirect]
((o=options[:redirect]) && begin
if o.is_a?(Symbol)
object_url(@this, o)
elsif o.is_a?(String) || o.is_a?(Hash)
o
else
object_url(*Array(o))
end
end)

# Then try the record's show page
(!destroyed && object_url(@this)) ||

Expand All @@ -411,24 +426,6 @@ def owning_object
end


def redirect_after_submit(*args)
options = args.extract_options!
o = options[:redirect]
if o
url = if o.is_a?(Symbol)
object_url(this, o)
elsif o.is_a?(String) || o.is_a?(Hash)
o
else
object_url(*Array(o))
end
redirect_to url
else
redirect_to destination_after_submit(*args)
end
end


def response_block(&b)
if b
respond_to do |format|
Expand Down Expand Up @@ -521,13 +518,17 @@ def show_response
if request.xhr? && params[:render]
hobo_ajax_response
render :nothing => true unless performed?
else
respond_with(self.this)
end
end

def index_response
if request.xhr? && params[:render]
hobo_ajax_response(:page => :blah)
render :nothing => true unless performed?
else
respond_with(self.this)
end
end

Expand All @@ -547,6 +548,7 @@ def hobo_create(*args, &b)
self.this = new_for_create(attributes)
this.user_save(current_user)
end
flash_notice (ht( :"#{@this.class.to_s.underscore}.messages.create.success", :default=>["The #{@this.class.model_name.human} was created successfully"])) if valid?
response_block(&b) || create_response(:new, options)
end

Expand All @@ -561,6 +563,7 @@ def hobo_create_for(owner_association, *args, &b)
self.this = association.new(attributes)
this.save
end
flash_notice (ht( :"#{@this.class.to_s.underscore}.messages.create.success", :default=>["The #{@this.class.model_name.human} was created successfully"])) if valid?
response_block(&b) || create_response(:"new_for_#{name_of_auto_action_for(owner_association)}", options)
end

Expand All @@ -587,30 +590,31 @@ def flash_notice(message)
end


def create_response(new_action, options={}, &b)
flash_notice (ht( :"#{@this.class.to_s.underscore}.messages.create.success", :default=>["The #{@this.class.model_name.human} was created successfully"])) if valid?
def create_response(new_action, options={})
valid = valid? # valid? can be expensive
if params[:render]
if (params[:render_options] && params[:render_options][:errors_ok]) || valid
hobo_ajax_response

response_block(&b) or begin
valid = valid? # valid? can be expensive
if params[:render]
if (params[:render_options] && params[:render_options][:errors_ok]) || valid
hobo_ajax_response

# Maybe no ajax requests were made
render :nothing => true unless performed?
else
errors = @this.errors.full_messages.join('\n')
message = ht( :"#{this.class.to_s.underscore}.messages.create.error", :errors=>errors,:default=>["Couldn't create the #{this.class.name.titleize.downcase}.\n #{errors}"])
ajax_response("alert('#{message}');", params[:render_options])
end
else
if valid
redirect_after_submit options
else
re_render_form(new_action)
end
end
end
# Maybe no ajax requests were made
render :nothing => true unless performed?
else
errors = @this.errors.full_messages.join('\n')
message = ht( :"#{this.class.to_s.underscore}.messages.create.error", :errors=>errors,:default=>["Couldn't create the #{this.class.name.titleize.downcase}.\n #{errors}"])
render :js => "alert(#{message.to_json});\n"
end
else
location = destination_after_submit(options)
respond_with(self.this, :location => location) do |format|
format.html do
if valid
redirect_to location
else
re_render_form(new_action)
end
end
end
end
end


Expand Down Expand Up @@ -642,7 +646,7 @@ def hobo_update(*args, &b)
#
# parameters:
# valid is a cache of valid?
# options is passed through to redirect_after_submit
# options is passed through to destination_after_submit
def update_response(valid=nil, options={})
# valid? can be expensive, cache it
valid = valid? if valid.nil?
Expand All @@ -656,15 +660,19 @@ def update_response(valid=nil, options={})
errors = @this.errors.full_messages.join('\n')
message = ht(:"#{@this.class.to_s.underscore}.messages.update.error", :default=>["There was a problem with that change\\n#{errors}"], :errors=>errors)

ajax_response("alert('#{message}');", params[:render_options])
render :js => "alert(#{message.to_json});\n"
end
else
if valid
flash_notice (ht(:"#{@this.class.to_s.underscore}.messages.update.success", :default=>["Changes to the #{@this.class.model_name.human} were saved"]))

redirect_after_submit options
else
re_render_form(:edit)
location = destination_after_submit(options)
respond_with(self.this, :location => location) do |format|
format.html do
if valid
flash_notice (ht(:"#{@this.class.to_s.underscore}.messages.update.success", :default=>["Changes to the #{@this.class.model_name.human} were saved"]))
redirect_to location
else
re_render_form(:edit)
end
end
end
end
end
Expand All @@ -674,16 +682,16 @@ def hobo_destroy(*args, &b)
self.this ||= args.first || find_instance
this.user_destroy(current_user)
flash_notice ht( :"#{model.to_s.underscore}.messages.destroy.success", :default=>["The #{model.name.titleize.downcase} was deleted"])
destroy_response(options, &b)
response_block(&b) || destroy_response(options, &b)
end


def destroy_response(options={}, &b)
response_block(&b) or
respond_to do |wants|
wants.html { redirect_after_submit(this, true, options) }
wants.js { hobo_ajax_response || render(:nothing => true) }
end
def destroy_response(options={})
if params[:render]
hobo_ajax_response || render(:nothing => true)
else
respond_with(self.this, :location => destination_after_submit(this, true, options))
end
end


Expand All @@ -701,26 +709,32 @@ def creator_page_action(name, options={}, &b)
def do_creator_action(name, options={}, &b)
@creator = model::Lifecycle.creator(name)
self.this = @creator.run!(current_user, attribute_parameters)
response_block(&b) or
if valid?
respond_to do |wants|
wants.html { redirect_after_submit(options) }
wants.js { hobo_ajax_response || render(:nothing => true) }
end
response_block(&b) || do_creator_response(name, options)
end

def do_creator_response(name, options)
if valid?
if params[:render]
hobo_ajax_response || render(:nothing => true)
else
this.exempt_from_edit_checks = true
respond_to do |wants|
# errors is used by the translation helper, ht, below.
errors = this.errors.full_messages.join("\n")
location = destination_after_submit(options)
respond_with(self.this, :location => location)
end
else
this.exempt_from_edit_checks = true
if params[:render] && params[:render_options] && params[:render_options][:errors_ok]
hobo_ajax_response
render :nothing => true unless performed?
else
# errors is used by the translation helper, ht, below.
errors = this.errors.full_messages.join("\n")
respond_with(self.this) do |wants|
wants.html { re_render_form(name) }
wants.js { render(:status => 500,
:text => ht(:"#{@this.class.to_s.underscore}.messages.creator.error", :default=>["Couldn't do creator #{name}.\n#{errors}"], :name=>name, :errors=>errors)
)}
end
end
end
end


def prepare_transition(name, options)
key = options.delete(:key) || params[:key]

Expand All @@ -744,25 +758,9 @@ def do_transition_action(name, *args, &b)
options = args.extract_options!
@transition = prepare_transition(name, options)
@transition.run!(this, current_user, attribute_parameters)
response_block(&b) or
if valid?
respond_to do |wants|
wants.html { redirect_after_submit(options) }
wants.js { hobo_ajax_response || render(:nothing => true) }
end
else
respond_to do |wants|
# errors is used by the translation helper, ht, below.
errors = this.errors.full_messages.join("\n")
wants.html { re_render_form(name) }
wants.js { render(:status => 500,
:text => ht(:"#{@this.class.to_s.underscore}.messages.transition.error", :default=>["Couldn't do transition #{name}.\n#{errors}"], :name=>name, :errors=>errors)
)}
end
end
response_block(&b) || update_response(nil, options)
end


# --- Miscelaneous Actions --- #

# Hobo 1.3's name one uses params[:query], jQuery-UI's autocomplete
Expand Down

0 comments on commit b0641b6

Please sign in to comment.