【问题标题】:Rails form_for Can not save databaseRails form_for 无法保存数据库
【发布时间】:2016-01-20 12:09:49
【问题描述】:

我是新手,在审查我的代码时需要帮助。 无法保存表单数据,也没有显示 Flash 成功消息。 这是在 Rails 服务器中显示的内容:

Started POST "/registrations" for 139.193.122.192 at 2016-01-18 02:02:07 +0000 
Cannot render console from 139.193.122.192! Allowed networks: 127.0.0.1, ::1, 127.0.0.0/127.255.255.255 Processing by RegistrationsController#create as HTML   
Parameters: {"utf8"=>"✓", "authenticity_token"=>"rOZfP2y2huPWAZoUaYjlRXyos5aqiaJh3MTiidXZFRBHJW0yL/rSC4cZwyMuZ//UwwUounNMgzL8HL/yJI8RyQ==", "registration"=>{"name"=>"Yosafat", "last_name"=>"Kakomba", "date_of_birth"=>"06/08/1982", "address"=>"Perum Vila Nusa Indah 2 Blok CC2/18 Jatiasih", "suburb"=>"Bekasi", "post_code"=>"16969", "telephone"=>"622193709536", "email"=>"ariel.kakomba@gmail.com", "news_letter"=>"1", "private_health_fund"=>"0", "exercise_routine"=>"Never", "occupation"=>"Programmer", "past_medical_history"=>"I don't have", "medication"=>"I don't have", "symptoms"=>"I don't have", "terms_of_service"=>"1"}, "gift_voucher"=>"1", "other_references"=>{"{:placeholder=>\"Do you have any other references?\"}"=>""}, "gentle_treatment"=>"1", "head"=>"1", "allergies_or_asthma"=>"1", "commit"=>"Register Now"} 
Unpermitted parameter: last_name    (0.1ms)  begin transaction   Registration Exists (0.2ms)  SELECT  1 AS one FROM "registrations" WHERE LOWER("registrations"."email") = LOWER('ariel.kakomba@gmail.com') LIMIT 1    (0.1ms)  rollback transaction Redirected to https://simpleform3-yoskakomba.c9users.io/ Completed 302 Found in 192ms (ActiveRecord: 1.7ms)


Started GET "/" for 139.193.122.192 at 2016-01-18 02:02:07 +0000 Cannot render console from 139.193.122.192! Allowed networks:
    127.0.0.1, ::1, 127.0.0.0/127.255.255.255 Processing by PagesController#index as HTML   Rendered pages/index.html.erb within layouts/application (37.3ms)   Rendered layouts/_navigation.html.erb (2.3ms)   Rendered layouts/_messages.html.erb (0.1ms)   Rendered layouts/_footer.html.erb (0.1ms) Completed 200 OK in 309ms (Views:
    308.1ms | ActiveRecord: 0.0ms)

当我签入 Rails 控制台时: 数据未保存,闪现成功信息未显示。

这是我的控制器:

class RegistrationsController < ApplicationController
  def new 
    @registration = Registration.new  
  end

  def create 
    @registration = Registration.new(registration_params)

    if @registration.save
      flash[:success] = "Your registration was created succesfully"
      redirect_to root_path
    else
      redirect_to root_path
    end
  end

  private

  def registration_params
    params.require(:registration).permit(:name, :lastname, :date_of_birth,
    :address, :suburb, :post_code, :telephone, :private_health_fund,
    :email, :reference, :news_letter, :occupation, :exercise_routine, :body_conditions,
    :past_medical_history, :medication, :symptoms, :other_experience, :preference, 
    :body_area, :terms_of_service, :drive_and_walk_by, :google_search,    :gift_voucher, :yellow_pages, :yelp, :trip_advisor,:start_local,
    :tenbest, :time_out, :friend_referral, :quiet, :treatment_description, :gentle_treatment, :face,
    :hair_scalp, :head, :chest, :stomach, :back, :buttocks, :arms, :legs, :hands, :feet, :allergies_or_asthma, :open_wounds,
    :numbness_tinglint,
    :skin_condition, :headaches_migraine, :recent_illness_or_surgery, :varicose_veins, :diabetes, :osteoporosis)
  end

