Giter Site home page Giter Site logo

attribute_normalizer's Introduction

Attribute Normalizer

Build Status

A little normalization goes a long way in helping maintain data integrity.

Change History

  • 1.1.0
    • Allow the use of default normalizers before and after the evaluation of a given block
  • 1.0.0
    • DSL Changes
    • Default attributes to normalize
    • mongid support
  • 0.3.0
    • Normalizer Chaining
    • Built-in common normalizers
    • Ability to change the default attribute normalization.
  • 0.2.1
    • ActiveModel Support Built-in
    • Fix for :with option getting dropped when normalizing several attributes
  • 0.2.0
    • Removed the normalization on reads.
    • Added out of the box support for CassandraObjects
    • Included RSpec matcher normalizer_attribute
    • Added the ability to define global normalizers
    • Strings no longer get ‘strip’ called on them before getting passed on to your defined normalization blocks

Supported ORMs

  • Active Model
  • Active Record
  • CassandraObjects

I will gladly take pull requests to automatically load Attribute Normalizer into your ORM of choice if requested. To test it out on your ORM just include the AttributeNormalizer module after requiring it.

# your_initializer.rb
require 'attribute_normalizer'
YourORM::Base.send :include, AttributeNormalizer

Install

sudo gem install attribute_normalizer

Then just required it. Rails usages is as follows.

Rails 2

# config/environment.rb
config.gem 'attribute_normalizer'

Rails 3

# Gemfile
gem 'attribute_normalizer'

It also still works as a traditional Rails plugin.

./script/plugin install git://github.com/mdeering/attribute_normalizer.git

Usage

Lets create a quick test/spec for what we want to accomplish as far as normalization using the built in RSpec matcher.

# spec/models/book_spec.rb
describe Book do
  it { should normalize_attribute(:author) }
  it { should normalize_attribute(:price).from('$3,450.98').to(3450.98) }
  it { should normalize_attribute(:summary).from('   Here is my summary that is a little to long   ').to('Here is m...') }
  it { should normalize_attribute(:title).from(' pick up chicks with magic tricks  ').to('Pick Up Chicks With Magic Tricks') }
  it { should normalize_attribute(:slug).from(' Social Life at the Edge of Chaos    ').to('social-life-at-the-edge-of-chaos') }
  it { should normalize_attribute(:limited_slug).from(' Social Life at the Edge of Chaos    ').to('social-life') }
end

The following normalizers are already included with the +0.3 version of the gem.

  • :blank Will return nil on empty strings
  • :phone Will strip out all non-digit characters and return nil on empty strings
  • :strip Will strip leading and trailing whitespace.
  • :squish Will strip leading and trailing whitespace and convert any consecutive spaces to one space each

And lets predefine some normalizers that we may use in other classes/models or that we don’t want to clutter up our class/model’s readability with.

# config/initializers/attribute_normalizer.rb
AttributeNormalizer.configure do |config|

  config.normalizers[:currency] = lambda do |value, options|
    value.is_a?(String) ? value.gsub(/[^0-9\.]+/, '') : value
  end

  config.normalizers[:truncate] = lambda do |text, options|
    if text.is_a?(String)
      options.reverse_merge!(:length => 30, :omission => "...")
      l = options[:length] - options[:omission].mb_chars.length
      chars = text.mb_chars
      (chars.length > options[:length] ? chars[0...l] + options[:omission] : text).to_s
    else
      text
    end
  end

  # The default normalizers if no :with option or block is given is to apply the :strip and :blank normalizers (in that order).
  # You can change this if you would like as follows:
  # config.default_normalizers = :strip, :blank

end

The normalize_attributes method is eager loaded into your ORM. normalize_attribute is aliased to normalize_attributes and both can take in a single attribute or an array of attributes.

class Book < ActiveRecord::Base

  # By default it will strip leading and trailing whitespace
  # and set to nil if blank.
  normalize_attributes :author, :publisher

  # Using one of our predefined normalizers.
  normalize_attribute  :price, :with => :currency

  # Using more then one of our predefined normalizers including one with options
  normalize_attribute :summary, :with => [ :strip, { :truncate => { :length => 12 } } ]

  # You can also define your normalization block inline.
  normalize_attribute :title do |value|
    value.is_a?(String) ? value.titleize.strip : value
  end

  # Or use a combination of normalizers plus an inline block.
  # the normalizers in the :with option will each be evalulated
  # in order and the result will be given to the block.
  # You could also use option :before in place of :with
  normalize_attribute :slug, :with => [ :strip, :blank ] do |value|
    value.present? && value.is_a?(String) ? value.downcase.gsub(/\s+/, '-') : value
  end

  # Use builtin normalizers before and after the evaluation of your inline
  # block
  normalize_attribute :limited_slug, :before => [ :strip, :blank ], :after => [ { :truncate => { :length => 11, :omission => '' } } ] do |value|
    value.present? && value.is_a?(String) ? value.downcase.gsub(/\s+/, '-') : value
  end

end

All the specs will pass now. Here is quick look at the behaviour from a console.

summary = 'Here is my summary that is a little to long'
title   = 'pick up chicks with magic tricks'
book    = Book.create!(:author => '', :price => '$3,450.89', :summary => summary, :title => title, :slug => title, :limited_slug => title)
book.author       # => nil
book.price        # => 3450.89
book.summary      # => 'Here is m...'
book.title        # => 'Pick Up Chicks With Magic Tricks'
book.slug         # => 'pick-up-chicks-with-magic-tricks'
book.limited_slug # => 'pick-up-chi'

Test Helpers

If you are running RSpec there is a matcher available for use. Usage can been seen above. Include it as follows.

Rails 2

# spec/spec_helper.rb
RSpec.configure do |config|
  config.include AttributeNormalizer::RSpecMatcher, :type => :models
end

Rails 3

# spec/spec_helper.rb
RSpec.configure do |config|
  config.include AttributeNormalizer::RSpecMatcher, :type => :model
end

I will gladly take a patch to add a macro to Test::Unit if someone submits it.

Credits

Original module code and concept was taken from Dan Kubb during a project we worked on together. I found that I was consistently using this across all my projects so I wanted to plugin-er-size and gem this up for easy reuse.

Copyright

Copyright © 2009-2010 Michael Deering See MIT-LICENSE for details.

attribute_normalizer's People

Contributors

adam12 avatar d1plo1d avatar dmeremyanin avatar e2 avatar fudanchii avatar gducharme avatar ggordan avatar heydiplo avatar jdewyea avatar joaovitor avatar joshk avatar kevinschiffmann avatar logicaltext avatar mauriciopasquier avatar mdeering avatar neaf avatar samleb avatar sobrinho avatar tmaier avatar willglynn avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

attribute_normalizer's Issues

2.0 Release

  • Update for RSpec 3 expect syntax-
  • With the removal of the default_attributes stuff we are breaking API so should be a major release.-
  • Make normalizers more pluggable with a correct API and registration.

Breaks abstract models

Adding this gem will break abstract model setups. For instance:

class Color < ActiveRecord::Base  
  self.abstract_class = true
