Rails - 如何避免在视图中使用hidden_​​fields将值传递给控制器​​?

cap*_*ome 6 ruby ruby-on-rails nested-forms ruby-on-rails-4

有没有办法可以避免hidden_field将视图中的值传递给控制器​​的方法?出于安全原因,我更喜欢控制器方法.不幸的@variables是,不支持价值配对strong_parameters.

编辑6/18美国东部时间下午1:00

  1. 我已将garages控制器重命名为appointments
  2. cars_controller不再创造新的appointment(正式的garages).在该中创建新约会 appointments_controller

我目前的结构


路线

Rails.application.routes.draw做

resources :techs, only: [:index, :show], shallow: true do
    resources :cars, only: [:new, :create]
end
Run Code Online (Sandbox Code Playgroud)

资源:约会

#For searchkick
resources :cars, only: [:show] do
    collection do
        get 'search'
    end
end

root "home#index"

end
Run Code Online (Sandbox Code Playgroud)

楷模

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
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

car.rb

class Car < ActiveRecord::Base  
  belongs_to :service
  belongs_to :tech
  has_many :appointments 
end
Run Code Online (Sandbox Code Playgroud)

appointment.rb

class Garage < ActiveRecord::Base
  belongs_to :customer
  belongs_to :tech
  belongs_to :car
end
Run Code Online (Sandbox Code Playgroud)

控制器

cars_controller

def new
  @car = Car.find(params[:id])
  @tech = Tech.find(params[:tech_id])

  @appointment = Garage.new 
end
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

意见

cars.new.html

请注意,此表单将隐藏值传递给appointment_controller.

来自@car.name和其他相似的值不是来自一个text_field预定义的值,而是基于存储在cars数据库中的上一页的选择.

<%= 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 %>
Run Code Online (Sandbox Code Playgroud)

service.html

<%= render 'form' %>
Run Code Online (Sandbox Code Playgroud)

_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 %>
Run Code Online (Sandbox Code Playgroud)

_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>
Run Code Online (Sandbox Code Playgroud)

>编辑美国东部时间下午1点14分

关于该应用程序的这个特定功能的简要概要

  1. 一个customer通过服务列表点击tech所提供的
  2. customer选择例如一个服务制动器其是一个服务tech已经在他的个人资料列出.
  3. 制动器的属性列在carsdb中
  4. cars belongs_totechs
  5. customer可以节省制动器是的一个attribribute techs carappointment
  6. 相当数量从预定义值techcustomer的街道地址,等等,以及car预先加载到form用于在存储appointments表.
  7. appointment充当历史表.因此,如果tech决定services在此示例制动器中修改他的任何一个,则appointments表格将保持不受制动器条目的影响.
  8. 一旦customer选择了Add to appointment按钮,它会保存所有的预定义的值从tech,customercar属性(在本例中刹车)的appointments分贝.

另一种解决方法是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
Run Code Online (Sandbox Code Playgroud)

如果您需要更多详细信息,请与我们联系.

cap*_*ome 1

为了解决我的问题,我对最初帖子的最新编辑说明如下:

编辑 6/18 下午 1:00 美国东部时间

  1. 我已将我的重命名garages_controllerappointments_controller
  2. cars_controller不再创建新的约会(正式车库)。一个新的约会被创建在appointments_controller

我传递的唯一隐藏字段是约会视图 /new.html.erbcar_id中的。 <%= 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
Run Code Online (Sandbox Code Playgroud)

谢谢大家的回复。我应该更清楚。:(