I'm trying to create a form on my web app so a user with the correct permissions can add a new "Site" to the database. I have a database table called site with all the correct attributes on my local machine. When the submit button is clicked on the form, I get the following error. I tried using an attribute accessor, but it causes many of my previous tests to fail. Is there a way to solve this problem without using attribute accessor?
Error:
NoMethodError in Admin::AddSitesController#create undefined method `write_from_user' for nil:NilClass
def create
site = Site.new(site_params) <-- highlighted in error message
authorize(site)
Model
class Site < ApplicationRecord
include ActiveModel::Model
self.table_name = "site"
validates :name, presence: true
validates :address, presence: true
validates :year_built, inclusion: {in: 1700..Date.today.year, message: "that year is fake"},
allow_nil: true
validates :number_of_floors, numericality: {only_integer: true, greater_than: 0}, allow_nil: true
validates :total_floor_area, numericality: {only_integer: true, greater_than: 0}, allow_nil: true
validates :number_of_units, numericality: {only_integer: true, greater_than: 0}, allow_nil: true
validates :primary_use_type, presence: true
validates :number_of_bedrooms, numericality: {only_integer: true, greater_than: 0}, allow_nil: true
validates :people_per_bedroom, numericality: {only_integer: true, greater_than: 0}, allow_nil: true
validates :water_performance_goal, numericality: {only_integer: true, greater_than: 0}, allow_nil: true
belongs_to :organization
belongs_to :weather_station
has_many :site_users, dependent: :destroy
has_many :users, through: :site_users
enum primary_use_type: {
commerical: "Commercial",
residential: "Residential"
}
enum building_type: {
affordable: "Affordable",
market_rate: "Market Rate"
}
enum population_type: {
family: "Family",
elderly_disabled: "Elderly/Disabled",
mixed_other: "Mixed/Other"
}
enum construction_type: {
brick_block: "Brick/Block",
concrete_slab: "Concrete/Slab",
wood_steel: "Light Framed Wood/Steel",
timber_steel: "Heavy Framed Timber/Steel"
}
Controller
module Admin
class AddSitesController < ApplicationController
def new
@site = Site.new
authorize(@site)
end
def create
site = Site.new(site_params)
authorize(site)
if site.valid?
site.save
flash[:notice] = "good"
redirect_to admin_superusers_path
else
flash[:messages] = site.errors.full_messages
redirect_to admin_manage_sites_path
end
end
private
def site_params
params.require(:site).permit(
:organization_id,
:name,
:address,
:year_built,
:construction_type,
:number_of_floors,
:total_floor_area,
:number_of_units,
:weather_station_id,
:primary_use_type,
:building_type,
:population_type,
:number_of_bedrooms,
:people_per_bedroom,
:water_performance_goal,
:sro
)
end
end
end
Form
<%= form_with(
model: @site,
url: admin_add_sites_path,
) do |form| %>
<div class="pr-8">
<% if flash[:messages] %>
<ul class=“flash alert”>
<% flash[:messages].each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
<% end %>
<h2 class="heading-300 text-green-800 mt-3" >
<%= t(".site_info")%>
</h2>
<%= form.label(:organization_id, "Organization", class: "form-label") %>
<% options = options_from_collection_for_select(@organizations, :id, :name, form.object.organization_id) %>
<%= form.select :organization_id, options%>
<%= form.label(:name, "Site name", class: "form-label") %>
<%= form.text_field(:name, autocomplete: "off", autocapitalize: "on", class: "form-input") %>
<%= form.label(:address, class: "form-label") %>
<%= form.text_field(:address, autocomplete: "off", autocapitalize: "on", class: "form-input") %>
<%= form.label("Format: address, city, state, zip code", class: "form-detail text-sm") %>
<h2 class="heading-300 text-green-800 mt-5" >
<%= t(".site_details")%>
</h2>
<%= form.label(:year_built, class: "form-label") %>
<%= form.text_field(:year_built, autocomplete: "off", class: "form-input") %>
<%= form.label(:construction_type, class: "form-label") %>
<%= form.select(:construction_type, Site.construction_types.values, :include_blank => true) %>
<%= form.label(:number_of_floors, class: "form-label") %>
<%= form.text_field(:number_of_floors, autocomplete: "off", class: "form-input") %>
<%= form.label(:total_floor_area, class: "form-label") %>
<%= form.text_field(:total_floor_area, autocomplete: "off", class: "form-input") %>
<%= form.label("Units: sqaure feet", class: "form-detail text-sm") %>
<%= form.label(:number_of_units, class: "form-label") %>
<%= form.text_field(:number_of_units, autocomplete: "off", class: "form-input") %>
<%= form.label(:weather_station_id, "NOAA weather station", class: "form-label") %>
<% options = options_from_collection_for_select(@weather_stations, 'id', 'zip_code', form.object.weather_station_id) %>
<%= form.select :weather_station_id, options%>
<%= form.label(:primary_use_type, class: "form-label") %>
<%= form.select(:primary_use_type, Site.primary_use_types.values, :include_blank => true) %>
<div aria-expanded="false" class="form__drawer">
<div class="pl-8 pb-8 mt-5">
<h2 class="heading-300">
<%= "Residential Options" %>
</h2>
<%= form.label(:building_type, class: "form-label") %>
<%= form.select(:building_type, Site.building_types.values, :include_blank => true) %>
<%= form.label(:population_type, class: "form-label") %>
<%= form.select(:population_type, Site.population_types.values, :include_blank => true) %>
<%= form.label(:number_of_bedrooms, class: "form-label") %>
<%= form.text_field(:number_of_bedrooms, autocomplete: "off", class: "form-input") %>
<%= form.label(:people_per_bedroom, class: "form-label") %>
<%= form.text_field(:people_per_bedroom, class: "form-input") %>
<%= form.label(:water_performance_goal, class: "form-label") %>
<%= form.text_field(:water_performance_goal, autocomplete: "off", class: "form-input", value: 60) %>
<%= form.label("Gal/Bedroom/Day ", class: "form-detail text-sm") %>
<%= form.label(:sro, "SRO", class: "form-label") %>
<%= form.select(:sro, ["yes", "no"], :include_blank => true) %>
</div>
</div>
<div class="mt-2">
<%= form.submit "Add", class: "button-primary w-full" %>
</div>
</div>
<% end %>
Routes
namespace :admin do
get "/" => "dashboards#show"
resources :site_users, only: [:update, :destroy]
resources :superusers, only: [:index]
resources :manage_sites, only: [:index, :update, :destroy]
resources :superuser_invitations, only: [:create]
resources :add_sites, only: [:create, :new]
resources :organizations, only: [] do
resources :managers, only: [:index]
resources :manager_invitations, only: [:create]
end
resources :sites, only: [] do
resources :users, only: [:index]
resources :user_invitations, only: [:create]
end
end
Figured it out- just needed to remove
include ActiveModel::Model
from the Site model as it is already connected to the database through its table.