end

表单在 index.html.erb 中并使用 ClientSideValidation gem 进行验证

<h2>Registration Form</h2> <hr>

<div class="row">
    <div class="well col-md-8 col-md-offset-2">

      <%= form_for @registration, validate:true do |f| %>

      <div class="row"><!-- FIELD FOR NAME / LAST NAME / DOB -->

        <div class="col-md-4">
          <%= f.label :name %>
          <%= f.text_field :name, placeholder: 'first name' %>
        </div>

        <div class="col-md-4">
          <%= f.label :last_name %>
          <%= f.text_field :last_name, placeholder: 'last name' %>
        </div>

        <div class="col-md-4">
          <%= f.label :date_of_birth %>
          <%= f.text_field :date_of_birth, placeholder: 'Your date of birth ex: DD/MM/YYYY' %>
        </div>
        </div>

  <div class="row"><!-- FIELD FOR ADDRESS / SUBURB/ POSTCODE -->

    <div class="col-md-4">
      <%= f.label :address %>
      <%= f.text_field :address, placeholder: 'Your primary home address' %>
    </div>

    <div class="col-md-4">
      <%= f.label :suburb %>
      <%= f.text_field :suburb, placeholder: 'Your sub urban area' %>
    </div>

    <div class="col-md-4">
      <%= f.label :post_code %>
      <%= f.text_field :post_code, placeholder: 'Address postal code' %>
    </div>

  </div>

  <div class="row"><!-- FIELD FOR TELEPHONE AND EMAIL -->

    <div class="col-md-6">
      <%= f.label :telephone %>
      <%= f.text_field :telephone, placeholder: 'Mobile or landline' %>
    </div>

    <div class="col-md-6">
      <%= f.label :email %>
      <%= f.email_field :email, placeholder: 'Your email address' %>
    </div>

  </div>

  <div class="row checkbox"><!-- FIELD FOR PRIVATE HEALTH FUND & NEWSLETTER CHECKBOX -->

    <div class="col-md-6">
      <%= f.label :news_letter %>
      <%= f.check_box :news_letter %> 
      <p>*Interested in receiving news or promotion from us?</p>
    </div>

    <div class="col-md-6">
     <%= f.label :private_health_fund %>
     <%= f.check_box :private_health_fund %>
     <p>*Do you have private health fund?</p>
    </div>

  </div>
  <div class="row"></div>

  <div class="row checkbox"><!-- FIELD FOR REFERENCES AND PREFERENCE -->

    <div class="col-md-6">
      <b>How Did You Hear About Us?</b><br/><br/ >
      <%= check_box_tag :drive_and_walk_by %> <h8>Drive and Walk by</h8> <br/>
      <%= check_box_tag :google_search %> <h8>Google Search</h8> <br/>
      <%= check_box_tag :gift_voucher %> <h8>Gift voucher</h8> <br/>
      <%= check_box_tag :yellow_pages %> <h8>Google Search</h8> <br/>
      <%= check_box_tag :yelp %> <h8>Yelp</h8> <br/>
      <%= check_box_tag :trip_advisor %> <h8>Trip Advisor</h8> <br/>
      <%= check_box_tag :start_local %> <h8>Start Local</h8> <br/>
      <%= check_box_tag :tenbest %> <h8>10Best</h8> <br/>
      <%= check_box_tag :time_out %> <h8>Time Out</h8> <br/>
      <%= check_box_tag :friend_referral %> <h8>Friend referral</h8> <br/><br/>
      <b>Other References</b><br/>
      <%= text_field :other_references, placeholder: 'Do you have any other references?'%>
    </div>

    <div class="col-md-6">
      <b>Your Preference in Massage Therapy</b><br/><br/ >
      <%= check_box_tag :quiet %> <h8>Quiet environment</h8> <br/>
      <%= check_box_tag :treatment_description %> <h8>Treatment Description</h8> <br/>
      <%= check_box_tag :gentle_treatment %> <h8>Gentle Treatment</h8> <br/><br/>
      <b>Excercise Routine</b><br/>
      <%= f.select :exercise_routine, ['Never', 'Light 1-2 times', 'Moderate 3-4 times', 'Competitive 5-7 times'], validate: false, prompt: 'How many times do you excercise?' %>

    </div>

  </div>

  <div class="row checkbox">

    <div class="col-md-6">
      <b>Body area you want to skip</b><br/><br/ >
      <%= check_box_tag :face %> <h8>Face</h8> <br/>
      <%= check_box_tag :hair_scalp %> <h8>Hair Scalp</h8> <br/>
      <%= check_box_tag :head %> <h8>Head</h8> <br/>
      <%= check_box_tag :chest %> <h8>Chest</h8> <br/>
      <%= check_box_tag :stomach %> <h8>Stomach</h8> <br/>
      <%= check_box_tag :back %> <h8>Back</h8> <br/>
      <%= check_box_tag :buttocks %> <h8>Buttocks</h8> <br/>
      <%= check_box_tag :arms %> <h8>Arms</h8> <br/>
      <%= check_box_tag :legs %> <h8>Legs</h8> <br/>
      <%= check_box_tag :hands %> <h8>Hands</h8><br/>
      <%= check_box_tag :feet %> <h8>Feet</h8><br/>
    </div>

    <div class="col-md-6">
      <b>Existing Health Condition</b><br/><br/ >
      <%= check_box_tag :allergies_or_asthma %> <h8>Allergies or Asthma</h8> <br/>
      <%= check_box_tag :open_wounds %> <h8>Open Wounds</h8> <br/>
      <%= check_box_tag :numbness_tinglint %> <h8>Numbness/Tinglint</h8> <br/>
      <%= check_box_tag :skin_condition %> <h8>Skin Condition</h8> <br/>
      <%= check_box_tag :headaches_migraine %> <h8>Headaches/Migraine</h8> <br/>
      <%= check_box_tag :recent_illness_or_surgery %> <h8>Recent Illness or Surgery</h8> <br/>
      <%= check_box_tag :varicose_veins %> <h8>Varicose Veins</h8> <br/>
      <%= check_box_tag :diabetes %> <h8>Diabetes</h8> <br/>
      <%= check_box_tag :osteoporosis %> <h8>Osteoporosis</h8> <br/><br/>
    </div>

  </div><br/>

  <div class="row"><!-- FIELD FOR OCCUPATION AND PAST MEDICAL HISTORY -->

    <div class="col-md-6">
      <%= f.label :occupation %>
      <%= f.text_area :occupation, placeholder: "Your main job", validate: false %>
    </div>

    <div class="col-md-6">
      <%= f.label :past_medical_history %>
      <%= f.text_area :past_medical_history, placeholder: "Please tell us if you have medication history within 5 years before we proceed your therapy",
      validate: false %>
    </div>

  </div>

  <div class="row"><!-- FIELD FOR MEDICATION AND SYMPTOMS -->

    <div class="col-md-6">
      <%= f.label :medication %>
      <%= f.text_area :medication, placeholder: "Please tell us if you have medication history within 5 years before we proceed your therapy",
      validate: false %>
    </div>

    <div class="col-md-6">
      <%= f.label :symptoms %>
      <%= f.text_area :symptoms, placeholder: "Please tell us if you have any symptoms regarding your existing health condition before we proceed your therapy", validate: false %>
    </div>

  </div>

  <div class="row">

    <div class="col-md-6 col-md-offset-3">
      <b>Terms Of Service</b><br/>

      <h7>Arrival Time</h7>
      <p>Please arrive at least 10 minutes before your treatment. New clients will be asked to fill out a record form.</p>
      <h7>Arrival Late</h7>
      <p>All treatments conclude at the scheduled time.</p>
      <h7>Cancelation Policy<h7>
      <p>When you reschedule or cancel an appointment, we require 24 hours notice; cancellation without notice will incur a cancellation fee of $30.
      Confirmation of an appointment is acknowledgement of this cancellation policy.</p>

    </div>

  </div>

  <div class="row">

    <div class="col-md-6 col-md-offset-3 checkbox">
      <%= f.label "I agree with the terms of service" %>
      <%= f.check_box :terms_of_service %><br/>
      <p>*I read and understood the terms of service</p>

    </div>
  </div>
      <%= f.submit 'Register Now', class: "btn btn-success" %>

  <% end %>

