0

I'm working on an application in which a certain model is updated from a number of different locations using remote forms. I'm looking for a pattern to dynamically call the right JS callback after updating this model.

With a normal form this can be solved by passing a redirect url in the form itself and then redirecting to this url in the controller. The remote form side is harder: Should I pass a file name? Should I pass an arbitrary string and then switch on that string in a single .js.erb file? Any other suggestions?

Is this just a sign that the application should be restructured to prevent updating the same model from more than one location?

1
  • Re-usability is one of the qualities of object oriented programming, so using different code for the same thing is not good. Maybe you should pass a hidden form parameter or a url parameter (POST/GET form respectively), then switch on that and render accordingly from your controller (probably resulting to different views) Commented Mar 4, 2014 at 21:46

1 Answer 1

2

No it's fine If you can call the same controller action from different locations.

Your options:

1) Preferably this controller action can give the same response and will work for the different locations, ex. it just updates a container with a id which is present in all those locations.

2) You noted that redirects made things easy in the past, consider adding the following to your application controller:

def js_redirect_to(path, flash_messages = {})
  flash_messages.each { |type, message| flash[type] = message }

  respond_to do |format|
    format.js { render :js => "window.top.location='#{path}';" }
  end
end

This is the same signature as the normal redirect_to, it just allows you to redirect from a js request. Note that if you use turbolinks the js should be 'Turbolinks.visit(url);'.

3) If you really can't handle it generically like the options above, you could pass your JS namespace of the location you are submitting from in the form, and the controller calls the same method for all locations, it's just a different namespace. Ex:

Let say one location is from Pet administration, then in assets pet.js:

var pet = {
  load = function() {
    your page load js...
  },

  ... more functions...

  post_callback = function(html_segment1, html_segment2) {
    this is where you handle the form callback for pets...
    $('some_element').html(html_segment1);
    $('another_element').html(html_segment2);
  }
}

Construct more like these for other locations of your app. Using JS namespaces like this is anyway a good idea. Then your form submits a parameter :location => :pet to the controller, which responds with:

... your JS code that all pages should execute...
html_segment1 = "<%= escape_javascript(render 'some_partial') %>";
html_segment2 = "<%= escape_javascript(render 'other_partial') %>";
<%= @location %>.post_callback(html_segment1, html_segment2);

4) Use a widget gem, most popular is apotomo or cells.

5) Just use a case in the controller to render different views.

Hope this helps, let me know if you need clarification.

Sign up to request clarification or add additional context in comments.

3 Comments

Unfortunately the first options you suggest wont work since we'll be updating different UI components depending on what location is updating. The second option doesn't work since we don't actually want a page refresh. The third option is intriguing, but the question then becomes how do you properly pass the html to populate each individual component particular to the response from this location?
I've updated no.3 and added no.4. Sounds like this is might be a good fit for widgets.
Thanks Pierre, think the answer we'll use going forward is no. 5. It's not always pretty, but if you keep an eye on it seems like we'll be able to keep it under control

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.