rails / protected_attributes

Protect attributes from mass-assignment in ActiveRecord models.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Bug using prepend module, save does not populate the fiels

Yoshyn opened this issue · comments

Hi.

I just find a bug in the gem that force me to remove strong_parameter in my app.

Here is the code that work (rails only)

unless File.exist?('Gemfile')
  File.write('Gemfile', <<-GEMFILE)
    source 'https://rubygems.org'
    gem 'rails', '~> 4.2' #, github: 'rails/rails'
    gem 'arel'            #, github: 'rails/arel'
    gem 'sqlite3'
  GEMFILE

  system 'bundle'
end

require 'bundler'
Bundler.setup(:default)

require 'active_record'
require 'minitest/autorun'
require 'logger'

# This connection will do for database-independent bug reports.
ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: ':memory:')
ActiveRecord::Base.logger = Logger.new(STDOUT)

ActiveRecord::Schema.define do
  create_table :posts, force: true  do |t|
    t.string :title
  end

  create_table :post_infos, force: true  do |t|
    t.integer :post_id
    t.string  :basic_field
    t.string  :prepended_field
  end
end

module Prepends
  module Post

    def post_info
      merged_attributes = { prepended_field: 'YATA' }.stringify_keys.merge(super().try(:attributes) || {})

      if super.nil?
        send(:build_post_info, merged_attributes )
      elsif (!super().valid? && self.new_record?)
        super().attributes   = merged_attributes
        super()
      else
        super()
      end
    end
  end
end

class Post < ActiveRecord::Base
  prepend Prepends::Post

  has_one :post_info, dependent: :destroy
  accepts_nested_attributes_for :post_info, allow_destroy: true
end

class PostInfo < ActiveRecord::Base
  belongs_to :post
  validates :prepended_field, presence: true
end

class BugTest < Minitest::Test
  def test_association_stuff
    post = Post.new( { title: 'Testing', post_info_attributes: { basic_field: 'YOLO' } } )

    post.save!
    assert_equal 1,                 PostInfo.count
    assert_equal post.id,           PostInfo.first.post.id
    assert_equal 'YOLO',            PostInfo.first.basic_field
    assert_equal 'YATA',            PostInfo.first.prepended_field
  end
end

Here is the code that failed (with protected_attributes)

unless File.exist?('Gemfile')
  File.write('Gemfile', <<-GEMFILE)
    source 'https://rubygems.org'
    gem 'rails', '~> 4.2' #, github: 'rails/rails'
    gem 'arel'            #, github: 'rails/arel'
    gem 'sqlite3'
    gem 'protected_attributes'
  GEMFILE

  system 'bundle'
end

require 'bundler'
Bundler.setup(:default)

require 'active_record'
require 'minitest/autorun'
require 'logger'
require 'protected_attributes'

# This connection will do for database-independent bug reports.
ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: ':memory:')
ActiveRecord::Base.logger = Logger.new(STDOUT)

ActiveRecord::Schema.define do
  create_table :posts, force: true  do |t|
    t.string :title
  end

  create_table :post_infos, force: true  do |t|
    t.integer :post_id
    t.string  :basic_field
    t.string  :prepended_field
  end
end

module Prepends
  module Post

    def post_info
      merged_attributes = { prepended_field: 'YATA' }.stringify_keys.merge(super().try(:attributes) || {})

      if super.nil?
        send(:build_post_info, merged_attributes )
      elsif (!super().valid? && self.new_record?)
        super().attributes   = merged_attributes
        super()
      else
        super()
      end
    end
  end
end

class Post < ActiveRecord::Base
  prepend Prepends::Post

  has_one :post_info, dependent: :destroy
  accepts_nested_attributes_for :post_info, allow_destroy: true

  attr_accessible :title, :post_info_attributes
end

class PostInfo < ActiveRecord::Base
  belongs_to :post
  validates :prepended_field, presence: true

  attr_accessible :basic_field, :prepended_field
end

class BugTest < Minitest::Test
  def test_association_stuff
    post = Post.new( { title: 'Testing', post_info_attributes: { basic_field: 'YOLO' } } )

    post.save!
    assert_equal 1,                 PostInfo.count
    assert_equal post.id,           PostInfo.first.post.id
    assert_equal 'YOLO',            PostInfo.first.basic_field
    assert_equal 'YATA',            PostInfo.first.prepended_field
  end
end

Which produce :

Finished in 0.028528s, 35.0529 runs/s, 0.0000 assertions/s.

  1) Error:
BugTest#test_association_stuff:
ActiveRecord::RecordInvalid: Validation failed: Post info prepended field can't be blank
    ~/codes/tmp/.gems/gems/activerecord-4.2.1/lib/active_record/validations.rb:79:in `raise_record_invalid'
1 runs, 0 assertions, 0 failures, 1 errors, 0 skips
``

Yeah. I don't think there is a way to make this gem work with prepend but I had not investigate it yet. Could you check that?

Closing because of it is stale