Skip to main content
March 23, 2026Noble Desktop Publishing Team/10 min read

Updating Quantities & Prices with AJAX

Master Dynamic Web Updates with Rails AJAX

Core Technologies Covered

AJAX Requests

Learn to update page content without full reloads using Rails built-in AJAX functionality. Improve user experience with seamless interactions.

Unobtrusive JavaScript

Implement best practices for separating front-end and back-end logic using data attributes and clean JavaScript integration.

Dynamic Price Updates

Build real-time shopping cart functionality that recalculates totals instantly when quantities change.

Topics Covered in This Ruby on Rails Tutorial:

Adding an AJAX Request

Exercise Overview

In this comprehensive section, we'll explore a powerful combination of Rails features including AJAX, web services, and email functionality. AJAX (Asynchronous JavaScript and XML) remains a cornerstone of modern web development, enabling seamless user experiences by updating page content without full page reloads. Rails makes AJAX implementation remarkably straightforward through its built-in helpers and conventions, allowing developers to create dynamic, responsive applications with minimal JavaScript code.

This exercise demonstrates practical AJAX implementation in a real-world e-commerce context, where users expect instant feedback when updating cart quantities. We'll transform a traditional form submission into a smooth, asynchronous operation that updates only the necessary page elements.

  1. If you completed the previous exercises, you can skip the following sidebar. We strongly recommend completing the previous exercises (8A-10B) before starting this one, as they establish the foundational cart functionality we'll be enhancing. If you haven't finished them, follow the setup instructions below.

    Prerequisites Required

    This exercise builds on previous work from exercises 8A-10B. If you haven't completed those, follow the Git checkout instructions to catch up to the required starting point.

If You Did Not Do the Previous Exercises (8A-10B)

  1. Close any files you may have open.
  2. Open the Finder and navigate to Class Files > yourname-Rails Class
  3. Open Terminal.
  4. Type cd and a single space (do NOT press Return yet).
  5. Drag the yourname-Rails Class folder from the Finder to the Terminal window and press ENTER.
  6. Run rm -rf nutty to delete your copy of the nutty site.
  7. Run git clone https://bitbucket.org/Noble Desktop/nutty.git to copy the That Nutty Guy Git repository.
  8. Type cd nutty to enter the new directory.
  9. Type git checkout 10B to bring the site up to the end of the previous exercise.
  10. Run bundle to install any necessary gems.
  11. Run yarn install --check-files to install JavaScript dependencies.

Quick Setup Process

1

Clean Previous Work

Remove existing nutty directory and clone fresh repository from Git

2

Checkout Correct Branch

Use Git checkout 10B to get the codebase at the right starting point

3

Install Dependencies

Run bundle and yarn install to ensure all gems and JavaScript packages are ready

Getting Started

Now we'll set up our development environment and prepare the necessary dependencies for AJAX functionality. Modern Rails applications rely on JavaScript package managers like Yarn to handle front-end dependencies efficiently.

  1. For this exercise, we'll continue working with the nutty folder located in Desktop > Class Files > yourname-Rails Class > nutty.

    If you haven't already done so, we strongly recommend opening the nutty folder in your code editor if it supports project-based editing (like Sublime Text, VS Code, or RubyMine). This provides better navigation and context switching between related files.

  2. Run yarn add jquery

    jQuery remains a practical choice for DOM manipulation in Rails applications, providing cross-browser compatibility and a familiar API for developers transitioning from traditional web development.

  3. You should still have a window with two tabs open in Terminal from the last exercise, with the first tab running the Rails server. The Rails development server needs to remain active to serve our AJAX requests. If you don't have the server running, complete the following sidebar.

    Environment Setup

    0/3

