Ikke-ActiveRecord-modeller i Rails 4

ActiveRecord kommer med et kraftig sett med validatorer og andre funksjoner for attributter av en vedvarende datamodell. På den annen side er skjemaer en av de eldste og viktigste byggesteinene i dagens webprogrammer - et viktig grensesnitt for brukerinngang. Av de to formhjelpere som Rails gir, antar "form_for" også at du jobber med en slags vedvarende gjenstand. Så det kan ta full nytte av alle aktive rekordfunksjoner, dvs. valideringer.

Dette er alt bra for vedvarende objekter med databasebaserte representasjoner. Men hva skjer når du trenger en kompleks form som ikke gjenspeiler en vedvarende plate av noe slag?

I denne opplæringen snakker jeg om mulige løsninger på dette problemet og hvordan man implementerer en i Rails 4 (Active Models).

I denne opplæringen bygger vi et program med et skjema hvor en bruker kan legge til tilbakemelding som deretter lagres i en database. Denne applikasjonen vil også ha valideringer og visninger, akkurat slik du lager dem for en databasebasert modell, men så går vi gjennom noen av endringene i modellen for å gjøre det tableless. Og alle funksjonene må fungere som de er, uten å foreta ytterligere endringer. Det finnes ingen oppdateringer, slett eller finn handlinger for tilbakemelding.

Første ting først

For denne opplæringen antar jeg at du har en grunnleggende understating av Rails-rammen og kan enkelt lage eller generere grunnleggende kontroller, modeller og visninger. Jeg antar at du også vet litt om hvordan ruter og valideringer fungerer. På det tidspunktet jeg skrev denne opplæringen brukte jeg Rails 4.2.5 og SQLite 3.8.10.2.

Introduksjon

Det kan være mange situasjoner når du har en klasse som du vil fungere som en typisk ActiveRecord-modell, men du vil ikke fortsette dataene i databasen. For eksempel kan du ha et kontaktskjema eller noe mer komplekst som en klage eller tilbakemeldingsskjema. 

I disse situasjonene, for å løse dette problemet, ville en tilnærming være å bruke form_tag hjelpemetode, som gir deg tilpassede skjemafelt som gjør det du trenger uten å måtte binde dem med noen modell i det hele tatt.

Dette fungerer bra, men form_tag kan raskt bli kjedelig å skrive og vedlikeholde hvis man håndterer mer enn noen få felt på grunn av behovet for å håndtere å navngi sine mange attributter og deres valideringer alene. Snart vil kontrolleren din ende opp med å håndtere mye logikk og tonnevis av skjemaparams, noe som sannsynligvis ikke er en ideell løsning.

En renere, mer fleksibel tilnærming ville være om vi på en eller annen måte kunne bruke det samme form_for med en modell og alle valideringer og andre fordeler de kommer med, men uten å måtte ha database-støttede representasjoner av sine attributter.

Rails tilbyr akkurat denne typen løsning: Aktiv modell-som er akkurat som en vanlig modell, men uten bordene. Det gir akkurat den samme enkle måten å validere og nesten alle de andre godbiter som sendes med ActiveRecord. Det hjelper deg å holde applikasjonsstrukturen konsistent, fordi du bruker modeller til å representere objekter i appen din, uansett, ruter er tilgjengelige gratis, og skjemaet er like enkelt som det var før med form_for.

La oss lage et nytt program først

I dette trinnet genererer vi et dummy-program for å leke med under denne opplæringen.

Trinn 1: Bygning

Start opp terminalen din og skriv inn disse kommandoene for å opprette et nytt program:

# Lag en grunnleggende Rails App rails ny tableless cd tableless # Opprett en kontroller med bare ny, opprett og velg Handlinger rails generere kontroller tilbakemeldinger Ny opprett suksess - skip-ruter # Lag en modell rails generere modell tilbakemelding navn: streng e-post: streng adresse : strengmelding: tekstforslag: tekst 

Dette er hvordan din Katalogstruktur vil se.

Trinn 2: Redigering

