3

I have an action in a controller concern, which gets included in a controller. This action does not render a js.erb file as specified under a respond_to block. How do I properly get an action in a controller concern to successfully render a js.erb file (or any view, for that matter)? Is it a problem with my routes?

The link for the module action

= link_to image_tag("upvote.png"), 
send("vote_socionics_#{votable_name}_path", votable, vote_type: "#{s.type_two_im_raw}"),           
id: "vote-#{s.type_two_im_raw}",           
method: :post,          
remote: true

** The link for the controller action**

= link_to "whatever", characters_whatever_path, remote: true

controllers/characters_controller.rb

class CharactersController < ApplicationController
  include SocionicsVotesConcern

  def an_action
    respond_to do |format|
      format.js { render 'shared/vote_socionics' }   # This renders/executes the file
    end
  end

controllers/concerns/socionics_votes_concern.rb

module SocionicsVotesConcern
  extend ActiveSupport::Concern

  def vote_socionics
    respond_to do |format|
      format.js { render 'shared/vote_socionics' }   # This DOES NOT render/execute the file. Why?
    end
  end

end

views/shared/whatever.js.erb

  # js code that executes 

routes.rb

  concern :socionics_votes do
    member do
      post 'vote_socionics'
    end
  end

  resources :universes
  resources :characters,  concerns: :socionics_votes
  resources :celebrities, concerns: :socionics_votes
  resources :users,       concerns: :socionics_votes
ahnbizcad
  • 10,491
  • 9
  • 59
  • 85
  • 1
    Have you tried to extend module from `ApplicationController` ? – Abdul Baig Jul 16 '14 at 06:33
  • if so, then is including a module as a controller into a controller not a problem? This gave me the error as follows `wrong argument type Class (expected Module)` – ahnbizcad Jul 20 '14 at 01:39

2 Answers2

4
module SocionicsVotesConcern
  extend ActiveSupport::Concern

  included do 

    def vote_socionics
      respond_to do |format|
        format.js { render 'shared/vote_socionics' }
      end      
    end

  end

end

Wrap any actions/methods you define in the concern in an included do block. This way, anything in the block will be considered as if it was directly written in the includer object (i.e. the controller you're mixing this into)

With this solution, there are no loose ends, no idiosyncracies, no deviations from rails patterns. You will be able to use respond_to blocks, and won't have to deal with weird stuff.

ahnbizcad
  • 10,491
  • 9
  • 59
  • 85
1

I don't think this is Rails compatible man.

  • A controller action renders a view or redirects;
  • A module has methods. Methods executes code;

So just including the methods from a module named as a controller is not gonna work. What you really need to do is to call an action from controller A to controller B.So SocionicsVotesController would turn into a real controller class and you would use the redirect_to rails method.

You would have to specify the controller and action you're redirecting to, like:

redirect_to :controller => 'socionics', :action => 'index'

Or just:

redirect_to socionics_url

Which will send a HTTP 302 FOUND by default.

EDITED:

If you want to reuse the way your controller actions respond, while using rails 4 concerns, try this:

class CharactersController < ApplicationController
  include SocionicsVotesControllerConcerns  # not actually a controller, just a module.

  def an_action
    respond
  end


module SocionicsVoteControllerConcerns
    extend ActiveSupport::Concern

    def respond
      respond_to do |format|
        format.html { render 'whatever' }
        format.json { head :no_content }
      end
    end
end

I only got it to work when changing format.js to format.html, maybe because of this.

Community
  • 1
  • 1
Tiago Farias
  • 3,397
  • 1
  • 27
  • 30
  • the reason i have **SocionicsVotesController** as a module is because this goes into three different controllers (with models) for a polymorphic association. all of the related private methods would also go in each actual controller as well. Should i just repeat myself and put them in each controller without a module? I feel like this pattern will eventually come up, so i might as well learn how to do it now. – ahnbizcad Jul 16 '14 at 07:52
  • Isn't this kind of stuff what concerns were designed for in rails? – ahnbizcad Jul 16 '14 at 07:53
  • Concerns reinforce code reuse, sure. But if you want to respond with the same resource time and time again, maybe you should reuse your controller, not write 3 different ones. But, ok... lemme see how you can use concerns to do what you're trying to do. – Tiago Farias Jul 16 '14 at 18:38
  • hrm. that's a shame because i need it to be js for doing ajax-y stuffs – ahnbizcad Jul 17 '14 at 00:24
  • I see. But that is still doable. But of course, it's another problem. – Tiago Farias Jul 17 '14 at 01:52
  • No, its actually the main problem. Your answer answers another problem – ahnbizcad Jul 17 '14 at 06:31
  • A polymorphic association implies multiple resources. I'm not writing 3 diff controllers for the stuff that I put in the concern.l, or for the 1 resource. The point is to add in a concern module to a resource controller to give that resource some functionality. That's the whole point of a concern. I only showed one resource because showing more is irrelevant to the problem. – ahnbizcad Jul 17 '14 at 06:42
  • 1
    So, all you wanted was just to make format.js work inside your module? – Tiago Farias Jul 17 '14 at 06:47
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/57469/discussion-between-tiago-farias-and-gwho). – Tiago Farias Jul 17 '14 at 07:01