Ruby Rails 通过表单将对象添加到数据库时出错
Ruby on Rails Adding Object to Database through Forms Error
我正在尝试在我的网络应用程序上创建一个表单,以便具有正确权限的用户可以向数据库添加一个新的“站点”。我有一个名为 site 的数据库 table,在我的本地计算机上具有所有正确的属性。单击表单上的提交按钮时,出现以下错误。我尝试使用属性访问器,但它导致我以前的许多测试失败。有没有不使用属性访问器就能解决这个问题的方法?
错误:
Admin::AddSitesController#create 中没有方法错误
nil:NilClass
的未定义方法 `write_from_user'
def create
site = Site.new(site_params) <-- highlighted in error message
authorize(site)
型号
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"
}
控制器
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_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 %>
路线
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
想通了 - 只需要删除
include ActiveModel::Model
来自 Site 模型,因为它已经通过其 table.
连接到数据库
为了澄清 Rachel 的回答,include ActiveModel::Model
应该只用于数据库中没有 table 的模型。由于您的站点模型已经通过 self.table_name = "site"
连接到数据库,因此当您尝试访问站点 table.
中的列和值时,Ruby 将开始抛出错误
我正在尝试在我的网络应用程序上创建一个表单,以便具有正确权限的用户可以向数据库添加一个新的“站点”。我有一个名为 site 的数据库 table,在我的本地计算机上具有所有正确的属性。单击表单上的提交按钮时,出现以下错误。我尝试使用属性访问器,但它导致我以前的许多测试失败。有没有不使用属性访问器就能解决这个问题的方法?
错误:
Admin::AddSitesController#create 中没有方法错误 nil:NilClass
的未定义方法 `write_from_user' def create
site = Site.new(site_params) <-- highlighted in error message
authorize(site)
型号
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"
}
控制器
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_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 %>
路线
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
想通了 - 只需要删除
include ActiveModel::Model
来自 Site 模型,因为它已经通过其 table.
连接到数据库为了澄清 Rachel 的回答,include ActiveModel::Model
应该只用于数据库中没有 table 的模型。由于您的站点模型已经通过 self.table_name = "site"
连接到数据库,因此当您尝试访问站点 table.