Her skal jeg gi kodeutsnittene for alle filene du må fylle ut. Koden er ganske selvforklarende. Du kan enten laste ned denne appen fra GitHub-depotet som er koblet til dette innlegget, eller følg trinnene mine for å lage en selv.

→ / Config /routes.rb

ressurser: tilbakemeldinger,: bare => [: ny,: opprett] få tilbakemelding / suksess '=>' tilbakemeldinger # suksess ', som:: suksess

→ /app/views/feedbacks/success.html.erb

<%= notice %>


<%= link_to 'Submit New Feedback', new_feedback_path %>

→ / app / visninger / tilbakemeldinger /new.html.erb 

Ny tilbakemelding

<%= form_for(@feedback) do |f| %> <% if @feedback.errors.any? %>

<%= pluralize(@feedback.errors.count, "error") %> Forbudt denne tilbakemeldingen fra å bli lagret:

    <% @feedback.errors.full_messages.each do |message| %>
  • <%= message %>
  • <% end %>
<% end %>
<%= f.label :name %>
<%= f.text_field :name %>
<%= f.label :email %>
<%= f.text_field :email %>
<%= f.label :address %>
<%= f.text_field :address %>
<%= f.label :message %>
<%= f.text_area :message %>
<%= f.label :suggestion %>
<%= f.text_area :suggestion %>
<%= f.submit %>
<% end %> <%= link_to 'Back', feedbacks_path %>

→ /app/controllers/feedbacks_controller.rb

klassen feedbacksController < ApplicationController def new @feedback = Feedback.new end def create @feedback = Feedback.new(feedback_params) respond_to do |format| if @feedback.save format.html  redirect_to success_path, notice: 'Feedback was successfully submitted.'  else format.html  render :new  end end end def success end private def feedback_params params.require(:feedback).permit(:name, :email, :address, :message, :suggestion) end end

→ / app /modeller / feedbacks.rb

klasse tilbakemelding < ActiveRecord::Base # fields validation for the database. validates :name, presence: true validates :email, presence: true, length: in:5… 255 validates :address, presence: true validates :message, presence: true validates :suggestion, presence: true end

Trinn 3: Implementere

For å distribuere den på din lokale server må du først kjøre følgende kommandoer for å opprette databasen i systemet.

cd tableless / rake db: migrere 

Hvis du har fulgt opplæringen så langt, skal kommandoen ovenfor opprette en sqlite3-database som standard. For å endre det, kan du hoppe til database.yml-For denne tutorials skyld skal jeg gå med sqlite3.

Kjør nå skinner s i terminalen din, og du bør se noe som ligner på dette.

Og med dette bør du være i stand til å kjøre en dummy applikasjon.

Trinn 4: Testing

Nå er det på tide å teste det vi nettopp har laget. Trykk denne ruten i nettleseren din for å sjekke om alt fungerer bra: http: // localhost: 3000 / tilbakemeldinger / new

Du bør se et skjema som ovenfor. Trykk på Submit-knappen uten å fylle ut noe felt for å sjekke om valideringene fungerer som de skal.

Flott. Du bør se seks valideringsfeil, som ovenfor. Nå kan vi prøve å fylle ut riktige verdier og sende inn skjemaet.

Du bør se noe lignende på skjermen. La oss sjekke databasen for posten vi nettopp har skrevet inn. 

Åpne opp din Terminal, gå til prosjektkatalogen din, og skriv inn kommandoene nedenfor.

  • skinner db for å starte databaseklienten i konsollen.
  • SQLite> .tables å liste alle tabellene i databasen din (DB er valgt som standard).
  • SQLite> .heiser på å vise Kolonne navn i resultatene dine.
  • SQLite> velg * fra tilbakemeldinger; for å se all tilbakemelding i databasen.

Og her kan vi se tilbakemeldingen ble lagret i databasen. Hvis du ser på loggene, kan du også finne SETT INN spørsmål.

Og med dette er testen vår over. Nå som alt ser ut til å fungere bra, la oss hoppe inn i løsningen.