</div><!-- FIELD FOR CLASS WELL -->




**This is my *application.html.erb***

<!DOCTYPE html>
<html>
<head>
  <title>Workspace</title>
  <%= stylesheet_link_tag    'application', media: 'all', 'data-turbolinks-track' => true %>
  <%= javascript_include_tag 'application', 'data-turbolinks-track' => true %>
  <%= csrf_meta_tags %>
</head>
<body>
  <%= render 'layouts/navigation' %>
  
  <div class="container">
    <%= render 'layouts/messages' %>

    
    <%= yield %>
    

    <%= render 'layouts/footer' %>
  </div>
  
</body>
</html>

这是我的注册.rb

class Registration < ActiveRecord::Base   validates :name, presence: true, length: { minimum: 5, maximum: 19 }   validates :last_name, presence: true, length: { minimum: 5, maximum: 19 }   validates :address, presence: true   validates :date_of_birth, presence: true   VALID_EMAIL_REGEX = /\A([\w+\-].?)+@[a-z\d\-]+(\.[a-z]+)*\.[a-z]+\z/i  validates :email, presence: true, length: { maximum: 105 },
                                    uniqueness: { case_sensitive: false },
                                    format: { with: VALID_EMAIL_REGEX }   validates :suburb, presence: true   validates :state, presence: true   validates :post_code, presence: true   validates :telephone, presence: true   validates :reference, presence: true   validates :news_letter, presence: true   validates :occupation, presence: true   validates :exercise_routine, presence: true   validates :body_conditions, presence: true   validates :past_medical_history, presence: true, length: { minimum: 5, maximum: 500 }   validates :medication, presence: true, length: { minimum: 5, maximum: 500 }   validates :symptoms, presence: true, length: { minimum: 5, maximum: 500 }   validates :other_experience, presence: true, length: { minimum: 5, maximum: 500 }   validates :preference, presence: true   validates :body_area, presence: true   validates :terms_of_service, presence: true    end

