我应该将模型计算保存为属性吗?
Should I save a Model calculation as an attribute?
我有一个应用程序,允许用户使用表单输入名称、描述、长度和宽度来创建新房间。每个创建的房间都会成为一条新记录,应用程序会计算房间的 'size' 为 'length' * 'width'。这是一个简单的应用程序,我正在使用它来学习 Rails,但我可能会更进一步,将房间集合形成一个房子,每个房子总共 'size'。
我的问题涉及 'size' 值以及应如何将其集成到应用程序中。我最初认为用户应该立即在表单上看到 'size' 的值,但一旦发现可能需要 Ajax 就搁置了。我将 'size' 方法计算从视图移动到模型以符合 "fat model, skinny controller" 概念,现在我在 'index' 视图中显示 'size',留下 'new' 查看纯粹是为了输入数据。
我最初将模型设置为包括长度、宽度和尺寸。查看 Room 模型的迁移:
20150118183743_create_rooms.rb
class CreateRooms < ActiveRecord::Migration
def change
create_table :rooms do |t|
t.string :name
t.text :description
t.integer :length
t.integer :width
t.integer :size
t.timestamps null: false
end
end
end
我应该将每条记录保存 'size' 到数据库吗?我读过,没有必要将计算作为属性保存到模型中。据推测,该应用程序应该处理这个问题?正确的思考方式是什么?
我的 'index' 视图计算 & returns 最大值 'length' 和 'width',但是当我尝试计算最大值 'size' 时,我 运行 出错了。我在模型中对此进行了计算(即方法),但它似乎是错误的。有什么建议么?
以下是相关代码:
room.rb
class Room < ActiveRecord::Base
validates :name, presence: true, length: { maximum: 30 },
uniqueness: { case_sensitive: false }
validates :length, :width, presence: true,
numericality: { only_integer: true,
less_than_or_equal_to: 1000,
greater_than_or_equal_to: 1 }
def size
size = length * width
end
def max_room
size.max
end
end
rooms_controller.rb
class RoomsController < ApplicationController
def show
@room = Room.find(params[:id])
end
def new
@room = Room.new
end
def index
@rooms = Room.all
end
def create
@room = Room.new(user_params)
if @room.save #a boolean, if able to save the instance
flash[:success] = "You created a new Room!!"
redirect_to @room #we send the user to the room
else
render 'new' #so we want to render the new template
end
end
private
def user_params
params.require(:room).permit(:name, :description, :length,
:width, :size)
end
end
index.html.erb
<% provide(:title, 'All Rooms') %>
<h1>All rooms</h1>
<div class="container">
<div class="row column-md-7">
<table class="table table-hover">
<thead>
<tr>
<th>Name</th>
<th>Description</th>
<th class="text-right">Length (ft.) </th>
<th class="text-right">Width (ft.) </th>
<th class="text-right">Size (sq.ft.) </th>
<th class="text-center">Delete? </th>
</tr>
</thead>
<tbody>
<% @rooms.each do |room| %>
<tr>
<td> <%= link_to room.name, room %> </td>
<td> <%= room.description %> </td>
<td class="text-right"> <%= room.length %> </td>
<td class="text-right"> <%= room.width %> </td>
<td class="text-right"> <%= room.size %> </td>
<td class="text-center"> <%= link_to "delete", room, method: :delete,
data: { confirm: "You sure?" } %> </td>
</tr>
<% end %>
</tbody>
</table>
<div class="alert alert-info">
The model contains <%= pluralize(Room.count, "room") %> in total.
The max length is <%= Room.maximum('length') %>.
The max width is <%= Room.maximum('width') %>.
</div>
</div>
</div>
我尝试通过添加
来显示 'size'
The max size is <%= Room.max_room %>
但是返回了一个错误。
new.html.erb
<% provide(:title, "New Room") %>
<h1>The Rooms page </h1>
<div class="row">
<div class="col-md-6 col-md-offset-3">
<%= form_for(@room) do |f| %>
<%= render 'shared/error_messages' %>
<%= f.label :name %>
<%= f.text_field :name %>
<%= f.label :description %>
<%= f.text_area :description %>
<%= f.label :length, "Length (ft.)" %>
<%= f.number_field :length %>
<%= f.label :width, "Width (ft.)" %>
<%= f.number_field :width %>
<%= f.submit "Create my room", class: "btn btn-primary" %>
<% end %>
</div>
</div>
show.html.erb
<% provide(:title, @room.name) %>
<h1>The "<%= @room.name %>" page </h1>
<h2>This page contains the show action associated with the
Rooms page </h2>
<br>
<br>
<div class="container">
<div class="col-md-6 col-md-offset-3">
<table class="table table-bordered">
<thead>
<tr>
<th>Name</th>
<th>Description</th>
<th class="text-right">Length (ft.) </th>
<th class="text-right">Width (ft.) </th>
<th class="text-right">Size (sq.ft.) </th>
</tr>
</thead>
<tbody>
<tr>
<td> <%= @room.name %> </td>
<td> <%= @room.description %> </td>
<td class="text-right"> <%= @room.length %> </td>
<td class="text-right"> <%= @room.width %> </td>
<td class="text-right"> <%= @room.size %> </td>
</tr>
</tbody>
</table>
</div>
</div>
<hr>
<%= link_to "Create a new room", new_room_path, class: "btn btn btn-primary" %>
routes.rb
Rails.application.routes.draw do
root 'static_pages#home'
get 'home' => 'static_pages#home'
get 'calculations' => 'static_pages#calculations'
get 'help' => 'static_pages#help'
get 'about' => 'static_pages#about'
get 'new_room' => 'rooms#new'
get 'rooms' => 'rooms#index'
resources :rooms
end
我打算使用需要进行大量数值计算的应用程序,因此我想掌握这些基础知识。如果我在应该(也许)在虚拟环境中完成计算时保存了太多计算,我不希望应用程序的数据库崩溃。
所以,回顾一下....
- 应将应用计算作为新记录的属性保存到数据库中吗?
- 'size' 的正确 calculation/method 是什么?
- 如果我想对计算值执行计算,是否必须先将该值保存为属性?
您对 max_room
的实现是错误的,因为 size
值只是一个数字,max 方法没有在数字上定义,而是应该在 [=14] 上调用=] 的值。
所以Room
应该这样实现:
class Room < ActiveRecord::Base
validates :name, presence: true, length: { maximum: 30 },
uniqueness: { case_sensitive: false }
validates :length, :width, presence: true,
numericality: { only_integer: true,
less_than_or_equal_to: 1000,
greater_than_or_equal_to: 1 }
def size
size = length * width
end
class << self
# This is a class method, since it depends on all the rooms
# not on a specific room
def max_size
# This will delegate the calculation to the database
select('MAX(length * width) AS max')[0]['max'];
end
# But, this will instantiate the records on memory before it makes the calculation
# def max_room
# all.max{ |room| room.length * room.width }
# end
# This is a class method as well
def max_room
order('size DESC').first
end
end
end
- Should a app calculation be saved to the database as an attribute to a new record?
如果计算值所依赖的属性会经常变化,这种情况下不要保存计算值,而是每次需要的时候再计算一次。但是我看到一个房间的长宽是不会改变的,所以计算出来的值需要计算一次,保存起来以备需要时使用(比如计算max_size),所以在这个如果您需要创建一个属性 size
并在使用挂钩创建记录时对其进行计算。
before_save :calculate_size
private
def calculate_size
size = length * width
end
我有一个应用程序,允许用户使用表单输入名称、描述、长度和宽度来创建新房间。每个创建的房间都会成为一条新记录,应用程序会计算房间的 'size' 为 'length' * 'width'。这是一个简单的应用程序,我正在使用它来学习 Rails,但我可能会更进一步,将房间集合形成一个房子,每个房子总共 'size'。
我的问题涉及 'size' 值以及应如何将其集成到应用程序中。我最初认为用户应该立即在表单上看到 'size' 的值,但一旦发现可能需要 Ajax 就搁置了。我将 'size' 方法计算从视图移动到模型以符合 "fat model, skinny controller" 概念,现在我在 'index' 视图中显示 'size',留下 'new' 查看纯粹是为了输入数据。
我最初将模型设置为包括长度、宽度和尺寸。查看 Room 模型的迁移:
20150118183743_create_rooms.rb
class CreateRooms < ActiveRecord::Migration
def change
create_table :rooms do |t|
t.string :name
t.text :description
t.integer :length
t.integer :width
t.integer :size
t.timestamps null: false
end
end
end
我应该将每条记录保存 'size' 到数据库吗?我读过,没有必要将计算作为属性保存到模型中。据推测,该应用程序应该处理这个问题?正确的思考方式是什么?
我的 'index' 视图计算 & returns 最大值 'length' 和 'width',但是当我尝试计算最大值 'size' 时,我 运行 出错了。我在模型中对此进行了计算(即方法),但它似乎是错误的。有什么建议么?
以下是相关代码:
room.rb
class Room < ActiveRecord::Base
validates :name, presence: true, length: { maximum: 30 },
uniqueness: { case_sensitive: false }
validates :length, :width, presence: true,
numericality: { only_integer: true,
less_than_or_equal_to: 1000,
greater_than_or_equal_to: 1 }
def size
size = length * width
end
def max_room
size.max
end
end
rooms_controller.rb
class RoomsController < ApplicationController
def show
@room = Room.find(params[:id])
end
def new
@room = Room.new
end
def index
@rooms = Room.all
end
def create
@room = Room.new(user_params)
if @room.save #a boolean, if able to save the instance
flash[:success] = "You created a new Room!!"
redirect_to @room #we send the user to the room
else
render 'new' #so we want to render the new template
end
end
private
def user_params
params.require(:room).permit(:name, :description, :length,
:width, :size)
end
end
index.html.erb
<% provide(:title, 'All Rooms') %>
<h1>All rooms</h1>
<div class="container">
<div class="row column-md-7">
<table class="table table-hover">
<thead>
<tr>
<th>Name</th>
<th>Description</th>
<th class="text-right">Length (ft.) </th>
<th class="text-right">Width (ft.) </th>
<th class="text-right">Size (sq.ft.) </th>
<th class="text-center">Delete? </th>
</tr>
</thead>
<tbody>
<% @rooms.each do |room| %>
<tr>
<td> <%= link_to room.name, room %> </td>
<td> <%= room.description %> </td>
<td class="text-right"> <%= room.length %> </td>
<td class="text-right"> <%= room.width %> </td>
<td class="text-right"> <%= room.size %> </td>
<td class="text-center"> <%= link_to "delete", room, method: :delete,
data: { confirm: "You sure?" } %> </td>
</tr>
<% end %>
</tbody>
</table>
<div class="alert alert-info">
The model contains <%= pluralize(Room.count, "room") %> in total.
The max length is <%= Room.maximum('length') %>.
The max width is <%= Room.maximum('width') %>.
</div>
</div>
</div>
我尝试通过添加
来显示 'size'The max size is <%= Room.max_room %>
但是返回了一个错误。
new.html.erb
<% provide(:title, "New Room") %>
<h1>The Rooms page </h1>
<div class="row">
<div class="col-md-6 col-md-offset-3">
<%= form_for(@room) do |f| %>
<%= render 'shared/error_messages' %>
<%= f.label :name %>
<%= f.text_field :name %>
<%= f.label :description %>
<%= f.text_area :description %>
<%= f.label :length, "Length (ft.)" %>
<%= f.number_field :length %>
<%= f.label :width, "Width (ft.)" %>
<%= f.number_field :width %>
<%= f.submit "Create my room", class: "btn btn-primary" %>
<% end %>
</div>
</div>
show.html.erb
<% provide(:title, @room.name) %>
<h1>The "<%= @room.name %>" page </h1>
<h2>This page contains the show action associated with the
Rooms page </h2>
<br>
<br>
<div class="container">
<div class="col-md-6 col-md-offset-3">
<table class="table table-bordered">
<thead>
<tr>
<th>Name</th>
<th>Description</th>
<th class="text-right">Length (ft.) </th>
<th class="text-right">Width (ft.) </th>
<th class="text-right">Size (sq.ft.) </th>
</tr>
</thead>
<tbody>
<tr>
<td> <%= @room.name %> </td>
<td> <%= @room.description %> </td>
<td class="text-right"> <%= @room.length %> </td>
<td class="text-right"> <%= @room.width %> </td>
<td class="text-right"> <%= @room.size %> </td>
</tr>
</tbody>
</table>
</div>
</div>
<hr>
<%= link_to "Create a new room", new_room_path, class: "btn btn btn-primary" %>
routes.rb
Rails.application.routes.draw do
root 'static_pages#home'
get 'home' => 'static_pages#home'
get 'calculations' => 'static_pages#calculations'
get 'help' => 'static_pages#help'
get 'about' => 'static_pages#about'
get 'new_room' => 'rooms#new'
get 'rooms' => 'rooms#index'
resources :rooms
end
我打算使用需要进行大量数值计算的应用程序,因此我想掌握这些基础知识。如果我在应该(也许)在虚拟环境中完成计算时保存了太多计算,我不希望应用程序的数据库崩溃。
所以,回顾一下....
- 应将应用计算作为新记录的属性保存到数据库中吗?
- 'size' 的正确 calculation/method 是什么?
- 如果我想对计算值执行计算,是否必须先将该值保存为属性?
您对 max_room
的实现是错误的,因为 size
值只是一个数字,max 方法没有在数字上定义,而是应该在 [=14] 上调用=] 的值。
所以Room
应该这样实现:
class Room < ActiveRecord::Base
validates :name, presence: true, length: { maximum: 30 },
uniqueness: { case_sensitive: false }
validates :length, :width, presence: true,
numericality: { only_integer: true,
less_than_or_equal_to: 1000,
greater_than_or_equal_to: 1 }
def size
size = length * width
end
class << self
# This is a class method, since it depends on all the rooms
# not on a specific room
def max_size
# This will delegate the calculation to the database
select('MAX(length * width) AS max')[0]['max'];
end
# But, this will instantiate the records on memory before it makes the calculation
# def max_room
# all.max{ |room| room.length * room.width }
# end
# This is a class method as well
def max_room
order('size DESC').first
end
end
end
- Should a app calculation be saved to the database as an attribute to a new record?
如果计算值所依赖的属性会经常变化,这种情况下不要保存计算值,而是每次需要的时候再计算一次。但是我看到一个房间的长宽是不会改变的,所以计算出来的值需要计算一次,保存起来以备需要时使用(比如计算max_size),所以在这个如果您需要创建一个属性 size
并在使用挂钩创建记录时对其进行计算。
before_save :calculate_size
private
def calculate_size
size = length * width
end