Løsningen

Trinn 1: Implementering 

Å implementere Aktiv modell, Det første du må gjøre er å fjerne tilbakemeldingsmodellens arv til < ActiveRecord::Base som vi ikke vil at denne modellen skal ha en database-back-end lenger. 

Så snart vi gjør dette, vil vårt skjema ikke lenger fungere, da validatorene leveres av ActiveRecord. Men å legge til Inkluder ActiveModel :: Modell på neste linje bør gjenopprette alt.

Din modell skal se slik ut nå.

Klassen tilbakemelding inkluderer ActiveModel :: Modell 

Den andre tingen er å legge til attr_accessor å generere getters og setters for alle attributter, slik som dette.

attr_accessor: navn,: email,: adresse,: melding,: forslag

Nå skal sluttresultatet av modellen se slik ut.

klasse tilbakemelding inkluderer ActiveModel :: Modell attr_accessor: navn,: email,: adresse,: melding,: forslag # felt validering for databasen. Validerer: Navn, Tilstedeværelse: Sann Validerer: E-post, Tilstedeværelse: Sann, Lengde: i: 5 ... 255 Validerer: Adresse, Tilstedeværelse: Sann Validerer: Beskjed, Tilstedeværelse: Sann Validerer: Forslag, Tilstedeværelse: Sann slutt

Å fikse modellen er ikke nok til å få appen til å oppføre seg som vi vil. Kontrolleren forventer fortsatt å lagre den mottatte dataobjektet i databasen i skape metode. @ feedback.save vil ikke fungere som vi ikke har en database tilbake til å lagre den nye tilbakemeldingen lenger.

Vi kan fikse dette problemet ved å endre @ feedback.save inn i @ feedback.valid? siden vi bare utfører valideringene i våre modeller nå, og basert på denne suksesshendelsen kan du utføre en hvilken som helst foretrukket oppgave innen denne koden, dvs. sende varsler, send e-post eller logg hendelser, osv..

klassen feedbacksController < ApplicationController def create @feedback = Feedback.new(feedback_params) respond_to do |format| if @feedback.valid? # Something interesting can be done here # - send notifications # - send email # - log events format.html  redirect_to success_path, notice: 'Feedback was successfully submitted.'  else format.html  render :new  end end end

Trinn 2: Testing

La oss gjenta testene vi har utført tidligere.

Hit ruten http: // localhost: 3000 / tilbakemeldinger / new og sendeskjemaet uten å fylle ut noen felt. Alle valideringene skal fungere som tidligere.

Flott. Nå kan vi prøve å sende inn skjemaet med gyldige verdier.

Og her går du - den samme suksessmeldingen.

Nå er det siste som vi må sjekke, databasen. 

For det, åpne opp din Terminal, gå til prosjektkatalogen din, og skriv inn kommandoene nedenfor.

  • skinner db for å starte databaseklienten i konsollen.
  • SQLite> .tables å liste alle tabellene i databasen din (DB er valgt som standard).
  • SQLite> .heiser på å vise Kolonne navn i resultatene dine.
  • SQLite> velg * fra tilbakemeldinger for å se all tilbakemelding i databasen.

Og denne gangen, siden vår modell ikke støttes med en databasetabell, finner du ikke de nylig innmeldte verdiene i tabellen.

Hvis du sjekker konsollloggene, ser vi ikke SETT INN spørre lenger.

Konklusjon

Så med dette er vi ferdige med ActiveModel, og vi så hvor lett det er å lage en bordløs modell. ActiveModel er i store forbedringer, slik at du kan forvente noen endringer i kommende versjoner av Rails. 

Vi har nettopp brukt valideringene og attributtoppgaver i denne opplæringen for å holde ting enkelt og klart. Men ta en titt i katalogen som inneholder koden for ActiveModel på GitHub.

Vi kan se fra listen at ActiveModel også inkluderer klasser for attributt metoder, serialisering, tilbakeringinger og skitten sporing blant annet. På denne måten kan du holde øye med kommende funksjoner og bli kjent med andre.