非常感谢您的帮助

【问题讨论】:

  • “我是新手,在审查我的代码时需要帮助。” - 欢迎

标签: ruby-on-rails activerecord


【解决方案1】:

当您查看您发布的日志时,您会看到有一个Unpermitted parameter: last_name。这是因为在表单中你有last_name,在registration_params 方法中你有lastname

registration_params 中的lastname 更改为last_name 应该可以解决您的问题。

【讨论】:

  • 嗨,帕万,感谢您向我展示“未经许可的参数”上的错误,我没有注意到这一点。我已经在registration_params里改了。
  • @ArielBoham 如果我的回答对你有用,请接受我的回答:)
【解决方案2】:

既然你是新人,我有一些建议(@Pavan的回答是正确的)。


您遇到问题的原因是因为您要求 :last_namevalidation 一起出席:

#app/models/registration.rb
class Registration < ActiveRecord::Base
      validates :name, presence: true, length: { minimum: 5, maximum: 19 } 
      validates :last_name, presence: true, length: { minimum: 5, maximum: 19 }
      validates :address, presence: true
      validates :date_of_birth, presence: true VALID_EMAIL_REGEX = /\A([\w+\-].?)+@[a-z\d\-]+(\.[a-z]+)*\.[a-z]+\z/i
      validates :email, presence: true, length: { maximum: 105 }, uniqueness: { case_sensitive: false }, format: { with: VALID_EMAIL_REGEX }   
      validates :suburb, presence: true
      validates :state, presence: true   
      validates :post_code, presence: true
      validates :telephone, presence: true
      validates :reference, presence: true
      validates :news_letter, presence: true
      validates :occupation, presence: true
      validates :exercise_routine, presence: true
      validates :body_conditions, presence: true
      validates :past_medical_history, presence: true, length: { minimum: 5, maximum: 500 }
      validates :medication, presence: true, length: { minimum: 5, maximum: 500 }
      validates :symptoms, presence: true, length: { minimum: 5, maximum: 500 }
      validates :other_experience, presence: true, length: { minimum: 5, maximum: 500 }
      validates :preference, presence: true
      validates :body_area, presence: true
      validates :terms_of_service, presence: true