Restarting the Rails Server

  1. In Terminal, cd into the nutty folder:
  • Type cd and a space.
  • Drag the nutty folder from Desktop > Class Files > yourname-Rails Class onto the Terminal window (so it will type out the path for you).
  • In Terminal, hit Return to change directory.
  1. In Terminal, type the following:

    rails s
  2. Open a new tab (Cmd–T) leaving our server running in the old tab.
  3. In the new tab, cd into the nutty folder:
  • Type cd and a space.
  • Drag the nutty folder from Desktop > Class Files > yourname-Rails Class onto the Terminal window (so it will type out the path for you).
  • In Terminal, hit Return to change directory.
  • In the browser navigate to: localhost:3000

    If you see a Sign Out link at the top right, you are already signed in and you can skip the next step. The sign in instructions differ based on whether you already have login credentials.

  • If you already have a username and password: At the top right, click Sign In and sign in with the email and password you've been using.

    If you started from a prepared folder and don't have an account: Click the Sign up link, enter an email and password, then click Sign Up.

  • Click on a product to view its details.

  • Click Add To Cart to add the item to your shopping cart.

  • Notice there is an update button below the product quantity in your cart.

    We're going to transform this button into a seamless AJAX-powered feature. Rather than reloading the entire page when the update button is clicked—a jarring experience that disrupts the user's flow—we'll update only the specific elements that change: the individual item's Total Price, the cart's Subtotal, and the overall Total. This approach exemplifies modern web application design, where users expect immediate, contextual feedback without losing their place on the page.

  • Server Management Best Practice

    Keep the Rails server running in a dedicated Terminal tab while using a second tab for other commands. This workflow prevents interruptions during development.

    Making the Update Link Functional

    Let's begin by implementing the core AJAX functionality in our cart view. We'll start by converting the static update link into a functional form that can submit data asynchronously.

    1. In your code editor, open nutty > app > views > cart > index.html.erb

    2. Around line 35, locate the update link wrapped in an <a> tag. We need to convert this into a proper form tag so we can submit the quantity field along with the form submission.

    3. Wrap it in a form tag by adding the following bold code starting around line 34:

      <td>
         <%= form_with model: line_item, method: :patch, local: false do |f| %>
            <%= f.number_field :quantity, min: 1, max: 100 %>
            <a href="#">update</a>
         <% end %>
         <%= link_to 'remove', line_item_path(line_item), method: :delete %>
    4. Let's examine this code in detail:

      • line_item refers to the specific line item in question—each row in the shopping cart.
      • method: :patch calls the update method by default—exactly what we want because we're modifying an existing line item rather than creating or deleting one.
      • local: false is the critical parameter that transforms this into an AJAX request. This single option triggers Rails' built-in AJAX handling, which manages the asynchronous submission and response processing behind the scenes.
    5. We need to replace the update link with a proper submit button. Starting around line 36, delete the <a> tags and replace them with the following bold code:

      <%= f.number_field :quantity, min: 1, max: 100 %>
         <%= f.submit %>
      <% end %>

      NOTE: While this creates a button element, we'll style it to appear as a link to maintain consistency with the page's existing design language.

    6. Save the file and leave it open.

    7. In your code editor, open nutty > app > controllers > line_items_controller.rb

    8. Add the update method before the destroy method around line 15:

      end
      
      def update
         @line_item = LineItem.find(params[:id])
         @line_item.update(params.require(:line_item).permit(:quantity))
         @line_item.save
      end
      
      def destroy

      This method handles the PATCH request, finds the specific line item, updates its quantity with the submitted value, and saves the changes to the database.

    9. Save the file and close it.

    10. Test the functionality by adding an item to your cart and adjusting its quantity. You'll notice that nothing appears to change immediately, but if you manually reload the cart page, you'll see the adjusted quantity has been saved. This confirms our backend logic is working—now we need to implement the frontend response using Rails' AJAX capabilities.

    Key Implementation Components

    Form Integration

    Wrap update functionality in form_with helper to properly submit quantity data along with the AJAX request.

    AJAX Configuration

    Set local: false parameter to enable AJAX behavior instead of standard form submission with page reload.

    Controller Method Requirements

    The update method handles finding the line item, updating the quantity parameter, and saving changes. Rails automatically looks for a corresponding JavaScript view file.

    Fixing the Total Price

    Now we'll create the JavaScript response that updates the page dynamically. Instead of rendering traditional HTML, we'll use Rails' JavaScript template system to execute client-side updates after our AJAX request completes.

    1. Switch back to your code editor.

    2. Create a new file.

    3. Save it as update.js.erb into the nutty > app > views > line_items folder.

      This file extension is significant: the .js.erb format allows us to embed Ruby code within JavaScript, creating dynamic responses that can access our Rails instance variables and helper methods. Rails automatically renders this template when an AJAX request is made to the update action.

    4. Let's verify our JavaScript pipeline is working correctly before proceeding. Type:

      alert('<%= @line_item.title %>');
    5. Save the file and leave it open.

    6. Go to the browser and reload the cart: localhost:3000/cart

    7. Change the quantity of a product, then click update.

      An alert should pop up displaying the title of the item you updated. This demonstrates that our Ruby-to-JavaScript pipeline is functioning correctly, and we can seamlessly pass server-side data to client-side code.

    8. Click OK to dismiss the alert. Excellent—our foundation is solid!

    9. Go back to update.js.erb and delete the alert code.

    10. Now let's implement the actual functionality to update the Total Price field. Type:

      $('td.total-price').html('<%= number_to_currency @line_item.subtotal %>');
    11. Save the file.

    12. Go to the browser and navigate to: localhost:3000

    13. Add another product to your cart to create multiple line items.

    14. Change the quantity of a product, then click update.

      You'll notice that the Total Price changed for all items instead of just the one you updated. This occurs because our CSS selector td.total-price is too broad—it targets every element with that class. We need to make our targeting more specific using unobtrusive JavaScript techniques.

      Unobtrusive JavaScript is a modern best practice that separates behavior from presentation by using data attributes as hooks instead of inline event handlers or overly specific CSS selectors. This approach maintains cleaner separation of concerns and makes code more maintainable.

    15. In your code editor, open nutty > app > views > cart > index.html.erb

    16. Around line 45, add the following bold code to create a unique identifier for each line item:

      <td class="total-price" data-line-item-id="<%= line_item.id %>"><%= number_to_currency line_item.subtotal %></td>
    17. Save the file.

    18. In your code editor, open nutty > app > views > line_items > update.js.erb

    19. Replace the generic .total-price selector with the more specific code shown in bold:

      $('td[data-line-item-id=<%= @line_item.id %>].total-price').html('<%= number_to_currency @line_item.subtotal %>');
    20. Save the file.

    21. Go to the browser and reload the cart: localhost:3000/cart

    22. Change the quantity of a product, then click update.

      Perfect! Now only the specific product's price updates, demonstrating precise DOM targeting. Let's extend this functionality to update the cart's Subtotal and Total fields as well.

    JavaScript Response Implementation

    1

    Create JavaScript View

    Build update.js.erb file in line_items views folder to handle AJAX responses

    2

    Test Basic Functionality

    Use alert to verify JavaScript execution and Ruby variable access

    3

    Implement Targeted Updates

    Use data attributes and specific selectors to update only the relevant line item

    Selector Specificity Issue

    Using generic class selectors like 'td.total-price' will update all matching elements. Use unique data attributes to target specific line items accurately.

    Fixing the Subtotal & Total

    With individual line items updating correctly, we'll now implement updates for the order summary section. This requires updating the cart's overall calculations, which affects multiple users' perception of the transaction total.

    1. In your code editor, open nutty > app > views > cart > index.html.erb

    2. Around line 59, add a unique identifier to the subtotal field:

      <td>Subtotal</td>
         <td id="subtotal"><%= number_to_currency @cart.subtotal %></td>
      </tr>
    3. Around line 71, add a unique identifier to the total field:

      <td>Total</td>
         <td id="total"><%= number_to_currency @cart.total %></td>
      </tr>
    4. Save the file.

    5. In your code editor, open nutty > app > views > line_items > update.js.erb

    6. On the second line, add the following bold code to update all relevant totals:

      $('td[data-line-item-id=<%= @line_item.id %>]').html('<%= number_to_currency @line_item.subtotal %>');
      $('td#subtotal').html('<%= number_to_currency @cart.subtotal %>');
      $('td#total').html('<%= number_to_currency @cart.total %>');

      NOTE: The @cart instance variable is available here because it's created by our before_action callback load_cart_or_redirect_customer, which runs before every action in our controller.

    7. Save the file.

    8. Go to the browser and reload the cart: localhost:3000/cart

    9. Change the quantity of a product, then click update.

      Excellent! Now all totals update seamlessly and instantly. You've successfully implemented a professional-grade AJAX feature that provides immediate user feedback while maintaining data integrity. This pattern—updating specific page elements without full page reloads—is fundamental to modern web application development.

    10. Leave Terminal, your code editor, and browser open as we will continue building upon this foundation in the following exercise.

    Update Strategy Comparison

    FeatureIndividual ItemsCart Totals
    Selector Methoddata-line-item-id attributeunique ID attributes
    Update ScopeSingle line item onlyEntire cart summary
    Data Source@line_item.subtotal@cart.subtotal & @cart.total
    Recommended: Use targeted selectors for precise updates without affecting other cart elements
    Complete AJAX Integration

    With all three update targets implemented, users can modify quantities and see immediate price recalculations without any page reloads, creating a smooth shopping experience.

    Key Takeaways

    1Rails makes AJAX implementation straightforward with the local: false parameter in form helpers, automatically handling JavaScript responses
    2Create .js.erb view files to combine Ruby backend data with JavaScript DOM manipulation for dynamic updates
    3Use data attributes and specific selectors to target individual elements rather than updating all matching elements accidentally
    4Unobtrusive JavaScript separates presentation from logic by using data hooks instead of inline event handlers
    5The form_with helper with method: :patch automatically routes to the update controller action for existing records
    6Instance variables from controller actions are accessible in JavaScript view templates, enabling seamless data integration
    7Test basic JavaScript execution with simple alerts before implementing complex DOM manipulation
    8Shopping cart functionality benefits significantly from AJAX by providing instant feedback on price calculations without page reloads

    RELATED ARTICLES