【问题标题】:change the name of nested keys received as parameter更改作为参数接收的嵌套键的名称
【发布时间】:2018-12-11 10:24:14
【问题描述】:

在rails中,嵌套参数通过附加到键的属性传递,然后将其传递给允许

如果我收到普通哈希并想在调用 permit 之前将属性附加到每个嵌套键

怎么做?

"project":{  
  "project_name":"test",
  "tentative_start_date":"2018-12-12",
  "tentative_end_date":"2019-12-12",
"project_roles":[  
     {  
        "role_id":1,
        "project_role_skills":[  
           {  
              "skill":{  
                 "skill_type":"C++",
                 "id":2
              }
           }
        ],
        "project_role_users":[  

        ],
        "role_end_date":"2018-12-12",
        "role_start_date":"2018-12-12"
     }
  ]

} }

这是我收到的请求,我想将属性附加到 project_roles、project_role_skill 等,以便 rails 接受它

请大家帮忙

【问题讨论】:

    标签: ruby-on-rails strong-parameters


    【解决方案1】:

    你试过了吗? Rails 4 - Strong Parameters - Nested Objects 如果它不适合您,您能否指定您当前的表单以及您当前使用permit 的方法是什么?

    【讨论】:

    • 我收到上面提到的响应,我想将其转换为“project_roles_attributes”,因为它是嵌套的,rails 只能以这种方式接受
    • 对不起,我还是不明白。您能否为您的表单和使用许可的控制器操作添加code
    • params.require(:project) .permit(:date, :id, :created_at, :updated_at, :project_name, :tentative_start_date, :tentative_end_date, :actual_start_date, :actual_start_date, :actual_end_date, :customer_id , customer_attributes: [:id, :name, :email, :sales_executive, :contact_person, :notes], project_roles_attributes: [
    • 就像你在这里看到的那样 project_roles_attribute 是允许的,但我得到的响应有 project_roles
    • 好的,如果您尝试我在答案中粘贴的链接中的内容,例如params.require(:project).permit(<all previous attributes here>, :project_roles => [:role_id, :project_role_skills => [] ])。你能得到你想要的允许的属性吗?
    【解决方案2】:

    TL;DR:

    def params_with_deep_appended_nested_attributes(_params)
      modified_params = _params.clone
    
      _params.each do |k, v|
        if v.is_a?(Array)
          modified_params["#{k}_attributes"] = []
    
          v.each_with_index do |vv, index|
            if vv.is_a?(ActionController::Parameters)
              modified_params["#{k}_attributes"][index] = params_with_deep_appended_nested_attributes(vv)
            end
          end
    
          modified_params.delete(k)
    
        elsif v.is_a?(ActionController::Parameters)
          modified_params["#{k}_attributes"] = params_with_deep_appended_nested_attributes(v)
          modified_params.delete(k)
        end
      end
    
      modified_params
    end
    

    使用示例:

    # rails console
    example_json_hash_request = {
      "project": {
        "project_name":"test",
        "tentative_start_date":"2018-12-12",
        "tentative_end_date":"2019-12-12",
        "project_roles": [
           {  
              "role_id":1,
              "project_role_skills":[  
                 {  
                    "skill":{  
                       "skill_type":"C++",
                       "id":2
                    }
                 }
              ],
              "project_role_users":[  
    
              ],
              "role_end_date":"2018-12-12",
              "role_start_date":"2018-12-12"
           }
        ]
      }
    }
    
    # simulate `params` value in the controller
    params = ActionController::Parameters.new(example_json_hash_request)
    
    modified_params = params_with_deep_appended_nested_attributes(params)
    
    pp modified_params.permit!.to_hash
    # {"project_attributes"=>
    #   {"project_name"=>"test",
    #    "tentative_start_date"=>"2018-12-12",
    #    "tentative_end_date"=>"2019-12-12",
    #    "project_roles_attributes"=>
    #     [{"role_id"=>1,
    #       "role_end_date"=>"2018-12-12",
    #       "role_start_date"=>"2018-12-12",
    #       "project_role_skills_attributes"=>
    #        [{"skill_attributes"=>{"skill_type"=>"C++", "id"=>2}}],
    #       "project_role_users_attributes"=>[]}]}}
    

    解决办法:

    # app/controllers/application_controller.rb
    class ApplicationController < ActionController::Base
      # ...
      # I added `= params` to default to the `params` value here in the controller
      def params_with_deep_appended_nested_attributes(_params = params)
        modified_params = _params.clone
    
        _params.each do |k, v|
          if v.is_a?(Array)
            modified_params["#{k}_attributes"] = []
    
            v.each_with_index do |vv, index|
              if vv.is_a?(ActionController::Parameters)
                modified_params["#{k}_attributes"][index] = params_with_deep_appended_nested_attributes(vv)
              end
            end
    
            modified_params.delete(k)
    
          elsif v.is_a?(ActionController::Parameters)
            modified_params["#{k}_attributes"] = params_with_deep_appended_nested_attributes(v)
            modified_params.delete(k)
          end
        end
    
        modified_params
      end
      # ...
    end
    
    # app/controllers/projects_controller.rb
    class ProjectsController < ApplicationController
      def create
        @project = Project.new(project_params)
    
        if @project.save
          # ...
        else
          # ...
        end
      end
    
      def project_params
        params_with_deep_appended_nested_attributes.require(:project_attributes).permit(
          :project_name, :tentative_start_date, :tentative_end_date,
          project_roles_attributes: [
            :role_id, :role_end_date, :role_start_date,
            project_role_skills_attributes: [
              skill_attributes: [
                :skill_type, :id
              ]
            ],
            project_role_users_attributes: []
          ]
        )
      end
    end
    

    别忘了在模型中定义“嵌套属性”:

    # app/models/project.rb
    class Project < ApplicationRecord
      has_many :project_roles
      accepts_nested_attributes_for :project_roles
    end
    
    # app/models/project_role.rb
    class ProjectRole < ApplicationRecord
      belongs_to :project
      has_many :project_role_skills
      has_many :project_role_users
      accepts_nested_attributes_for :project_role_skills
      accepts_nested_attributes_for :project_role_users
    end
    
    # app/models/project_role_skill.rb
    class ProjectRoleSkill < ApplicationRecord
      belongs_to :project_role
      belongs_to :skill
      accepts_nested_attributes_for :skill
    end
    

    待办事项:

    • 添加 params_with_deep_appended_nested_attributes 返回值的缓存,以避免每次调用 params_with_deep_appended_nested_attributes 时都运行代码。

    这个问题让我很感兴趣。将来我可能会发现我的这段代码有用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-02-12
      • 1970-01-01
      • 2022-01-17
      • 1970-01-01
      • 1970-01-01
      • 2014-05-22
      • 1970-01-01
      • 2022-01-18
      相关资源
      最近更新 更多