end

class Green < Color
end

Without gem:

irb(main):001:0> Green.table_name
=> "greens"

With gem:

irb(main):001:0> Green.table_name
=> "colors"

Tested on Rails 3.2.6

Automatically apply default normalizers

In most cases strip whitespaces is desirable for run by default for all model attributes. This could be provide via using macro in model without any options:

normalize_attributes # apply default normalizers for all attributes

And for exceptional cases:

normalize_attributes :only => [:title, :name]
normalize_attributes :except => [:raw_data]

Another gem https://github.com/rmm5t/strip_attributes uses this conventions but it lacks functionality.

It would be handy and much more in rails style if you implement this feature

Normalize empty json string to "{}"

I created a custom normalizer:

  config.normalizers[:json] = lambda do |text, options|
    if text == ""
      {}.to_json # or "{}"
    else
      text
    end
  end

But the spec fails oddly:
it { should normalize_attribute(:rawInfo).from("").to({}.to_json) }
...

Failure/Error: it { should normalize_attribute(:rawInfo).from("").to({}.to_json) }
       rawInfo did not normalize as expected! "{}" != "{}"

I've checked the text encoding format of my source files, and used .to_json, also to eliminate that as in issue. This is only an issue for the spec helper, or something else?

Thanks,
j

Default attributes?

