🪟 Windows TippsThe Gemini desktop app is now available for Windows(11.09.2026 um 17:06 Uhr)
🕵️ SicherheitslückenBurn Out, Or Fade Away(14.09.2026 um 14:25 Uhr)
🪟 Windows TippsProfi-Edelstahlpfanne von WMF jetzt zum halben Preis erhältlich(15.09.2026 um 08:05 Uhr)
🪟 Windows TippsThe Gemini desktop app is now available for Windows(11.09.2026 um 17:06 Uhr)
🕵️ SicherheitslückenBurn Out, Or Fade Away(14.09.2026 um 14:25 Uhr)
🪟 Windows TippsProfi-Edelstahlpfanne von WMF jetzt zum halben Preis erhältlich(15.09.2026 um 08:05 Uhr)

🔧 Programmierung 🕛 vor 1 Jahr 10 Min Lesezeit
0

How to Develop an Air Quality Monitoring App with Ruby on Rails

↗ Quelle (dev.to)
🗣️ Stimme:
📑 Inhaltsübersicht

Prerequisites:




  • Ruby

  • sqlite3

  • Rails Installer






Install the app






CODE
rails new air_quality_app









serve the application






CODE
cd air_quality_app

bin/rails server






visit your browser with this link





Create a controller



To create FeedsController and its index action, run the controller generator in the terminal.




CODE
bin/rails generate controller Feeds index 









install the Waqi Ruby SDK



Add this line to your application's Gemfile:




CODE
gem 'waqi-ruby'






And then execute:




CODE
bundle




Or install it yourself as:




CODE
gem install waqi-ruby




You need a token to conveniently access the Air QUality Open Data Platform API. Visit , you can check it out for more details.






install tailwindcss






CODE
bundle add tailwindcss-rails
rails tailwindcss:install






The above commands will create files and folders necessary to kickstart designing with tailwind: app/views/layouts/application.html.erb, app/assets/builds/, config/tailwind.config.js, app/assets/stylesheets/application.tailwind.css, Procfile.dev, bin/dev.



Additionally, you can install



Let's interact with api by submitting a city name and get a result.

First, modify the form tag to conform to rails code standard!




CODE
...
<%= form_with url: "/feeds/index", method: :get do |form| %>
<%= form.label :city, "Search", class:"mb-2 text-sm font-medium text-gray-900 sr-only dark:text-gray-300" %>
<div class="relative">
<div class="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none">
<svg class="w-5 h-5 text-gray-500 dark:text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"></path></svg>
</div>

<%= form.text_field :city, placeholder: "enter name of city...", autofocus: true, required: true, value: @city,
class:"block p-4 pl-10 w-full text-sm text-gray-900 bg-gray-50 rounded-lg border border-gray-300 focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
%>

<%= form.submit "Search", class: "text-white absolute right-2.5 bottom-2.5 bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm px-4 py-2 dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800" %>
</div>
<% end %>

<div class="text-center">
<p><%= @feeds %></p>
</div>






You should notice the form_url tag has the url '/feeds/index'. After submitting the form the request goes to the index action on feeds_controller.



Modify the controller to accept the request and connect to Air Quality API to get a result:




CODE
# app/controllers/feeds_controller.rb

require 'waqi'

class FeedsController < ApplicationController
before_action :set_client

def index
@city = request.query_parameters['city']

if !@city.blank?
@feeds = @waqi_client.get_city_feed(@city)
end
end

private

def set_client
@waqi_client = Waqi::Client::new(api_key: Rails.application.credentials[:air_quality_data_token])
end
end






