Rails reconstructs class constants into tables corresponding to the database

Source: Internet
Author: User

The problem is this: the original code. The Html.erb page has a SELECT element with each item corresponding to the class constant in the model:

<%= f.select:p ay_type,order::P ayment_types,prompt: ' Select a PAYMENT method '%>

The constants in the class are defined as follows:

Class Order < activerecord::base  payment_types = ["Check", "Credit card", "Purchase Order"]end

Now I want to reconstruct the payment_types to the table in the database, so we have a tentative first step, first create a model as follows:

Rails g model Payment_types type:string

Rake Db:migrate

The second step is to write a script to import the constants into the table:

Paymenttype.transaction do  Order::P ayment_types.each do |type|    Paymenttype.create (type:type)  endend

But there was an error running rails runner script/load_payment_types.rb, as follows:

/var/lib/gems/2.1.0/gems/activerecord-4.2.0/lib/active_record/inheritance.rb:215:in ' subclass_from_attributes ': Invalid single-table inheritance Type:check is not a subclass of Paymenttype (Activerecord::subclassnotfound)

After confirming that there is no syntax error, it is possible that the type name and a method or property in the frame are in conflict, so that only the name is changed:

Rails g Migration Rename_type_to_payment_types

Modify the name of the type in the. rb file that is generated in the Migrate directory:

Class Renametypetopaymenttypes < activerecord::migration  def change    rename_column:p ayment_types,:type,: Pay_type  EndEnd

Then rake db:migrate, and then modify the code in the LOAD_PAYMENT_TYPES.RB to conform to the changes:

Paymenttype.transaction do  paymenttype.delete_all  Order::P ayment_types.each do |type|    Paymenttype.create (pay_type:type)  endend

Then execute Rails runner script/load_payment_types.rb, then there's no problem:), the third step is to modify the new method in the controller, adding the following line:

    @payment_types = PaymentType.all.map {|type|type.pay_type}

The fourth step is to modify the code in the. Html.erb as follows:

<%= f.select:p Ay_type, @payment_types, prompt: ' Select a payment method '%>

Fifth step don't forget to modify the model's validation code:

Class Order < ActiveRecord::Base  Validates:name,:address,:email,:p ay_type,presence:true  #validates:p ay _type,inclusion:payment_types  validates:p ay_type,inclusion:paymenttype.all.map {|type|type.pay_type}end

Running it seems to be no problem. But wait! If New.html.erb all blank to submit the order, it will report an error, indicating that nil object does not have empty? Method! Think about it a little bit. The validation method of the order class is called when the Order.save is left blank, so the validation fails, the Save method will fail, and the render will be re-new.html.erb, but then the value of @payment_types does not exist. So in the Create method, add the new method to the sentence!

What about the horse? There are so many @payment_types in the code that violate the dry principle! We can consider putting it in the class variable of the order controller, but consider if the Pay_ in the database Types has the problem of modifying how to react to class variables in a timely manner. For simplicity's sake, the pay_type in the Payment_types table is rarely modified, and if modified can restart the Rails server to apply the changes, it can be further refactored:

First, class variables and class variable properties are added to the order controller:

Class Orderscontroller < Applicationcontroller  @ @payment_types = PaymentType.all.map {|type|type.pay_type}  def self.payment_types    @ @payment_types  endend

Then make the following changes in the New.html.erb and order model

#in new.html.erb<%= f.select:p ay_type,orderscontroller.payment_types,prompt: ' Select a payment method '%> #in Order.rbvalidates:p Ay_type,inclusion:orderscontroller.payment_types

At this time the original new and create variables @payment_types can delete the bird. This refactoring is over! :

Rails reconstructs class constants into tables corresponding to the database

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.