Rails - 如何避免在视图中使用 hidden_fields 将值传递给控制器?
Rails - How to avoid using hidden_fields in the view to pass values to controller?
有什么方法可以避免 hidden_field
将视图中的值传递给控制器的方法?出于安全原因,我更喜欢控制器方法。不幸的是 strong_parameters
不支持值配对 @variables
。
EDIT 6/18 1:00 PM EST
- I've renamed my
garages
controller to appointments
cars_controller
no longer creates a new appointment
(formally garages
). A new appointment is created in the
appointments_controller
我目前的结构
路线
Rails.application.routes.draw做
resources :techs, only: [:index, :show], shallow: true do
resources :cars, only: [:new, :create]
end
资源:约会
#For searchkick
resources :cars, only: [:show] do
collection do
get 'search'
end
end
root "home#index"
end
型号
tech.rb
class Tech < ActiveRecord::Base
searchkick
has_many :appointments
has_many :customers, :through => :appointments
has_many :service_menus
has_many :services
has_many :cars
end
service.rb
class Service < ActiveRecord::Base
belongs_to :tech
belongs_to :service_menu
has_many :cars, dependent: :destroy
accepts_nested_attributes_for :cars, :reject_if => :all_blank, :allow_destroy => true
end
car.rb
class Car < ActiveRecord::Base
belongs_to :service
belongs_to :tech
has_many :appointments
end
appointment.rb
class Garage < ActiveRecord::Base
belongs_to :customer
belongs_to :tech
belongs_to :car
end
控制器
cars_controller
def new
@car = Car.find(params[:id])
@tech = Tech.find(params[:tech_id])
@appointment = Garage.new
end
appointments_controller
def create
@appointment = current_customer.appointments.build(appointment_params)
if @appointment.save
redirect_to appointments_path, notice: "You car has been added to this appointment."
else
redirect_to appointments_path, notice: "Uh oh, an error has occured."
end
end
private
def appointment_params
params.require(:appointment).permit(:tech_id, :service_id, :car_id, ...and a bunch of other keys here)
end
观看次数
cars.new.html
Please note this form passes hidden values to the appointment_controller
.
Value from @car.name
and other alike are not from a text_field
but rather a pre-defined value based on selections from a previous page which is store in the cars
db.
<%= simple_form_for(@appointment, { class: 'form-horizontal' }) do |f| %>
<%= f.hidden_field :tech_id, value: @tech.id %>
<%= f.hidden_field :car_id, value: @car.id %>
<%= f.hidden_field :service_id, value: @car.service.id %>
<%= f.hidden_field :customer_car, value: current_customer.car %>
<%= f.hidden_field :customer_street_address, value: current_customer.street_address %>
<%= f.hidden_field :customer_city, value: current_customer.city %>
<%= f.hidden_field :customer_state, value: current_customer.state %>
<%= f.hidden_field :customer_zip_code, value: current_customer.zip_code %>
<%= f.hidden_field :service_name, value: @car.service.service_menu.name %>
<%= f.hidden_field :car_name, value: @car.name %>
<%= **And a bunch of other hidden values here which are too long to list** %>
<%= f.submit "Add to appointment", class: 'btn btn-default' %>
<% end %>
service.html
<%= render 'form' %>
_form.html
<%= simple_form_for @service do |f| %>
<div class="field">
<%= f.label "Select service category" %>
<br>
<%= collection_select(:service, :service_menu_id, ServiceMenu.all, :id, :name, {:prompt => true }) %>
<%= f.fields_for :cars do |task| %>
<%= render 'car_fields', :f => task %>
<% end %>
</div>
<div class="links">
<%= link_to_add_association 'Add New Car', f, :cars, class: 'btn btn-default' %>
</div><br>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
_car_fields.html
<div class="nested-fields">
<div class="field">
<%= f.label :name %><br>
<%= f.text_field :name %><br>
<%= f.label :hours %>
<%= f.select :hours, '0'..'8' %>
<%= f.label :minutes %>
<%= f.select :minutes, options_for_select( (0..45).step(15), selected: f.object.minutes) %><br>
<%= f.label :price %><br>
<%= f.text_field :price, :value => (number_with_precision(f.object.price, :precision => 2) || 0) %> <br>
<%= f.label :details %><br>
<%= f.text_area :details %></div>
<%= link_to_remove_association "Remove Car", f, class: 'btn btn-default' %>
<%= f.hidden_field :tech_id, value: current_tech.id %>
<br>
<hr>
</div>
> 编辑 7/14 1:30 下午 EST
应用程序此特定功能的简要介绍
- A
customer
点击了 tech
必须提供的服务列表
customer
选择一项服务,例如 brakes,这是 tech
在其个人资料中列出的一项服务。
- brakes 的属性列在
cars
db
cars
belongs_to
到 techs
-
customer
可以节省 brakes 这是 techs
car
到 appointment
[=166 的属性=]
- 来自
tech
的大量预定义值、customer
的街道地址等...,car
已预加载到 form
用于存储在 appointments
table.
appointment
充当 历史记录 table。因此,如果 tech
决定修改他的任何一个 services
在这个例子中 brakes,appointments
tables 将保持不变刹车条目。
- 一旦
customer
选择了 Add to appointment
按钮,它将保存 tech
、customer
和 car
属性中的所有预定义值(在这个例子中 brakes) 到 appointments
db.
另一种方法是完全摆脱 strong parameters
并执行以下操作:
def create
@appointment = Garage.create(tech_id: @car.service.tech.id,
customer_id: current_customer.id,
customer_street_address: current_customer.street_address,
customer_city: current_customer.city,
customer_state: current_customer.state,
customer_zip_code: current_customer.zip_code,
customer_phone_number: current_customer.phone_number,
customer_location_type: "WILL ADD LATER",
customer_latitude: current_customer.latitude,
customer_longitude: current_customer.longitude,
service_id: @car.service.id,
service_name: @car.service.name,
car_id: @car.id,
car_name: @car.name,
car_time_duration: @car.time_duration,
price: @car.price,
car_details: @car.details)
if @appointment.save
redirect_to techs_path, notice: "This service has been saved."
elsif
redirect_to tech_path, notice: "Uh oh, an error has occurred."
end
end
如果您需要更多详细信息,请告诉我。
我能想到一些方法可以用来避免这种 form
被 hidden_field
膨胀:
- 在用户会话中的控制器之间共享数据,非常类似于电子商务应用程序中的购物车。
- 如果您希望保留应用程序的无状态性,请创建一个模型来临时存储这些信息;这样你只需要在
form
. 中包含一个 hidden_field
- 使用 JavaScript 发出请求,将数据存储在本地对象中并在需要时将它们作为 JSON 传递(使用 AngularJS 很简单)。
无论您选择哪种方法,请记住,在 Web 应用程序中存储大量状态通常是一种代码味道。您可以随时重新考虑您的应用程序,这样您就不需要保留那么多上下文。
您可以将这些内容移动到回调中,并且仅通过表单传递 customer_id 和 car_id。这样车库实例就会知道它的客户和汽车 parents,你可以这样做:
class Garage < ActiveRecord::Base
before_create :copy_stuff
private
def copy_stuff
self.customer_street_address = customer.street_address
self.car_name = car.name
# and so on
end
end
Is there a way I can avoid the hidden_field method of passing values
in the view to a controller?
您可以通过将属性 disabled: true
添加到隐藏的输入字段标签来禁用 HTML/view 中的这些字段,以实现您的要求。
不确定语法是否准确,但例如应该是这样的
f.hidden_field :tech_id, value: @tech.id, disabled: true
为了解决我的问题,我对最初 post 的最新编辑说明如下:
EDIT 6/18 1:00 PM EST
- I've renamed my
garages_controller
to appointments_controller
cars_controller
no longer creates a new appointment (formally garages). A new appointment is created in the appointments_controller
只有 hidden_field 我路过 约会视图中的 car_id
/new.html.erb <%= f.hidden_field :car_id, value: @car.id %>
.
在 appointments_controller
中,我分配所有 car
属性执行以下操作。
def create
@appointment = current_customer.appointments.build(appointment_params)
@appointment.tech_id = @appointment.car.service.tech.id
@appointment.price = @appointment.car.price
@appointment.car_name = @appointment.car.name
@appointment.car_details = @appointment.car.details
if @appointment.save
redirect_to appointments_path, notice: "Thank you booking your appointment."
else
redirect_to appointments_path, notice: "Uh oh, an error has occurred. Please try again or contact us for further assistance"
end
end
谢谢大家的回复。
我早该知道的。 :(
有什么方法可以避免 hidden_field
将视图中的值传递给控制器的方法?出于安全原因,我更喜欢控制器方法。不幸的是 strong_parameters
不支持值配对 @variables
。
EDIT 6/18 1:00 PM EST
- I've renamed my
garages
controller toappointments
cars_controller
no longer creates a newappointment
(formallygarages
). A new appointment is created in theappointments_controller
我目前的结构
路线
Rails.application.routes.draw做
resources :techs, only: [:index, :show], shallow: true do
resources :cars, only: [:new, :create]
end
资源:约会
#For searchkick
resources :cars, only: [:show] do
collection do
get 'search'
end
end
root "home#index"
end
型号
tech.rb
class Tech < ActiveRecord::Base
searchkick
has_many :appointments
has_many :customers, :through => :appointments
has_many :service_menus
has_many :services
has_many :cars
end
service.rb
class Service < ActiveRecord::Base
belongs_to :tech
belongs_to :service_menu
has_many :cars, dependent: :destroy
accepts_nested_attributes_for :cars, :reject_if => :all_blank, :allow_destroy => true
end
car.rb
class Car < ActiveRecord::Base
belongs_to :service
belongs_to :tech
has_many :appointments
end
appointment.rb
class Garage < ActiveRecord::Base
belongs_to :customer
belongs_to :tech
belongs_to :car
end
控制器
cars_controller
def new
@car = Car.find(params[:id])
@tech = Tech.find(params[:tech_id])
@appointment = Garage.new
end
appointments_controller
def create
@appointment = current_customer.appointments.build(appointment_params)
if @appointment.save
redirect_to appointments_path, notice: "You car has been added to this appointment."
else
redirect_to appointments_path, notice: "Uh oh, an error has occured."
end
end
private
def appointment_params
params.require(:appointment).permit(:tech_id, :service_id, :car_id, ...and a bunch of other keys here)
end
观看次数
cars.new.html
Please note this form passes hidden values to the
appointment_controller
.Value from
@car.name
and other alike are not from atext_field
but rather a pre-defined value based on selections from a previous page which is store in thecars
db.
<%= simple_form_for(@appointment, { class: 'form-horizontal' }) do |f| %>
<%= f.hidden_field :tech_id, value: @tech.id %>
<%= f.hidden_field :car_id, value: @car.id %>
<%= f.hidden_field :service_id, value: @car.service.id %>
<%= f.hidden_field :customer_car, value: current_customer.car %>
<%= f.hidden_field :customer_street_address, value: current_customer.street_address %>
<%= f.hidden_field :customer_city, value: current_customer.city %>
<%= f.hidden_field :customer_state, value: current_customer.state %>
<%= f.hidden_field :customer_zip_code, value: current_customer.zip_code %>
<%= f.hidden_field :service_name, value: @car.service.service_menu.name %>
<%= f.hidden_field :car_name, value: @car.name %>
<%= **And a bunch of other hidden values here which are too long to list** %>
<%= f.submit "Add to appointment", class: 'btn btn-default' %>
<% end %>
service.html
<%= render 'form' %>
_form.html
<%= simple_form_for @service do |f| %>
<div class="field">
<%= f.label "Select service category" %>
<br>
<%= collection_select(:service, :service_menu_id, ServiceMenu.all, :id, :name, {:prompt => true }) %>
<%= f.fields_for :cars do |task| %>
<%= render 'car_fields', :f => task %>
<% end %>
</div>
<div class="links">
<%= link_to_add_association 'Add New Car', f, :cars, class: 'btn btn-default' %>
</div><br>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
_car_fields.html
<div class="nested-fields">
<div class="field">
<%= f.label :name %><br>
<%= f.text_field :name %><br>
<%= f.label :hours %>
<%= f.select :hours, '0'..'8' %>
<%= f.label :minutes %>
<%= f.select :minutes, options_for_select( (0..45).step(15), selected: f.object.minutes) %><br>
<%= f.label :price %><br>
<%= f.text_field :price, :value => (number_with_precision(f.object.price, :precision => 2) || 0) %> <br>
<%= f.label :details %><br>
<%= f.text_area :details %></div>
<%= link_to_remove_association "Remove Car", f, class: 'btn btn-default' %>
<%= f.hidden_field :tech_id, value: current_tech.id %>
<br>
<hr>
</div>
> 编辑 7/14 1:30 下午 EST
应用程序此特定功能的简要介绍
- A
customer
点击了tech
必须提供的服务列表 customer
选择一项服务,例如 brakes,这是tech
在其个人资料中列出的一项服务。- brakes 的属性列在
cars
db cars
belongs_to
到techs
-
customer
可以节省 brakes 这是techs
car
到appointment
[=166 的属性=] - 来自
tech
的大量预定义值、customer
的街道地址等...,car
已预加载到form
用于存储在appointments
table. appointment
充当 历史记录 table。因此,如果tech
决定修改他的任何一个services
在这个例子中 brakes,appointments
tables 将保持不变刹车条目。- 一旦
customer
选择了Add to appointment
按钮,它将保存tech
、customer
和car
属性中的所有预定义值(在这个例子中 brakes) 到appointments
db.
另一种方法是完全摆脱 strong parameters
并执行以下操作:
def create
@appointment = Garage.create(tech_id: @car.service.tech.id,
customer_id: current_customer.id,
customer_street_address: current_customer.street_address,
customer_city: current_customer.city,
customer_state: current_customer.state,
customer_zip_code: current_customer.zip_code,
customer_phone_number: current_customer.phone_number,
customer_location_type: "WILL ADD LATER",
customer_latitude: current_customer.latitude,
customer_longitude: current_customer.longitude,
service_id: @car.service.id,
service_name: @car.service.name,
car_id: @car.id,
car_name: @car.name,
car_time_duration: @car.time_duration,
price: @car.price,
car_details: @car.details)
if @appointment.save
redirect_to techs_path, notice: "This service has been saved."
elsif
redirect_to tech_path, notice: "Uh oh, an error has occurred."
end
end
如果您需要更多详细信息,请告诉我。
我能想到一些方法可以用来避免这种 form
被 hidden_field
膨胀:
- 在用户会话中的控制器之间共享数据,非常类似于电子商务应用程序中的购物车。
- 如果您希望保留应用程序的无状态性,请创建一个模型来临时存储这些信息;这样你只需要在
form
. 中包含一个 - 使用 JavaScript 发出请求,将数据存储在本地对象中并在需要时将它们作为 JSON 传递(使用 AngularJS 很简单)。
hidden_field
无论您选择哪种方法,请记住,在 Web 应用程序中存储大量状态通常是一种代码味道。您可以随时重新考虑您的应用程序,这样您就不需要保留那么多上下文。
您可以将这些内容移动到回调中,并且仅通过表单传递 customer_id 和 car_id。这样车库实例就会知道它的客户和汽车 parents,你可以这样做:
class Garage < ActiveRecord::Base
before_create :copy_stuff
private
def copy_stuff
self.customer_street_address = customer.street_address
self.car_name = car.name
# and so on
end
end
Is there a way I can avoid the hidden_field method of passing values in the view to a controller?
您可以通过将属性 disabled: true
添加到隐藏的输入字段标签来禁用 HTML/view 中的这些字段,以实现您的要求。
不确定语法是否准确,但例如应该是这样的
f.hidden_field :tech_id, value: @tech.id, disabled: true
为了解决我的问题,我对最初 post 的最新编辑说明如下:
EDIT 6/18 1:00 PM EST
- I've renamed my
garages_controller
toappointments_controller
cars_controller
no longer creates a new appointment (formally garages). A new appointment is created in theappointments_controller
只有 hidden_field 我路过 约会视图中的 car_id
/new.html.erb <%= f.hidden_field :car_id, value: @car.id %>
.
在 appointments_controller
中,我分配所有 car
属性执行以下操作。
def create
@appointment = current_customer.appointments.build(appointment_params)
@appointment.tech_id = @appointment.car.service.tech.id
@appointment.price = @appointment.car.price
@appointment.car_name = @appointment.car.name
@appointment.car_details = @appointment.car.details
if @appointment.save
redirect_to appointments_path, notice: "Thank you booking your appointment."
else
redirect_to appointments_path, notice: "Uh oh, an error has occurred. Please try again or contact us for further assistance"
end
end
谢谢大家的回复。 我早该知道的。 :(