The above code does the following:




  1. Loads the



    You can beautify your result and integrate a Google line chart to display daily forecast for Ozone and Particulate matter level:



    Add a script tag to app/views/layouts/application.html.erb file




    CODE
    ...

    <script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
    <script type="text/javascript">
    google.charts.load('current', {'packages':['line']});
    var forecast = document.getElementById('line_top_x').getAttribute('data-forecast')
    if(forecast.length) {
    google.charts.setOnLoadCallback(drawChart);
    }

    function drawChart() {
    var data = new google.visualization.DataTable();
    data.addColumn('string', 'Date');
    data.addColumn('number', 'Ozone (o3)');
    data.addColumn('number', 'Particulate Matter 10 (pm10)');
    data.addColumn('number', 'Particulate Matter 25 (pm25)');
    data.addRows(JSON.parse(forecast));

    var options = {
    width: 900,
    height: 500,
    axes: {
    x: {
    0: {side: 'top'}
    }
    }
    };

    var chart = new google.charts.Line(document.getElementById('line_top_x'));

    chart.draw(data, google.charts.Line.convertOptions(options));
    }
    </script>
    </body>
    </html>






    The script loads the chart library and the forecast data is inserted by getting the data attribute on the page app/views/feeds/index.html.erb:




    CODE
    var forecast = document.getElementById('line_top_x').getAttribute('data-forecast')






    Insert this code snippet below into the city_feed views page:




    CODE
    <% if @isError %>
    <div class="m-4 p-2 text-red-500">
    <span>Error: <%= @response["data"] %></span>
    </div>
    <% else %>

    <div class="text-center grid grid-flow-row-dense grid-cols-4 grid-rows-4">

    <p><span class="font-black">City: </span> <%= @city_info["name"] %></p>
    <p><span class="font-black">Latitude: </span><%= @city_info["geo"][0] %></p>
    <p><span class="font-black">Longitude: </span><%= @city_info["geo"][1] %></p>

    <% if !@iaqi.blank? %>
    <% @iaqi.each do |iaqi| %>
    <% extra = determineLabel(iaqi["name"]).to_h %>
    <p><span class="font-black"><%= extra["label"] %>: </span><%= iaqi["value"] %> <%= extra["unit"] %></p>
    <% end %>
    <% end %>
    </div>

    <div class="text-center">
    <h3> Daily forecast for Ozone, Particulate Matter 10 and 25</h3>
    <div id="line_top_x" style="margin-right: auto;margin-left: auto;display: table;" data-forecast="<%= @daily_forecast %>"></div>
    </div>

    <% end %>






    The code above handles the error if there's any and also display the city, latitude, longitude, and other air quality information for a particular station.



    This line of code <% extra = determineLabel(iaqi["name"]).to_h %> is used to format the data with readable texts and provide more information to the user. You can update the app/helpers/application_helper.rb with the code below. This is a helper class.




    CODE
    module ApplicationHelper
    def determineLabel(name)
    case name
    when "co"
    { "label" => "Carbon monoxide", "unit" => "ppm" }
    when "no2"
    { "label" => "Nitrogen dioxide", "unit" => "ppb" }
    when "pm10"
    { "label" => "PM10", "unit" => "µg/m³" }
    when "pm25"
    { "label" => "PM25", "unit" => "µg/m³" }
    when "o3"
    { "label" => "Ozone", "unit" => "ppb" }
    when "w"
    { "label" => "Wind Speed", "unit" => "m/s" }
    when "t"
    { "label" => "Temperature", "unit" => "°C" }
    when "p"
    { "label" => "Air pressure", "unit" => "mb" }
    when "so2"
    { "label" => "Sulfur dioxide", "unit" => "ppb" }
    when "h"
    { "label" => "Humidity", "unit" => "%"}
    when "dew"
    { "label" => "Dew", "unit" => "°C"}
    end
    end
    end






    Update the index method on FeedsController file:




    CODE
    def index
    @city = request.query_parameters['city']
    if !@city.blank?
    response = @waqi_client.get_city_feed(@city)

    if response["status"] == "ok"
    @response = response["data"]
    @city_info = response["data"]["city"]

    @iaqi = response["data"]["iaqi"].map do |key, value|
    { "name" => key.to_s, "value" => value["v"] }
    end

    @forecast = response["data"]["forecast"]["daily"]

    @daily_forecast = format_forecast_data(@forecast)

    elsif response["status"] == "error"
    @isError = true
    @response = response
    end
    end
    end

    private

    ...

    def format_forecast_data(air_quality_data)
    # Extract days from "o3", "pm10", and "pm25" arrays
    o3_days = air_quality_data["o3"].map { |data| data["day"] } || []
    pm10_days = air_quality_data["pm10"].map { |data| data["day"] } || []
    pm25_days = air_quality_data["pm25"].map { |data| data["day"] } || []

    # Find intersection of the three arrays
    identical_days = o3_days & pm10_days & pm25_days
    formatted_parameter_data = []

    # Extract required values and push into new array
    identical_days.each do |date|
    o3_index = air_quality_data["o3"].find_index { |entry| entry["day"] == date }
    pm10_index = air_quality_data["pm10"].find_index { |entry| entry["day"] == date }
    pm25_index = air_quality_data["pm25"].find_index { |entry| entry["day"] == date }

    formatted_parameter_data << [date, air_quality_data["o3"][o3_index]["avg"], air_quality_data["pm10"][pm10_index]["avg"], air_quality_data["pm25"][pm25_index]["avg"]]
    end
    formatted_parameter_data
    end






    such as Lat/Lng based Geolocalized feed, IP based Geolocalized feed, etc.



    The complete source code can be found on github

    Vollständiger Original-Bericht
    Ausführliche Details, Code-Beispiele & Hersteller-Stellungnahme auf dev.to.
    ↗ Original-Artikel auf dev.to lesen
Wie bewertest du diesen Beitrag?
1 Klick Feedback
Teilen mit Netzwerk & Team:

Community-Analysen & Experten-Meinungen 0

Verfasse deine eigene Analyse, teile Workarounds oder diskutiere diesen Vorfall im Blog.
Noch keine Community-Analyse verfasst. Markiere einen Textabschnitt oder klicke oben auf Eigene Analyse verfassen“!
Community Pulse: Relevanz-Einschätzung
1 Klick Experten-Votum
🔴 Akute Relevanz 0%
🟡 In Evaluierung 0%
🟢 Keine Auswirkung 0%
Spannende Innovation 0%
Verwandte Story-Cluster & Quellen (Vektor-KI)
Port 8095 Engine
1 Quelle
The Gemini desktop app is now available for Windows
1 Quelle
Burn Out, Or Fade Away
1 Quelle
Windows 11 KB5129195 is out after Microsoft confirms major issues with the September 2026 update, but it won’t fix AMD GPU errors
Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten How to Develop an Air Quality Monitoring App with Ruby on Rails

Thematisch verwandte Begriffe: Develop, Quality, Monitoring, with · 6 Treffer

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...