end

虽然这很好,但这意味着如果你不传递那个参数,Rails 会返回一个错误。错误存储在附加到返回对象的errors 方法中:

#app/views/registrations/new.html.erb
<%= form_for @registration do |f| %>
   <% if @registration.errors.any? %>
      <% @registration.errors.full_messsages do |message| %> 
          <%= message %>
      <% end %>
   <% end %>
<% end %> 

这将从您的模型返回错误消息。

#app/controllers/registrations_controller.rb
class RegistrationsController < ApplicationController
   def create 
      @registration = Registration.new(registration_params)
      redirect_to root_path, success: "Your registration was created" if @registration.save
      # will render "new" if errors
  end
end

其次,您可以通过声明多个验证(如果它们相同)来大规模清理模型:

#app/models/registration.rb
class Registration < ActiveRecord::Base
      VALID_EMAIL_REGEX = /\A([\w+\-].?)+@[a-z\d\-]+(\.[a-z]+)*\.[a-z]+\z/i

      validates :name, :last_name,     presence: true, length: { minimum: 5, maximum: 19 } 
      validates :email,                presence: true, length: { maximum: 105 }, uniqueness: { case_sensitive: false }, format: { with: VALID_EMAIL_REGEX }   
      validates :past_medical_history, :medication, :symptoms, :other_experience, presence: true, length: { minimum: 5, maximum: 500 }
      validates :date_of_birth, :address, :suburb, :state, :post_code, :telephone, :reference, :news_letter, :occupation, :exercise_routine, :body_conditions, :preference, :body_area, :terms_of_service, presence: true
end

第三,您的模型需要通过它所反映的对象名称来调用。

Ruby 是一种object orientated 语言,这意味着您对系统所做的一切都应以对象为范围。

作为初学者,这无关紧要;随着你的进步,你会意识到拥有......的重要性......

@user = User.find x
@user.do_some_action

...因此,当您拥有Registration 时,如果这是您要存储的数据的性质,那就太好了。如果它不是,您最适合将其名称更改为UserApplicant 等。


最后,您需要减少存储在 one 模型中的所有数据。

您可以将您的模型分成大约 2 个其他模型:

#app/models/registration.rb
class Registration < ActiveRecord::Base
   has_one :address
   has_one :preference
   accepts_nested_attributes_for :address, :preference
end

#app/models/address.rb
class Address < ActiveRecord::Base
   belongs_to :registration
end

#app/models/preference.rb
class Preference < ActiveRecord::Base
   belongs_to :registration
end

这将允许您传递多组数据,而不是将它们全部保存在同一个模型中:

#app/controllers/registrations_controller.rb
class RegistrationsController < ApplicationController
   def new
      @registration = Registration.new
      @registration.build_address
      @registration.build_preference
   end
end

#app/views/registrations/new.html.erb
<%= form_for @registration do |f| %>
   <%= f.fields_for :address do |a| %>
      <%= a.text_field :address %>
   <% end %>
<% end %>

你可以read up more about accepts_nested_attributes_for here

【讨论】:

  • 非常感谢您的帮助 Rich,我将根据您的评论修复它。我以前真的没有注意到。
  • 您好,Richard,您的回答帮助我解决了之前的问题。如果您不介意帮助我进行审核,我对 stackoverflow.com/questions/36050505/… 的 heroku 部署有疑问。非常感谢您的帮助
  • 当然,让我看看怎么回事!
【解决方案3】:

不确定您是否遗漏了一些表单代码,但需要有

    <%= f.submit "Submit" %>
<% end %>

..另外,您的 Flash 消息正在后台运行,但您需要为它们创建一个显示位置。转到您的布局文件夹中的 application.html.erb 并在开始的正文标记后添加:

<% flash.each do |key, value| %>
      <%= content_tag :div, value, class: "#{key}" %>
<% end %>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-12-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多