Rails: Ignoring non-existant attributes passed to create()

前端 未结 8 1154
执笔经年
执笔经年 2021-02-03 22:12

I have the following Rails model:

class CreateFoo < ActiveRecord::Migration
  def self.up
    create_table :foo do |t|
      t.string :a
      t.string :b
            


        
相关标签:
8条回答
  • 2021-02-03 22:19

    You can use Hash#slice and column_names method exists also as class method.

    hash = {a: 'some', b: 'string', c: 'foo', d: 'bar'}
    Foo.create(hash.slice(*Foo.column_names.map(&:to_sym)))
    
    0 讨论(0)
  • 2021-02-03 22:25

    I use this frequently (simplified):

    params.select!{|x| Model.attribute_names.index(x)}
    Model.update_attributes(params)
    
    0 讨论(0)
  • 2021-02-03 22:25

    I think using the attr_accessible method in the model class for Foo would achieve what you want, e.g.,:

    class Foo < ActiveRecord::Base
    
      attr_accessible :a, :b, :c
    
      ...
    end
    

    This would allow the setting/updating of only those attributes listed with attr_accessible.

    0 讨论(0)
  • 2021-02-03 22:27

    I found a solution that works fairly well, and is ultimately a combination of the above options. It allows for invalid params to be passed (and ignored), while valid ones are mapped correctly to the object.

    def self.initialize(params={})
      User.new(params.reject { |k| !User.attribute_method?(k) })
    end
    

    Now rather than calling User.new(), call User.initialize(). This will "filter" the correct params fairly elegantly.

    0 讨论(0)
  • 2021-02-03 22:36

    I came up with a solution that looks like this, you might find it helpful:

    def self.create_from_hash(hash)
      hash.select! {|k, v| self.column_names.include? k }
      self.create(hash)
    end
    

    This was an ideal solution for me, because in my case hash was coming from an ideal data source which mirrored my schema (except there were additional fields).

    0 讨论(0)
  • 2021-02-03 22:43

    I just had this exact problem upgrading to Rails 3.2, when I set:

    config.active_record.mass_assignment_sanitizer = :strict
    

    It caused some of my create! calls to fail, since fields that were previously ignored are now causing mass assignment errors. I worked around it by faking the fields in the model as follows:

    attr_accessor   :field_to_exclude
    attr_accessible :field_to_exclude
    
    0 讨论(0)
提交回复
热议问题