Search code examples
rubyroutesvoltrb

Volt Framework Routing: When Are Actions Invoked?


I have an app that will show collections of images according to routes like this:

client '/{{_type}}', controller: 'main', action: 'index'
client '/', {}

The idea is that in MainController#index I will be able to look at params._type and do a query like this:

@uploads = store._uploads.where({category: params._type})

I have a nav bar with the links: /, /spotlight, /nature and so on. The first one matches the default route, so the index action is called. Then clicking on the nav item that links to /spotlight again calls the index action (the expected response). But... If I click on the nav item for nature the index action is not called, the collection is not refreshed, and I don't the the images that correspond to the category.

I may be taking a "Rails" view of how routing should work because I read this:

It should also be noted that if a link is clicked and the controller/view to render the new URL is within the current component (or an included component), the page will not be reloaded, the URL will be updated via the HTML5 history API, and the params hash will update to reflect the new URL. You can use these changes in params to render different views based on the URL.

The above citation from the Volt docs implies to me that I cannot count on routes to accomplish what I have outlined.

Can anyone clarify what the "correct" way to achieve this goal is?


Adding @ryanstout's answer as it affects this with appropriate code formatting.

client '/{{_type}}', controller: 'main', action: 'index'
#          ^^^  Note that the underscore may not be included
#               here or you will have an undefined value

def uploads
  store._uploads.where({category: params._type})
end

The second part allows for creating a reactive data source whose changes affect the page when the route changes.


Solution

  • The action method is called from view binding when the view file changes. In this case, your param is changing, but it does not affect the view file. One way to handle this situation is use methods instead of instance variables for uploads

    Instead of setting @uploads, do something like this:

    def uploads
      store._uploads.where({category: params._type})
    end
    

    Then in the view use uploads where you would have used @uploads. Now when params._type changes, anything depending on the uploads method will be invalidated and re-rendered.

    Hope that helps. Also, I'm considering adding something to the view binding to make this easier, but I think its good to why it behaves as it does.