如何使用范围作为 POST 数据到 rails 控制器的参数之一

How to use Range as one of parameters for POST Data to rails controller

数据库迁移有 experience 字段定义为范围

class CreateJobPosts < ActiveRecord::Migration[5.1]
  def change
    create_table :job_posts do |t|
      t.string :name, null: false, limit: 100
      t.string :location, null: false, limit: 100
      t.int4range :experience, null: false
      t.text :description, null: false
      t.text :skills, null:false
      t.boolean :active, null: false, default: false
      t.string :seo_meta_keywords, array: true, null: false
      t.string :seo_meta_description, null: false, limit: 150

      t.timestamps
    end
    add_index :job_posts, :name, unique: true
    add_index :job_posts, :location
    add_index :job_posts, :active
  end
end

现在在编写测试时,我让 FactoryGirl 定义了一些像这样的模型

FactoryGirl.define do
    factory :job_post do
        name "DevOps Coach"
        location "Bangalore"
        experience (4..10)
        description 'Test Description'
        skills 'Test Skills'
        active true
        seo_meta_keywords ['keywords','keywords']
        seo_meta_description 'dummy descriptions'
    end
end

并在控制器中

def job_post_params
  params.require(:job_post).permit(:name, :location, :experience, :description, :skills, :active, :seo_meta_description, seo_meta_keywords: [])
end

属性哈希已按预期初始化

[89, 98] in /Users/anadi/Code/bauji/spec/controllers/job_posts_controller_spec.rb
   89:
   90:     context "with invalid params" do
   91:       it "returns a success response (i.e. to display the 'new' template)" do
   92:         byebug
   93:         temp = invalid_attributes
=> 94:         post :create, params: {job_post: invalid_attributes}, session: valid_session
   95:         expect(response).to be_success
   96:       end
   97:     end
   98:   end
(byebug) temp
{:name=>"No Name", :location=>"Nay", :experience=>4..10, :description=>"Test Description", :skills=>"Test skills", :active=>true, :seo_meta_keywords=>["keywords", "keywords"], :seo_meta_description=>"dummy descriptions"}

但是 POST & PUT 方法测试失败,因为 :experience 控制器的属性为 nil

[24, 33] in /Users/anadi/Code/bauji/app/controllers/job_posts_controller.rb
   24:   # POST /job_posts
   25:   # POST /job_posts.json
   26:   def create
   27:     byebug
   28:     @job_post = JobPost.new(job_post_params)
=> 29:     respond_to do |format|
   30:       if @job_post.save
   31:         format.html { redirect_to @job_post, notice: 'Job post was successfully created.' }
   32:         format.json { render :show, status: :created, location: @job_post }
   33:       else
(byebug) @job_post
#<JobPost:0x007fda5fb21920>
(byebug) @job_post.experience
*** ArgumentError Exception: bad value for range

nil

解决方案:

# Never trust parameters from the scary internet, only allow the white list through.
def job_post_params
  raw_post_params = params.require(:job_post).permit(:name, :location, :experience, :description, :skills, :active, :seo_meta_description, seo_meta_keywords: [])
  range_begin, range_end = raw_post_params[:experience].split('..').map { |v| Integer(v) }
  raw_post_params[:experience] = Range.new(range_begin, range_end)
  raw_post_params
end

能再紧凑点吗?

当您发出 POST 请求时,4..10 很可能会转换为 String"4..10"。尝试使用类似于以下内容的方式解析控制器中的字符串:

range_begin, range_end = params[:experience].split('..').map { |v| Integer(v) }
experience = Range.new(range_begin, range_end)

然后您可以将 experience 设置为 JobPost

的属性