{"id":14955857,"url":"https://github.com/michaelnera/active_record_importer","last_synced_at":"2025-10-06T08:32:11.545Z","repository":{"id":59150371,"uuid":"82173715","full_name":"michaelnera/active_record_importer","owner":"michaelnera","description":"An easy to setup and flexible importer for Ruby on Rails","archived":false,"fork":false,"pushed_at":"2017-08-18T09:53:56.000Z","size":55,"stargazers_count":8,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-01-14T11:48:01.149Z","etag":null,"topics":["active-record-import","active-record-importer","activerecord","activerecord-import","activerecord-importer","csv","csv-import","csv-importer","import","importer","rails","rails-import","rails-importer","ror","ruby","ruby-on-rails","ruby-on-rails-import","ruby-on-rails-importer","rubygems","rubyonrails"],"latest_commit_sha":null,"homepage":"","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/michaelnera.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-02-16T11:30:07.000Z","updated_at":"2023-01-11T02:29:18.000Z","dependencies_parsed_at":"2022-09-13T10:50:12.290Z","dependency_job_id":null,"html_url":"https://github.com/michaelnera/active_record_importer","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/michaelnera%2Factive_record_importer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/michaelnera%2Factive_record_importer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/michaelnera%2Factive_record_importer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/michaelnera%2Factive_record_importer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/michaelnera","download_url":"https://codeload.github.com/michaelnera/active_record_importer/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":235515432,"owners_count":19002481,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["active-record-import","active-record-importer","activerecord","activerecord-import","activerecord-importer","csv","csv-import","csv-importer","import","importer","rails","rails-import","rails-importer","ror","ruby","ruby-on-rails","ruby-on-rails-import","ruby-on-rails-importer","rubygems","rubyonrails"],"created_at":"2024-09-24T13:11:54.676Z","updated_at":"2025-10-06T08:32:06.245Z","avatar_url":"https://github.com/michaelnera.png","language":"Ruby","readme":"# ActiveRecordImporter\n\nSupports only Rails 4 and 5\n\nThis gem helps you insert/update records easily. For now, it only accepts CSV file.\nThis also helps you monitor how many rows are imported, and how many rows failed.\nThis gem also allows you to easily import to any model with few configurations.\n\nI'll release an update to enable this on background job.\n\n## Installation\n\nAdd this line to your application's Gemfile:\n\n```ruby\ngem 'active_record_importer'\n```\n\nAnd then execute:\n\n    $ bundle\n\nOr install it yourself as:\n\n    $ gem install active_record_importer\n\n## Usage\n### For version 0.4.0\n\nFor the newest version (0.4.0), you don't have to create Import table/model and controller.\nI already fixed the errors when there's no Import table/model on version 0.3.0.\nYou just need to add the `acts_as_importable` in your model you want to be importable, and you may now run:\n\n```ruby\nUser.import!(file: File.open(PATH_TO_FILE))\n```\n\n`insert` will be the default insert method for this\nIf you want to use `upsert` or `error_duplicate`, define it in your importer options:\n\n```ruby\nclass User \u003c ActiveRecord::Base\n  acts_as_importable insert_method: 'upsert',\n                     find_options: [:email]\nend\n```\n\nOr you may use in your console:\n\n```ruby\nUser.acts_as_importable insert_method: 'error_duplicate', find_options: ['email']\n```\n\n### If you don't want to record the status of your import, you don't have to do the remaining steps\n\n### Create Import table/model\nI'll add a generator on my next release\n#### DB Migration:\n```ruby\nclass ActiveRecordImporterMigration \u003c ActiveRecord::Migration\n  def change\n    create_table :imports do |t|\n      t.attachment  :file\n      t.attachment  :failed_file\n      t.text        :properties\n      t.string      :resource,           null: false\n      t.integer     :imported_rows,      default: 0\n      t.integer     :failed_rows,        default: 0\n      t.timestamps\n    end\n  end\nend\n```\n\n#### Add Import Model:\n```ruby\nclass Import \u003c ActiveRecord::Base\n  extend Enumerize\n  store :properties, accessors: %i(insert_method find_options batch_size)\n\n  enumerize :insert_method,\n            in: %w(insert upsert error_duplicate),\n            default: :upsert\n\n  has_attached_file :file\n  has_attached_file :failed_file\n\n  attr_accessor :execute_on_create\n\n  validates :resource, presence: true\n  validate :check_presence_of_find_options\n  validates_attachment :file,\n                       content_type: {\n                           content_type: %w(text/plain text/csv)\n                       }\n\n  validates_attachment :failed_file,\n                       content_type: {\n                           content_type: %w(text/plain text/csv)\n                       }\n\n  # I'll add import options in the next major release\n  # accepts_nested_attributes_for :import_options, allow_destroy: true\n  ### THIS IS VERSION 0.2.1 and below\n  def execute\n    resource_class.import!(self, execute_on_create)\n  end\n\n  ### THIS IS VERSION 0.2.1 and below\n  def execute\n    resource_class.import!(object: self, execute: execute_on_create)\n  end\n\n\n  ### THIS IS VERSION 0.2.1 and below\n  def execute!\n    resource_class.import!(self, true)\n  end\n\n  ### THIS IS VERSION 0.3.0\n  def execute!\n    resource_class.import!(object: self, execute: true)\n  end\n\n  def resource_class\n    resource.safe_constantize\n  end\n\n  def batch_size\n    super.to_i\n  end\n\n  ##\n  # Override this if you prefer have\n  # private permissions or you have\n  # private methods for reading files\n  ##\n  def import_file\n    local_path?(file) ? file.path : file.url\n  end\n\n  ##\n  # Override this method if you have\n  # private permissions or you have private methods\n  # for reading/writing uploaded files\n  ##\n  def failed_file_path\n    local_path?(failed_file) ? failed_file.path : failed_file.url\n  end\n\n  private\n\n  def check_presence_of_find_options\n    return if insert_method.insert?\n    errors.add(:find_options, \"can't be blank\") if find_options.blank?\n  end\n\n  def local_path?(f)\n    File.exist? f.path\n  end\nend\n```\n\n### Add `acts_as_importable` to any ActiveRecord model to make it importable\n\n```ruby\nclass User \u003c ActiveRecord::Base\n  acts_as_importable\nend\n```\n\nYou may also add import options:\n```ruby\nclass User \u003c ActiveRecord::Base\n  acts_as_importable default_attributes: { first_name: 'Juan',\n                                           last_name: 'dela Cruz' },\n                     find_options: %i(email),\n                     before_save: Proc.new { |user| user.password = 'temporarypassword123' }\n                     after_save: Proc.new { |user| puts \"THIS IS CALLED AFTER OBJECT IS SAVED\" }\nend\n```\n\nIf you're using ActiveRecord::Store, you may import values to your accessors by including them in the configuration:\n```ruby\nclass User \u003c ActiveRecord::Base\n  store :properties, accessors: [:first_key, :second_key]\n\n  acts_as_importable store_accessors: [:first_key, :second_key]\nend\n```\n\n### Add import form\nThis is a sample import HAML form:\n```ruby\n    # resource is your Model name\n    = f.input :resource\n    # batch_size is useful for large csv file\n    = f.input :batch_size\n    # insert_methods: [:upsert, :insert, :error_on_duplicate]\n    = f.input :insert_method, collection: insert_methods, class: 'form-control insert-method'\n    # `find_options` are the list of columns you want to use to update a certain instance or\n    # error when a duplicate is found. This is not required when your insert_method is `:insert`\n    = f.input :find_options\n    = f.input :file, as: :file,\n      input_html: { accept: '.csv' }\n```\n\nYou may also add some options from the SmarterCSV gem:\n\n    | Option                         |  Default\n    --------------------------------------------------------------\n    | :convert_values_to_metric      |  nil\n    | :value_converters              |  nil\n    | :remove_empty_values           |  false\n    | :comment_regexp                |  Regexp.new(/^#=\u003e/)\n    | :force_utf8                    |  true\n    | :chunk_size                    |  500\n    | :col_sep                       |  \",\"\n\nhttps://github.com/tilo/smarter_csv\n\n\n```ruby\nclass User \u003c ActiveRecord::Base\n  acts_as_importable csv_opts: {\n                       chunk_size: 2000,\n                       col_sep: '|',\n                       convert_values_to_numeric: { only: [:age, :salary] }\n                     }\nend\n```\n\n`I'll add more options SOON!`\n\n\n### Create Imports Controller:\n```ruby\nclass ImportsController \u003c ApplicationController\n\n  def create\n    @import = Import.create!(import_params)\n    @import.execute!\n  end\n\n  private\n\n  def import_params\n    params.require(:import).permit(:file, :resource, :insert_method, :batch_size)\n  end\nend\n```\n\n#### Run it via Rails Console:\n```ruby\nFile.open(PATH_TO_CSV_FILE) do |file|\n  @import = Import.create!(\n             resource: 'User',\n             file: file,\n             insert_method: 'upsert',\n             find_options: 'first_name,last_name'\n           )\nend\n@import.execute!\n```\n\n###REMINDER:\nHeaders of your csv file should be formatted/transformed to column names of your IMPORTABLE model\n\n\n## Development\n\nAfter checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.\n\nTo install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).\n\n## Contributing\n\nBug reports and pull requests are welcome on GitHub at https://github.com/michaelnera/active_record_importer. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](contributor-covenant.org) code of conduct.\n\n\n## License\n\nThe gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmichaelnera%2Factive_record_importer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmichaelnera%2Factive_record_importer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmichaelnera%2Factive_record_importer/lists"}