I was writing a PR (here's my branch with failing tests) about default attributes not beign applied, but then I ran into the commented-out code and this commit. I liked the idea of default attributes but if this is the direction the gem is going, at least we should fix the readme and deprecate the setter in the configuration.

Don't pollute target object namespace

Currently if somebody uses something like normalize_attribute :name it makes impossible to have normalize_name method in the corresponding model, I suggest the defined method is at least given some kind of unique name (using prefix or similar) so that collisions are less likely.

Override inherited for ActiveRecord::Base

Sorry for my english.

I use attribute_normalizer with globalize3
In model_inclusions you override inherited method and call (subclass.table_exists? rescue false). Here suppressed exception if connection isn't established.

For commands bundle exec rake db:drop db:create db:migrate and bundle exec rails console connection set at different times. According to this behavior will be different.
In globalize3 translation run overrided inherited method before class Translation will abstract class translation.
As a result, I get the name of the tables, the localization is the same for all models.
If remove check model_inclusions and model_inclusions it works and spec pass.
Why do we need this test?

NoMethodError: super: no superclass method `<attribute>=` when using abstract_class

As of #77 i have created a new issue for this problem. I use version 1.2.0 of attribute_normalizer, Rails 4.2.1 and Ruby 2.0 (or 2.3, doesn't matter).

Steps to reproduce:

# Gemfile
source 'https://rubygems.org/'

gem 'rails', '4.2.1'
gem 'attribute_normalizer', '1.2.0'
# [...]

# app/models/foo.rb
class Foo < ActiveRecord::Base                                                                                
  self.abstract_class = true                                                                                                                                                                                         
  normalize_attribute :bar                                                                                              
end

# app/models/baz.rb
class Baz < Foo
  self.table_name = 'foobar'
end
$ bundle exec rails c
Loading development environment (Rails 4.2.1)
irb(main):001:0> b = Baz.new
=> #<Baz id: nil, bar: nil>
irb(main):002:0> b.bar = "foo"
NoMethodError: super: no superclass method `bar=' for #<Baz id: nil, bar: nil>
        from /Users/shoffmann/test_app/vendor/bundle/ruby/2.0.0/gems/activemodel-4.2.1/lib/active_model/attribute_methods.rb:430:in `method_missing'
[...]

It does work with this workaround from issue #23.

Get attribute name within normalizer

I would like to create a normalizer with auto-truncation feature, so I need to know the current limit of a table field. To determine the length of the field I need to know the name of the attribute.

Here's what I want:

  config.normalizers[:auto_truncate] = lambda do |value, options|
    column = options[:model].column_for_attribute(options[:attribute_name])

    if value.is_a?(String) && column.limit
      value.mb_chars.limit(column.limit)
    else
      value
    end
  end

I looked into the source and found nothing relative to the topic. What if I add :attribute_name and :model keys into options hash and send PR?

Better naming for old_#{attribute}

https://github.com/mdeering/attribute_normalizer/blob/master/lib/attribute_normalizer/model_inclusions.rb#L51-L57

          alias_method "old_#{attribute}=", "#{attribute}="

          define_method "#{attribute}=" do |value|
            normalized_value = self.send(:"normalize_#{attribute}", value)
            self.send("old_#{attribute}=", normalized_value)
          end

old_ is not a good naming scheme.

Better use something like attribute_without_attribute_normalizer and attribute_with_attribute_normalizer

Some resources showing this naming convention:

Attribute normalizer and abstract classes

Attribute normalizer seems to be incompatible with abstract classes.

For example, there is an abstract class:

class Foo < ::ActiveRecord::Base
  self.abstract_class = true
  ...
end

Attribute normalizer has this code:

def inherited(subclass)
  super
  if subclass.respond_to?(:table_exists?) && (subclass.table_exists? rescue false)
    subclass.normalize_default_attributes
  end
end

So it calls table_exists? before the assignment of abstract_class, which leads to making the table name of the class calculated wrong. So table_exists? must not be called in 'inherited'.

Triggering all normalizers manually?

I would like to trigger manually all the normalizers, is it currently possible?
My use case is a form object using Structs as items.
I use the constructor to pass all the attributes from the params hash instead of using each attribute= methods, therefore attribute_normalizer is not triggered.

class SDOwnUseItem < Struct.new(:name, :packaging, :uom, :um3, :uweight)
  include AttributeNormalizer
  normalize_attributes :name, :packaging
end
#usage
SDOwnUseItem.new(attributes.slice(:name, :packaging, :uom, :um3, :uweight)) #<- I would like this to trigger the normalisation

Better error message for missing attribute

When an attribute doesn't exist on a model,

it { should normalize_attribute(:foo) }

gives the error:

Failure/Error: it { should normalize_attribute(:foo) }
     NoMethodError:
       undefined method `old_foo=' for #<Bar:0x007fe72c21f2a8>

It seems to me this error message should be more useful by telling you the attribute is missing.

Adding normalizers to default normalizers?

Hello.
Is there a way of adding an additional normalizer to the defaults normalizers? something like:
normalize_attribute :first_name, :with => :titleize, :defaults => true

Ruby 1.9

FYI: some specs fail under Ruby 1.8 because of this commit (hashes aren't ordered in 1.8), and you can't guarantee that strip is being applied before truncate. I do like the newer DSL, but perhaps the docs should say that attribute_normalizer is only compatible with Ruby versions greater than 1.9. I'm happy to help with any documentation updates if you like.

RSpecMatcher is out of date

Under rails 4.1.1, attribute_normalizer 1.1.0, and rspec 3.0.1, I get the following deprecation warning:

"AttributeNormalizer::RSpecMatcher::NormalizeAttribute implements a legacy RSpec matcher protocol. For the current protocol you should expose the failure messages via the failure_message and failure_message_when_negated methods."

Can't get it to work with nested_attributes

I have model with nested attibutes:
accepts_nested_attributes_for :addresses, :reject_if => proc { |attrs| attrs.all? { |k, v| v.blank? } }
And normalizer:
normalize_attributes :addresses_attributes do |value|
value.each_key do |k|
value[k].delete('city')
end if value.is_a?(HashWithIndifferentAccess)
value
end
But I got error:
super: no superclass method addresses_attributes=' /usr/lib/ruby/gems/1.8/gems/activerecord-2.3.8/lib/active_record/attribute_methods.rb:259:inmethod_missing'
/usr/lib/ruby/gems/1.8/gems/attribute_normalizer-0.2.0/lib/attribute_normalizer.rb:58:in `addresses_attributes='

boolean normalizer and active record

I'm using this custom normalizer with virtual boolean attributes

# Changes true, 'true', 1 and '1' into true
config.normalizers[:boolean] = lambda do |value, options|
  ActiveRecord::ConnectionAdapters::Column.value_to_boolean value
end

I was about to send a pull request but I'm not sure if it's ok to add this ActiveRecord dependency. If it's not, I could use the code directly. It's something like this:

  TRUE_VALUES = [true, 1, '1', 't', 'T', 'true', 'TRUE', 'on', 'ON'].to_set

  def value_to_boolean(value)
    if value.is_a?(String) && value.blank?
      nil
    else
      TRUE_VALUES.include?(value)
    end
  end

Disregard all of this if you don't want to add a normalizer useful only for virtual boolean attributes :)

Make it work to use normalize_attribute with virtual attributes created with attr_accessor

I tried to do this:

class User < ActiveRecord::Base
  attr_accessor :division_id
  normalize_attributes :division_id, :with => [:strip, :blank]
end

But got this error

NoMethodError (super: no superclass method `division_id=' for #<User:0x00000013035300>):

The error comes from the call to super here (attribute_normalizer/model_inclusions.rb):

        define_method "#{attribute}=" do |value|
          super(self.send(:"normalize_#{attribute}", value))
        end

This was my workaround:

module DivisionId
  attr_writer :division_id
end
class User < ActiveRecord::Base
  include DivisionId
  normalize_attributes :division_id, :with => [:strip, :blank]
end  

It would be nice if it just worked without any workaround though. Do you think that would be possible?

The only way I can think of right now to make it just work is to somehow fall back to an alias_method_chain if you can't use super .

Reopen #23?

#23 was closed because of missing infos to reproduce the issue. Perhaps the maintainers can now reopen the issue.

Undefined method old_[attribute]= in Rails 3.2.3

After upgrading from Rails 3.0, I get the above. I'm just really looking for confirmation that someone else has got this gem working with Rails 3.2, so I can see if it's something I must fix on my side.
Here's the stack trace:

NoMethodError: undefined method `old_account_number=' for #<BankAccount:0x00000006089f48>
from /home/daveungerer/.rvm/gems/ruby-1.9.3-p194/gems/activemodel-3.2.3/lib/active_model/attribute_methods.rb:407:in `method_missing'
from /home/daveungerer/.rvm/gems/ruby-1.9.3-p194/gems/activerecord-3.2.3/lib/active_record/attribute_methods.rb:148:in `method_missing'
from /home/daveungerer/.rvm/gems/ruby-1.9.3-p194/gems/attribute_normalizer-1.0.1/lib/attribute_normalizer/model_inclusions.rb:49:in `rescue in block (2 levels) in normalize_attributes'
from /home/daveungerer/.rvm/gems/ruby-1.9.3-p194/gems/attribute_normalizer-1.0.1/lib/attribute_normalizer/model_inclusions.rb:45:in `block (2 levels) in normalize_attributes'

It seems that, at the point the code in model_inclusions.rb is run, the :account_number= method is not yet defined, which causes it to never define :old_account_number=

One other thing: I'm using model inheritance, so if it turns out it that the gem is Rails 3.2 compatible, I'll investigate if that is the actual cause.

undefined method `normalize_attribute'

I am using rails 3.2.8 and 1.1.0 version of attribute_normalizer. I am seeing this error when I create an instance of my model class using ActiveModel.

undefined method `normalize_attribute'

I am using this in my initializer file:

AttributeNormalizer.configure do |config|
  config.normalizers[:subnets] = lambda do |value, options|
    value.join(',')
  end
end

Then in my model file I am using

include ActiveModel::AttributeMethods
include ActiveModel::Validations
include ActiveModel::Conversion
extend ActiveModel::Naming
extend ActiveModel::Translation
extend ActiveModel::Callbacks

normalize_attribute :subnets, :with => :subnets

Release 1.2

There are some needed fixes in 1.2.0.b that makes attribute_normalizer work better with other ActiveRecord-patching gems. (In our case, acts_as_fu).

Is 1.2.0 good to release to rubygems, or are there any outstanding issues remaining?

Shorthand for manual normalization

A quick little method I wrote for myself to be able to manually trigger a test.

Usage

AttributeNormalizer.normalize(:phone, "555-123-5123 ")
> 5551235123

Implementation

module AttributeNormalizer
  def self.normalize(normalizer_sym, value)
    configuration.normalizers[normalizer_sym].normalize(value)
  end
end

May be worth adding a slightly more robust method to the library itself.

Thanks for the good work, @mdeering!

Normalizing groups

Potential feature idea - grouping of normalizers within the initializer for re-use purposes. Something similar to:

AttributeNormalizer.configure do |config|
   config.groupings[:group] = [:strip, :blank, :custom, :custom]
end

class Model
   attribute_normalizer :code, with => :group
end

Default normalizers and default attributes

Hi,

I've added the support to add default attributes and normalize those automatically using the initializer file.

Also, I've added the support to add an attribute with one or more specific normalizers into the default attributes using the initializer file too.

You can check those changes in the following link:

karmatr0n@2946644

Thank you, your gem is really useful for my project!

Alex --

Crashes Ruby when used with mutant gem

Just an FYI I started to use this gem latest version yesterday and was pleased with it's benefits.

However I am heavily using mutation testing (mbj/mutant) of whom @dkubb is a contributor as well. I am a relative noobie. When I run my test suite after installing this gem it crashes Ruby 2.2 (appears to run out of stack). I have 100's of crash dumps and misbehavior documented in my mutation logs. When I remove the gem from the bundle normal behavior returns. It does not appear to be related to adding "normalize_attributes" statements. I spent a couple hours trying to get a simplified reproducible repo, but was not able too.

I am not blaming this gem as I don't know whether it is concurrency in mutant, or something this gem is doing inside a forked environment. I just really do not know.

I can say that in resurveying the landscape of gem's with this ones' functionality I ran across normalizr and replaced attribute_normalizer with that gem and got satisfactory functionality as well as it did not crash Ruby when running mutation testing.

Just a caution. If you want more detail I would be more than happy to add some gists with the crash dumps. I just wanted to make you aware of this.

Documentation is out of date

config.default_normalizers = { :strip => true, :blank => true }
should_be
config.default_normalizers = [:strip, :blank]

Also,
normalize_attribute :price, :currency => true
should_be
normalize_attribute :price, :with => [:currency]

HABTM adding/removing is broken (badly!)

The following is with a brand new Rails 4.1.4 app, Ruby 2, PostgreSQL. The only addition to the Gemfile is "attribute_normalizer" -- but I am not using it in any models. Removing the gem makes the code work as expected.

Not sure what the issue is. Only thing I can think of is that this gem is over writing a method Rails uses internally?

class Foo < ActiveRecord::Base
  has_and_belongs_to_many :bars
end
class Bar < ActiveRecord::Base
  has_and_belongs_to_many :foos
end
class FooBarsHabtm < ActiveRecord::Migration
  def change
    create_table :bars_foos, id: false do |t|
      t.references :foo, index: true
      t.references :bar, index: true
    end
  end
end
$ rails runner "f = Foo.create(name:'F'); b = Bar.create(name:'B'); f.bars << b"
/.../gems/activerecord-4.1.4/lib/active_record/connection_adapters/postgresql_adapter.rb:822:in `async_exec': PG::UndefinedTable: ERROR:  relation "" does not exist (ActiveRecord::StatementInvalid)
LINE 5:               AND cons.conrelid = '""'::regclass
                                          ^
:             SELECT attr.attname
            FROM pg_attribute attr
            INNER JOIN pg_constraint cons ON attr.attrelid = cons.conrelid AND attr.attnum = cons.conkey[1]
            WHERE cons.contype = 'p'
              AND cons.conrelid = '""'::regclass
  from /.../gems/activerecord-4.1.4/lib/active_record/connection_adapters/postgresql_adapter.rb:822:in `block in exec_no_cache'
  from /.../gems/activerecord-4.1.4/lib/active_record/connection_adapters/abstract_adapter.rb:373:in `block in log'
  from /.../gems/activesupport-4.1.4/lib/active_support/notifications/instrumenter.rb:20:in `instrument'
  from /.../gems/activerecord-4.1.4/lib/active_record/connection_adapters/abstract_adapter.rb:367:in `log'
  from /.../gems/activerecord-4.1.4/lib/active_record/connection_adapters/postgresql_adapter.rb:822:in `exec_no_cache'
  from /.../gems/activerecord-4.1.4/lib/active_record/connection_adapters/postgresql/database_statements.rb:137:in `exec_query'
  from /.../gems/activerecord-4.1.4/lib/active_record/connection_adapters/postgresql/schema_statements.rb:362:in `primary_key'
  from /.../gems/activerecord-4.1.4/lib/active_record/connection_adapters/postgresql/database_statements.rb:166:in `sql_for_insert'
  from /.../gems/activerecord-4.1.4/lib/active_record/connection_adapters/abstract/database_statements.rb:94:in `insert'
  from /.../gems/activerecord-4.1.4/lib/active_record/connection_adapters/abstract/query_cache.rb:14:in `insert'
  from /.../gems/activerecord-4.1.4/lib/active_record/relation.rb:64:in `insert'
  from /.../gems/activerecord-4.1.4/lib/active_record/persistence.rb:502:in `_create_record'
  from /.../gems/activerecord-4.1.4/lib/active_record/attribute_methods/dirty.rb:87:in `_create_record'
  from /.../gems/activerecord-4.1.4/lib/active_record/callbacks.rb:306:in `block in _create_record'
  from /.../gems/activesupport-4.1.4/lib/active_support/callbacks.rb:82:in `run_callbacks'
  from /.../gems/activerecord-4.1.4/lib/active_record/callbacks.rb:306:in `_create_record'
  from /.../gems/activerecord-4.1.4/lib/active_record/timestamp.rb:57:in `_create_record'
  from /.../gems/activerecord-4.1.4/lib/active_record/persistence.rb:482:in `create_or_update'
  from /.../gems/activerecord-4.1.4/lib/active_record/callbacks.rb:302:in `block in create_or_update'
  from /.../gems/activesupport-4.1.4/lib/active_support/callbacks.rb:113:in `call'
  from /.../gems/activesupport-4.1.4/lib/active_support/callbacks.rb:113:in `call'
  from /.../gems/activesupport-4.1.4/lib/active_support/callbacks.rb:166:in `block in halting'
  from /.../gems/activesupport-4.1.4/lib/active_support/callbacks.rb:166:in `call'
  from /.../gems/activesupport-4.1.4/lib/active_support/callbacks.rb:166:in `block in halting'
  from /.../gems/activesupport-4.1.4/lib/active_support/callbacks.rb:86:in `call'
  from /.../gems/activesupport-4.1.4/lib/active_support/callbacks.rb:86:in `run_callbacks'
  from /.../gems/activerecord-4.1.4/lib/active_record/callbacks.rb:302:in `create_or_update'
  from /.../gems/activerecord-4.1.4/lib/active_record/persistence.rb:125:in `save!'
  from /.../gems/activerecord-4.1.4/lib/active_record/validations.rb:57:in `save!'
  from /.../gems/activerecord-4.1.4/lib/active_record/attribute_methods/dirty.rb:29:in `save!'
  from /.../gems/activerecord-4.1.4/lib/active_record/transactions.rb:273:in `block in save!'
  from /.../gems/activerecord-4.1.4/lib/active_record/transactions.rb:329:in `block in with_transaction_returning_status'
  from /.../gems/activerecord-4.1.4/lib/active_record/connection_adapters/abstract/database_statements.rb:199:in `transaction'
  from /.../gems/activerecord-4.1.4/lib/active_record/transactions.rb:208:in `transaction'
  from /.../gems/activerecord-4.1.4/lib/active_record/transactions.rb:326:in `with_transaction_returning_status'
  from /.../gems/activerecord-4.1.4/lib/active_record/transactions.rb:273:in `save!'
  from /.../gems/activerecord-4.1.4/lib/active_record/associations/has_many_through_association.rb:103:in `save_through_record'
  from /.../gems/activerecord-4.1.4/lib/active_record/associations/has_many_through_association.rb:64:in `insert_record'
  from /.../gems/activerecord-4.1.4/lib/active_record/associations/collection_association.rb:522:in `block (2 levels) in concat_records'
  from /.../gems/activerecord-4.1.4/lib/active_record/associations/collection_association.rb:389:in `add_to_target'
  from /.../gems/activerecord-4.1.4/lib/active_record/associations/collection_association.rb:521:in `block in concat_records'
  from /.../gems/activerecord-4.1.4/lib/active_record/associations/collection_association.rb:519:in `each'
  from /.../gems/activerecord-4.1.4/lib/active_record/associations/collection_association.rb:519:in `concat_records'
  from /.../gems/activerecord-4.1.4/lib/active_record/associations/has_many_through_association.rb:42:in `concat_records'
  from /.../gems/activerecord-4.1.4/lib/active_record/associations/collection_association.rb:153:in `block in concat'
  from /.../gems/activerecord-4.1.4/lib/active_record/associations/collection_association.rb:168:in `block in transaction'
  from /.../gems/activerecord-4.1.4/lib/active_record/connection_adapters/abstract/database_statements.rb:201:in `block in transaction'
  from /.../gems/activerecord-4.1.4/lib/active_record/connection_adapters/abstract/database_statements.rb:209:in `within_new_transaction'
  from /.../gems/activerecord-4.1.4/lib/active_record/connection_adapters/abstract/database_statements.rb:201:in `transaction'
  from /.../gems/activerecord-4.1.4/lib/active_record/transactions.rb:208:in `transaction'
  from /.../gems/activerecord-4.1.4/lib/active_record/associations/collection_association.rb:167:in `transaction'
  from /.../gems/activerecord-4.1.4/lib/active_record/associations/collection_association.rb:153:in `concat'
  from /.../gems/activerecord-4.1.4/lib/active_record/associations/has_many_through_association.rb:36:in `concat'
  from /.../gems/activerecord-4.1.4/lib/active_record/associations/collection_proxy.rb:972:in `<<'
  from /.../gems/railties-4.1.4/lib/rails/commands/runner.rb:62:in `<top (required)>'
  from /.../gems/railties-4.1.4/lib/rails/commands/runner.rb:62:in `eval'
  from /.../gems/railties-4.1.4/lib/rails/commands/runner.rb:62:in `<top (required)>'
  from /.../gems/activesupport-4.1.4/lib/active_support/dependencies.rb:247:in `require'
  from /.../gems/activesupport-4.1.4/lib/active_support/dependencies.rb:247:in `block in require'
  from /.../gems/activesupport-4.1.4/lib/active_support/dependencies.rb:232:in `load_dependency'
  from /.../gems/activesupport-4.1.4/lib/active_support/dependencies.rb:247:in `require'
  from /.../gems/railties-4.1.4/lib/rails/commands/commands_tasks.rb:128:in `require_command!'
  from /.../gems/railties-4.1.4/lib/rails/commands/commands_tasks.rb:95:in `runner'
  from /.../gems/railties-4.1.4/lib/rails/commands/commands_tasks.rb:40:in `run_command!'
  from /.../gems/railties-4.1.4/lib/rails/commands.rb:17:in `<top (required)>'
  from /.../gems/activesupport-4.1.4/lib/active_support/dependencies.rb:247:in `require'
  from /.../gems/activesupport-4.1.4/lib/active_support/dependencies.rb:247:in `block in require'
  from /.../gems/activesupport-4.1.4/lib/active_support/dependencies.rb:232:in `load_dependency'
  from /.../gems/activesupport-4.1.4/lib/active_support/dependencies.rb:247:in `require'
  from /Users/philip/tmp/habmfu/bin/rails:8:in `<top (required)>'
  from /.../gems/activesupport-4.1.4/lib/active_support/dependencies.rb:241:in `load'
  from /.../gems/activesupport-4.1.4/lib/active_support/dependencies.rb:241:in `block in load'
  from /.../gems/activesupport-4.1.4/lib/active_support/dependencies.rb:232:in `load_dependency'
  from /.../gems/activesupport-4.1.4/lib/active_support/dependencies.rb:241:in `load'
  from /Users/philip/.rvm/rubies/ruby-2.0.0-p451/lib/ruby/site_ruby/2.0.0/rubygems/core_ext/kernel_require.rb:55:in `require'
  from /Users/philip/.rvm/rubies/ruby-2.0.0-p451/lib/ruby/site_ruby/2.0.0/rubygems/core_ext/kernel_require.rb:55:in `require'
  from -e:1:in `<main>'

Incompatibility with paper_trail

I'm trying to install paper_trail in my app but I can't create the migration table:
bundle exec rails generate paper_trail:install
Basically, whenever I invoke rails generate, I get the error below. I'm not so sure which gems is the culprit... I post it here first. If I comment gem 'attribute_normalizer' in my gemfile, the migration file is created normally. Tested with rails 3.1.1 and 3.0.10 on ruby 1.9.2

[rvm:ruby-1.9.2-p180@testrails31] Gamov-MBP:testrails31 gamov$ bundle exec rails generate paper_trail:install
/Users/gamov/.rvm/gems/ruby-1.9.2-p180@testrails31/gems/activerecord-3.1.1/lib/active_record/connection_adapters/abstract/connection_pool.rb:409:in retrieve_connection': ActiveRecord::ConnectionNotEstablished (ActiveRecord::ConnectionNotEstablished) from /Users/gamov/.rvm/gems/ruby-1.9.2-p180@testrails31/gems/activerecord-3.1.1/lib/active_record/connection_adapters/abstract/connection_specification.rb:107:inretrieve_connection'
from /Users/gamov/.rvm/gems/ruby-1.9.2-p180@testrails31/gems/activerecord-3.1.1/lib/active_record/connection_adapters/abstract/connection_specification.rb:89:in connection' from /Users/gamov/.rvm/gems/ruby-1.9.2-p180@testrails31/gems/activerecord-3.1.1/lib/active_record/base.rb:703:intable_exists?'
from /Users/gamov/.rvm/gems/ruby-1.9.2-p180@testrails31/gems/attribute_normalizer-1.0.0/lib/attribute_normalizer/model_inclusions.rb:65:in inherited' from /Users/gamov/.rvm/gems/ruby-1.9.2-p180@testrails31/gems/paper_trail-2.4.1/lib/paper_trail/version.rb:1:in<top (required)>'
from /Users/gamov/.rvm/gems/ruby-1.9.2-p180@testrails31/gems/activesupport-3.1.1/lib/active_support/dependencies.rb:240:in require' from /Users/gamov/.rvm/gems/ruby-1.9.2-p180@testrails31/gems/activesupport-3.1.1/lib/active_support/dependencies.rb:240:inblock in require'
from /Users/gamov/.rvm/gems/ruby-1.9.2-p180@testrails31/gems/activesupport-3.1.1/lib/active_support/dependencies.rb:223:in block in load_dependency' from /Users/gamov/.rvm/gems/ruby-1.9.2-p180@testrails31/gems/activesupport-3.1.1/lib/active_support/dependencies.rb:640:innew_constants_in'
from /Users/gamov/.rvm/gems/ruby-1.9.2-p180@testrails31/gems/activesupport-3.1.1/lib/active_support/dependencies.rb:223:in load_dependency' from /Users/gamov/.rvm/gems/ruby-1.9.2-p180@testrails31/gems/activesupport-3.1.1/lib/active_support/dependencies.rb:240:inrequire'
from /Users/gamov/.rvm/gems/ruby-1.9.2-p180@testrails31/gems/paper_trail-2.4.1/lib/paper_trail.rb:7:in <top (required)>' from /Users/gamov/.rvm/gems/ruby-1.9.2-p180@testrails31/gems/bundler-1.0.21/lib/bundler/runtime.rb:68:inrequire'
from /Users/gamov/.rvm/gems/ruby-1.9.2-p180@testrails31/gems/bundler-1.0.21/lib/bundler/runtime.rb:68:in block (2 levels) in require' from /Users/gamov/.rvm/gems/ruby-1.9.2-p180@testrails31/gems/bundler-1.0.21/lib/bundler/runtime.rb:66:ineach'
from /Users/gamov/.rvm/gems/ruby-1.9.2-p180@testrails31/gems/bundler-1.0.21/lib/bundler/runtime.rb:66:in block in require' from /Users/gamov/.rvm/gems/ruby-1.9.2-p180@testrails31/gems/bundler-1.0.21/lib/bundler/runtime.rb:55:ineach'
from /Users/gamov/.rvm/gems/ruby-1.9.2-p180@testrails31/gems/bundler-1.0.21/lib/bundler/runtime.rb:55:in require' from /Users/gamov/.rvm/gems/ruby-1.9.2-p180@testrails31/gems/bundler-1.0.21/lib/bundler.rb:122:inrequire'
from /Users/gamov/Temp/@NoTM/rails/testrails31/config/application.rb:7:in <top (required)>' from /Users/gamov/.rvm/gems/ruby-1.9.2-p180@testrails31/gems/railties-3.1.1/lib/rails/commands.rb:21:inrequire'
from /Users/gamov/.rvm/gems/ruby-1.9.2-p180@testrails31/gems/railties-3.1.1/lib/rails/commands.rb:21:in <top (required)>' from script/rails:6:inrequire'
from script/rails:6:in `

'

License missing from gemspec

RubyGems.org doesn't report a license for your gem. This is because it is not specified in the gemspec of your last release.

via e.g.

spec.license = 'MIT'
# or
spec.licenses = ['MIT', 'GPL-2']

Including a license in your gemspec is an easy way for rubygems.org and other tools to check how your gem is licensed. As you can imagine, scanning your repository for a LICENSE file or parsing the README, and then attempting to identify the license or licenses is much more difficult and more error prone. So, even for projects that already specify a license, including a license in your gemspec is a good practice. See, for example, how rubygems.org uses the gemspec to display the rails gem license.

There is even a License Finder gem to help companies/individuals ensure all gems they use meet their licensing needs. This tool depends on license information being available in the gemspec. This is an important enough issue that even Bundler now generates gems with a default 'MIT' license.

I hope you'll consider specifying a license in your gemspec. If not, please just close the issue with a nice message. In either case, I'll follow up. Thanks for your time!

Appendix:

If you need help choosing a license (sorry, I haven't checked your readme or looked for a license file), GitHub has created a license picker tool. Code without a license specified defaults to 'All rights reserved'-- denying others all rights to use of the code.
Here's a list of the license names I've found and their frequencies

p.s. In case you're wondering how I found you and why I made this issue, it's because I'm collecting stats on gems (I was originally looking for download data) and decided to collect license metadata,too, and make issues for gemspecs not specifying a license as a public service :). See the previous link or my blog post about this project for more information.

undefined method `normalize_attribute' in Rails 4.2.1

I'm running Rails 4.2.1 and Ruby 2.2.2 for a new app. I've added the following to my Gemfile

gem 'attribute_normalizer', '~> 1.2.0'

I ran bundle install to install the gem, then called normalize_attribute in my Resource model like so.

normalize_attribute :name, :address, :notes, :phone_number, :with => :squish

And for good measure I reloaded Rails/restarted Thin.

When I visit a page that calls the Resource model, I get the following:

undefined method `normalize_attribute' for #<Class:0x007fed6d6a2248>

Am I doing something wrong or is there a bug/compatibility issue with Rails 4.2.1 and Ruby 2.2.2? I wanted to post this here before I went to Stack for answers.

:postal_code normalizer?

@mdeering - we are going to be using your gem across quite a few of our apps...I'm planning on adding something simple that strips everything except letters and numbers for Canadian postal codes.

Any chance this would be something you pull in? If so, I'll create a PR. If not, I'll probably create an extension of this gem to avoid adding the same initializer to each one of our apps.

Thanks!

first_or_create fails in Rails 4.2

Given a model like

class Artist < ActiveRecord::Base
  normalize_attributes :name
end

And I'm in a fresh rails console
When I call first_or_create

artist  = Artist.where(name: 'John Doe').first_or_create!

Then I get an error

NoMethodError: super: no superclass method `name=' for #<Artist:0x007fcf95ec56f0>

This seems to because ActiveRecord has not defined the attribute methods. The odd thing is from reading the ActiveRecord source, it seems like define_attribute_methods should be invoked.

>> Artist.ancestors.select{|n| n.public_instance_methods.include?(:name=) }
=> [Artist(...)]

>> Artist.define_attribute_methods; Artist.ancestors.select{|n| n.public_instance_methods.include?(:name=) }
=> [Artist(...), #<#<Class:0x007fc3ec7868f8>:0x007fc3ec786970>]

My current workaround is

module AttributeNormalizer
  module ClassMethods
    alias_method :old_normalize_attributes, :normalize_attributes

    def normalize_attributes(*attributes, &block)
      define_attribute_methods
      old_normalize_attributes(*attributes, &block)
    end
  end
end

apply normalizer to all fields

Could create this option bellow like below
normalize_attribute :all

Could normalize all attributes with defaults of initializer: config.default_normalizers = { :strip => true, :blank => true }
I love this gem, but today i am using another because has this feature above

Thanks

Normalization should not be bi-directional

I wrote a patch a while back to add an option for :on => (:read || :write) so values don't get double-transformed when they are written and then read back out from the database:

http://github.com/avit/attribute_normalizer/commit/a7eed009

There were some comments on that commit about whether this is necessary, specifically why should {:on => :read} be supported. Currently attribute_normalizer already transforms on read by default, and I agree with the comment that this should be the job of a presenter (or a value class using composed_of).

What do you think about :write as the only option, or changing it so that's the only behaviour? (i.e. don't normalize on the reader method at all.)

Adding gem in a Rails 4 app breaks migrations in PostgreSQL

For some strange reason, after I added attribute_normalizer to my Gemfile in a Rails 4 app using a local PostgreSQL database, I could not run migrations from scratch again (ie: rake db:drop; rake db:create; rake db:migrate).

I tried this in a brand new app and the same thing happened:

rails new testapp
cd testapp/
nano Gemfile # add attribute_normalizer and pg gems
bundle
rails g scaffold child name age
nano config/database.yml # edit to use PostgreSQL
rake db:create
rake db:migrate

And the stack is:

rake db:migrate --trace
** Invoke db:migrate (first_time)
** Invoke environment (first_time)
** Execute environment
** Invoke db:load_config (first_time)
** Execute db:load_config
** Execute db:migrate
==  CreateChildren: migrating =================================================
-- create_table(:children)
   -> 0.0191s
==  CreateChildren: migrated (0.0192s) ========================================

rake aborted!
An error has occurred, this and all later migrations canceled:

PG::Error: ERROR:  column "id" does not exist
LINE 1: ...O "schema_migrations" ("version") VALUES ($1) RETURNING "id"
                                                                   ^
: INSERT INTO "schema_migrations" ("version") VALUES ($1) RETURNING "id"/home/user/.rvm/gems/ruby-2.0.0-p195/gems/activerecord-4.0.0/lib/active_record/connection_adapters/postgresql_adapter.rb:811:in `prepare'
/home/user/.rvm/gems/ruby-2.0.0-p195/gems/activerecord-4.0.0/lib/active_record/connection_adapters/postgresql_adapter.rb:811:in `prepare_statement'
/home/user/.rvm/gems/ruby-2.0.0-p195/gems/activerecord-4.0.0/lib/active_record/connection_adapters/postgresql_adapter.rb:772:in `exec_cache'
/home/user/.rvm/gems/ruby-2.0.0-p195/gems/activerecord-4.0.0/lib/active_record/connection_adapters/postgresql/database_statements.rb:139:in `block in exec_query'
/home/user/.rvm/gems/ruby-2.0.0-p195/gems/activerecord-4.0.0/lib/active_record/connection_adapters/abstract_adapter.rb:425:in `block in log'
/home/user/.rvm/gems/ruby-2.0.0-p195/gems/activesupport-4.0.0/lib/active_support/notifications/instrumenter.rb:20:in `instrument'
/home/user/.rvm/gems/ruby-2.0.0-p195/gems/activerecord-4.0.0/lib/active_record/connection_adapters/abstract_adapter.rb:420:in `log'
/home/user/.rvm/gems/ruby-2.0.0-p195/gems/activerecord-4.0.0/lib/active_record/connection_adapters/postgresql/database_statements.rb:137:in `exec_query'
/home/user/.rvm/gems/ruby-2.0.0-p195/gems/activerecord-4.0.0/lib/active_record/connection_adapters/postgresql/database_statements.rb:183:in `exec_insert'
/home/user/.rvm/gems/ruby-2.0.0-p195/gems/activerecord-4.0.0/lib/active_record/connection_adapters/abstract/database_statements.rb:96:in `insert'
/home/user/.rvm/gems/ruby-2.0.0-p195/gems/activerecord-4.0.0/lib/active_record/connection_adapters/abstract/query_cache.rb:14:in `insert'
/home/user/.rvm/gems/ruby-2.0.0-p195/gems/activerecord-4.0.0/lib/active_record/relation.rb:76:in `insert'
/home/user/.rvm/gems/ruby-2.0.0-p195/gems/activerecord-4.0.0/lib/active_record/persistence.rb:498:in `create_record'
/home/user/.rvm/gems/ruby-2.0.0-p195/gems/activerecord-4.0.0/lib/active_record/attribute_methods/dirty.rb:78:in `create_record'
/home/user/.rvm/gems/ruby-2.0.0-p195/gems/activerecord-4.0.0/lib/active_record/callbacks.rb:303:in `block in create_record'
/home/user/.rvm/gems/ruby-2.0.0-p195/gems/activesupport-4.0.0/lib/active_support/callbacks.rb:373:in `_run__2296398413646725002__create__callbacks'
/home/user/.rvm/gems/ruby-2.0.0-p195/gems/activesupport-4.0.0/lib/active_support/callbacks.rb:80:in `run_callbacks'
/home/user/.rvm/gems/ruby-2.0.0-p195/gems/activerecord-4.0.0/lib/active_record/callbacks.rb:303:in `create_record'
/home/user/.rvm/gems/ruby-2.0.0-p195/gems/activerecord-4.0.0/lib/active_record/timestamp.rb:57:in `create_record'
/home/user/.rvm/gems/ruby-2.0.0-p195/gems/activerecord-4.0.0/lib/active_record/persistence.rb:466:in `create_or_update'
/home/user/.rvm/gems/ruby-2.0.0-p195/gems/activerecord-4.0.0/lib/active_record/callbacks.rb:299:in `block in create_or_update'
/home/user/.rvm/gems/ruby-2.0.0-p195/gems/activesupport-4.0.0/lib/active_support/callbacks.rb:373:in `_run__2296398413646725002__save__callbacks'
/home/user/.rvm/gems/ruby-2.0.0-p195/gems/activesupport-4.0.0/lib/active_support/callbacks.rb:80:in `run_callbacks'
/home/user/.rvm/gems/ruby-2.0.0-p195/gems/activerecord-4.0.0/lib/active_record/callbacks.rb:299:in `create_or_update'
/home/user/.rvm/gems/ruby-2.0.0-p195/gems/activerecord-4.0.0/lib/active_record/persistence.rb:128:in `save!'
/home/user/.rvm/gems/ruby-2.0.0-p195/gems/activerecord-4.0.0/lib/active_record/validations.rb:57:in `save!'
/home/user/.rvm/gems/ruby-2.0.0-p195/gems/activerecord-4.0.0/lib/active_record/attribute_methods/dirty.rb:41:in `save!'
/home/user/.rvm/gems/ruby-2.0.0-p195/gems/activerecord-4.0.0/lib/active_record/transactions.rb:275:in `block in save!'
/home/user/.rvm/gems/ruby-2.0.0-p195/gems/activerecord-4.0.0/lib/active_record/transactions.rb:326:in `block in with_transaction_returning_status'
/home/user/.rvm/gems/ruby-2.0.0-p195/gems/activerecord-4.0.0/lib/active_record/connection_adapters/abstract/database_statements.rb:200:in `transaction'
/home/user/.rvm/gems/ruby-2.0.0-p195/gems/activerecord-4.0.0/lib/active_record/transactions.rb:209:in `transaction'
/home/user/.rvm/gems/ruby-2.0.0-p195/gems/activerecord-4.0.0/lib/active_record/transactions.rb:323:in `with_transaction_returning_status'
/home/user/.rvm/gems/ruby-2.0.0-p195/gems/activerecord-4.0.0/lib/active_record/transactions.rb:275:in `save!'
/home/user/.rvm/gems/ruby-2.0.0-p195/gems/activerecord-4.0.0/lib/active_record/validations.rb:41:in `create!'
/home/user/.rvm/gems/ruby-2.0.0-p195/gems/activerecord-4.0.0/lib/active_record/migration.rb:990:in `record_version_state_after_migrating'
/home/user/.rvm/gems/ruby-2.0.0-p195/gems/activerecord-4.0.0/lib/active_record/migration.rb:960:in `block in execute_migration_in_transaction'
/home/user/.rvm/gems/ruby-2.0.0-p195/gems/activerecord-4.0.0/lib/active_record/migration.rb:1005:in `block in ddl_transaction'
/home/user/.rvm/gems/ruby-2.0.0-p195/gems/activerecord-4.0.0/lib/active_record/connection_adapters/abstract/database_statements.rb:202:in `block in transaction'
/home/user/.rvm/gems/ruby-2.0.0-p195/gems/activerecord-4.0.0/lib/active_record/connection_adapters/abstract/database_statements.rb:210:in `within_new_transaction'
/home/user/.rvm/gems/ruby-2.0.0-p195/gems/activerecord-4.0.0/lib/active_record/connection_adapters/abstract/database_statements.rb:202:in `transaction'
/home/user/.rvm/gems/ruby-2.0.0-p195/gems/activerecord-4.0.0/lib/active_record/transactions.rb:209:in `transaction'
/home/user/.rvm/gems/ruby-2.0.0-p195/gems/activerecord-4.0.0/lib/active_record/migration.rb:1005:in `ddl_transaction'
/home/user/.rvm/gems/ruby-2.0.0-p195/gems/activerecord-4.0.0/lib/active_record/migration.rb:958:in `execute_migration_in_transaction'
/home/user/.rvm/gems/ruby-2.0.0-p195/gems/activerecord-4.0.0/lib/active_record/migration.rb:920:in `block in migrate'
/home/user/.rvm/gems/ruby-2.0.0-p195/gems/activerecord-4.0.0/lib/active_record/migration.rb:916:in `each'
/home/user/.rvm/gems/ruby-2.0.0-p195/gems/activerecord-4.0.0/lib/active_record/migration.rb:916:in `migrate'
/home/user/.rvm/gems/ruby-2.0.0-p195/gems/activerecord-4.0.0/lib/active_record/migration.rb:764:in `up'
/home/user/.rvm/gems/ruby-2.0.0-p195/gems/activerecord-4.0.0/lib/active_record/migration.rb:742:in `migrate'
/home/user/.rvm/gems/ruby-2.0.0-p195/gems/activerecord-4.0.0/lib/active_record/railties/databases.rake:42:in `block (2 levels) in <top (required)>'
/home/user/.rvm/gems/ruby-2.0.0-p195/gems/rake-10.1.0/lib/rake/task.rb:236:in `call'
/home/user/.rvm/gems/ruby-2.0.0-p195/gems/rake-10.1.0/lib/rake/task.rb:236:in `block in execute'
/home/user/.rvm/gems/ruby-2.0.0-p195/gems/rake-10.1.0/lib/rake/task.rb:231:in `each'
/home/user/.rvm/gems/ruby-2.0.0-p195/gems/rake-10.1.0/lib/rake/task.rb:231:in `execute'
/home/user/.rvm/gems/ruby-2.0.0-p195/gems/rake-10.1.0/lib/rake/task.rb:175:in `block in invoke_with_call_chain'
/home/user/.rvm/rubies/ruby-2.0.0-p195/lib/ruby/2.0.0/monitor.rb:211:in `mon_synchronize'
/home/user/.rvm/gems/ruby-2.0.0-p195/gems/rake-10.1.0/lib/rake/task.rb:168:in `invoke_with_call_chain'
/home/user/.rvm/gems/ruby-2.0.0-p195/gems/rake-10.1.0/lib/rake/task.rb:161:in `invoke'
/home/user/.rvm/gems/ruby-2.0.0-p195/gems/rake-10.1.0/lib/rake/application.rb:149:in `invoke_task'
/home/user/.rvm/gems/ruby-2.0.0-p195/gems/rake-10.1.0/lib/rake/application.rb:106:in `block (2 levels) in top_level'
/home/user/.rvm/gems/ruby-2.0.0-p195/gems/rake-10.1.0/lib/rake/application.rb:106:in `each'
/home/user/.rvm/gems/ruby-2.0.0-p195/gems/rake-10.1.0/lib/rake/application.rb:106:in `block in top_level'
/home/user/.rvm/gems/ruby-2.0.0-p195/gems/rake-10.1.0/lib/rake/application.rb:115:in `run_with_threads'
/home/user/.rvm/gems/ruby-2.0.0-p195/gems/rake-10.1.0/lib/rake/application.rb:100:in `top_level'
/home/user/.rvm/gems/ruby-2.0.0-p195/gems/rake-10.1.0/lib/rake/application.rb:78:in `block in run'
/home/user/.rvm/gems/ruby-2.0.0-p195/gems/rake-10.1.0/lib/rake/application.rb:165:in `standard_exception_handling'
/home/user/.rvm/gems/ruby-2.0.0-p195/gems/rake-10.1.0/lib/rake/application.rb:75:in `run'
/home/user/.rvm/gems/ruby-2.0.0-p195/gems/rake-10.1.0/bin/rake:33:in `<top (required)>'
/home/user/.rvm/gems/ruby-2.0.0-p195/bin/rake:23:in `load'
/home/user/.rvm/gems/ruby-2.0.0-p195/bin/rake:23:in `<main>'
/home/user/.rvm/gems/ruby-2.0.0-p195/bin/ruby_noexec_wrapper:14:in `eval'
/home/user/.rvm/gems/ruby-2.0.0-p195/bin/ruby_noexec_wrapper:14:in `<main>'
Tasks: TOP => db:migrate

If I remove attribute_normalizer from the Gemfile (and run bundle), migrations run correctly.

Using `normalize_attribute` on a virtual attribute on rails 4.0.4.rc1

Rails 4.0.4.rc1, 4.0.3 was fine

Code:

  attr_accessor :shortlisted_only
  normalize_attribute :shortlisted_only do |value|
    ActiveRecord::ConnectionAdapters::Column.value_to_boolean(value)
  end

Spec error:

1) ListingSearch attributes #shortlisted_only should normalize shortlisted_only from "1" to "true"
     Failure/Error: Unable to find matching line from backtrace
     SystemStackError:
       stack level too deep
     # /Users/PikachuEXE/.rvm/gems/ruby-2.0.0-p451/gems/activemodel-4.0.4.rc1/lib/active_model/attribute_methods.rb:330

  2) ListingSearch attributes #shortlisted_only should normalize shortlisted_only from "0" to "false"
     Failure/Error: Unable to find matching line from backtrace
     SystemStackError:
       stack level too deep
     # /Users/PikachuEXE/.rvm/gems/ruby-2.0.0-p451/gems/activemodel-4.0.4.rc1/lib/active_model/attribute_methods.rb:330

  3) ListingSearch attributes #listings when shortlisted_only is set true 
     Failure/Error: Unable to find matching line from backtrace
     SystemStackError:
       stack level too deep
     # /Users/PikachuEXE/.rvm/gems/ruby-2.0.0-p451/gems/activerecord-4.0.4.rc1/lib/active_record/attribute_methods.rb:50

  4) ListingSearch attributes #listings when shortlisted_only is set true 
     Failure/Error: Unable to find matching line from backtrace
     SystemStackError:
       stack level too deep
     # /Users/PikachuEXE/.rvm/gems/ruby-2.0.0-p451/gems/activerecord-4.0.4.rc1/lib/active_record/attribute_methods.rb:50

Using the normal way to declare accessor at the moment

  def shortlisted_only
    ActiveRecord::ConnectionAdapters::Column.value_to_boolean(@shortlisted_only)
  end
  def shortlisted_only=(value)
    @shortlisted_only = (ActiveRecord::ConnectionAdapters::Column.value_to_boolean(value))
  end

Camel case attributes cause error

I know this is a very unlikely issue for most but I thought I would submit it. I have a couple of legacy projects with camel cased column names. The fix is very simple.

Because you create the write method with the argument name same as the attribute, a camel cased attribute will appear as a reference to a constant which doesn't exist. Instead just use 'value' as the argument, like so:

def #{attribute}=(value)
  super(self.class.send(:normalize_#{attribute}, value))
end

Thanks for the plugin.

Adam

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.