WARNING: THIS SITE IS A MIRROR OF GITHUB.COM / IT CANNOT LOGIN OR REGISTER ACCOUNTS / THE CONTENTS ARE PROVIDED AS-IS / THIS SITE ASSUMES NO RESPONSIBILITY FOR ANY DISPLAYED CONTENT OR LINKS / IF YOU FOUND SOMETHING MAY NOT GOOD FOR EVERYONE, CONTACT ADMIN AT ilovescratch@foxmail.com
Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 3 additions & 7 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,9 @@ script: "bundle exec rake ci"
env:
- CODECLIMATE_REPO_TOKEN=a49f28520e49a35d73c9b6ed3d78ae110e4a5d05b9f154b999578a5175add09d
rvm:
- 2.0
- 2.1
- 2.2
- 2.3.0
- rbx-2
- jruby-9000
- ruby-head
- 2.3.5
- 2.4.2
- jruby-9.1.13.0
matrix:
allow_failures:
- rvm: ruby-head
Expand Down
3 changes: 2 additions & 1 deletion Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ source 'https://rubygems.org'
gemspec

group :test do
gem 'rom', git: 'https://github.com/rom-rb/rom.git', branch: 'master'
gem 'pry-byebug', platforms: :mri
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we need it? I think it will be good to have almost the same gems set in all adapters

gem 'rom-repository', '~> 2.0'
gem 'virtus'
gem 'rspec', '~> 3.1'
gem 'codeclimate-test-reporter', require: false
Expand Down
3 changes: 1 addition & 2 deletions examples/find_user.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
csv_file = ARGV[0] || File.expand_path("./users.csv", File.dirname(__FILE__))

configuration = ROM::Configuration.new(:csv, csv_file)
configuration.use(:macros)

configuration.relation(:users) do
def by_name(name)
Expand All @@ -27,7 +26,7 @@ class User < OpenStruct

container = ROM.container(configuration)

user = container.relation(:users).as(:entity).by_name('Jane').one
user = container.relations[:users].as(:entity).by_name('Jane').one
# => #<User id=2, name="Jane", email="[email protected]">

user or abort "user not found"
3 changes: 1 addition & 2 deletions lib/rom/csv.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
require 'csv'
require 'rom-core'

require 'rom'
require 'rom/csv/version'
require 'rom/csv/gateway'
require 'rom/csv/relation'
Expand Down
35 changes: 1 addition & 34 deletions lib/rom/csv/dataset.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,43 +2,10 @@

module ROM
module CSV
# Dataset for CSV
# CSV in-memory dataset used by CSV gateways
#
# @api public
class Dataset < ROM::Memory::Dataset
option :path, reader: true
option :file_options, reader: true

# Convert each CSV::Row to a hash
#
# @api public
def self.row_proc
-> row { row.to_hash }
end

def reload!
@data = load_data
end

def sync!
write_data && reload!
end

def write_data
::CSV.open(path, 'wb', file_options) do |csv|
data.to_a.each do |tuple|
csv << tuple
end
end
end

def load_data
::CSV.table(path, file_options).by_row!
end

def count
data.count
end
end
end
end
121 changes: 69 additions & 52 deletions lib/rom/csv/gateway.rb
Original file line number Diff line number Diff line change
@@ -1,64 +1,90 @@
require 'csv'

require 'rom/gateway'
require 'rom/csv/dataset'
require 'rom/csv/commands'

# Ruby Object Mapper
#
# @see http://rom-rb.org/
module ROM
# CSV support for ROM
#
# @example
# require 'rom/csv'
# require 'ostruct'
#
# setup = ROM.setup(:csv, "./spec/fixtures/users.csv")
# setup.relation(:users) do
# def by_name(name)
# dataset.find_all { |row| row[:name] == name }
# end
# end
#
# class User < OpenStruct
# end
#
# setup.mappers do
# define(:users) do
# model User
# end
# end
#
# rom = setup.finalize
# p rom.read(:users).by_name('Jane').one
# # => #<User id=2, name="Jane", email="[email protected]">
#
# **Note: rom-csv is read only at the moment.**
#
# @api public
module CSV
# CSV gateway interface
# CSV gateway
#
# Connects to a CSV file and uses it as a data-source
#
# @example
# rom = ROM.container(:csv, '/path/to/products.scv')
# gateway = rom.gateways[:default]
# gateway[:products] # => data from the csv file
#
# @api public
class Gateway < ROM::Gateway
# Expect a path to a single csv file which will be registered by rom to
# the given name or :default as the gateway.
adapter :csv

# @attr_reader [Hash] sources Data loaded from files
#
# @api private
attr_reader :sources

# @attr_reader [Hash] datasets CSV datasets
#
# @api private
attr_reader :datasets

# Create a new CSV gateway from a path to file(s)
#
# @example
# gateway = ROM::CSV::Gateway.new('/path/to/files')
#
# Uses CSV.table which passes the following csv options:
# * headers: true
# * converters: numeric
# * header_converters: :symbol
#
# @param path [String] path to csv
# @see CSV.table
#
# @param [String, Pathname] path The path to your CSV file(s)
# @param options [Hash] options passed to CSV.table
#
# @return [Gateway]
#
# @api public
def self.new(path, options = {})
super(load_from(path, options))
end

# Load data from CSV file(s)
#
# @api private
def self.load_from(path, options = {})
if File.directory?(path)
load_files(path, options)
else
{ source_name(path) => load_file(path, options) }
end
end

# Load CSV files from a given directory and return a name => data map
#
# @see CSV.table
def initialize(path, options = {})
# @api private
def self.load_files(path, options = {})
Dir["#{path}/*.csv"].each_with_object({}) do |file, h|
h[source_name(file)] = load_file(file, options)
end
end

def self.source_name(filename)
File.basename(filename, '.*')
end

# Load CSV file
#
# @api private
def self.load_file(path, options = {})
::CSV.table(path, options).map(&:to_h)
end

# @api private
def initialize(sources)
@sources = sources
@datasets = {}
@path = path
@options = options
@connection = ::CSV.table(path, options).by_row!
end

# Return dataset with the given name
Expand All @@ -80,7 +106,7 @@ def [](name)
#
# @api public
def dataset(name)
datasets[name] = Dataset.new(connection, dataset_options)
datasets[name] = Dataset.new(sources.fetch(name.to_s))
end

# Check if dataset exists
Expand All @@ -91,15 +117,6 @@ def dataset(name)
def dataset?(name)
datasets.key?(name)
end

private

def dataset_options
{ path: path, file_options: options }
end

# @api private
attr_reader :datasets, :path, :options
end
end
end
10 changes: 2 additions & 8 deletions lib/rom/csv/relation.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
require 'rom/relation'
require 'rom/memory'

module ROM
module CSV
Expand All @@ -9,14 +9,8 @@ module CSV
# end
#
# @api public
class Relation < ROM::Relation
class Relation < ROM::Memory::Relation
adapter :csv

forward :join, :project, :restrict, :order

def count
dataset.count
end
end
end
end
2 changes: 1 addition & 1 deletion rom-csv.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ Gem::Specification.new do |spec|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
spec.require_paths = ['lib']

spec.add_runtime_dependency 'rom', '~> 1.0'
spec.add_runtime_dependency 'rom-core', '~> 4.0'

spec.add_development_dependency 'bundler'
spec.add_development_dependency 'rake'
Expand Down
3 changes: 3 additions & 0 deletions spec/fixtures/db/products.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
id,title
1,T-Shirt
2,Mug
7 changes: 7 additions & 0 deletions spec/fixtures/db/variants.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
id,product_id,sku,quantity
1,1,TSHIRT1010PINK,3
2,1,TSHIRT1020BLUE,5
3,1,TSHIRT1030GREY,2
4,2,MUG2010WHITE,15
5,2,MUG2010GREEN,10
6,3,MUG2030BROWN,12
3 changes: 3 additions & 0 deletions spec/fixtures/semicolon.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
user_id;name;email
1;Jane;[email protected]
2;John;[email protected]
58 changes: 58 additions & 0 deletions spec/integration/adapter_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
require 'spec_helper'

require 'rom-repository'

RSpec.describe ROM::CSV do
let(:configuration) do
ROM::Configuration.new(:csv, uri)
end

let(:uri) { File.expand_path('./spec/fixtures/users.csv') }
let(:rom) { ROM.container(configuration) }

context 'single file configuration' do
let(:users_relation) do
Class.new(ROM::CSV::Relation) do
schema(:users) do
attribute :user_id, ROM::Types::Int
attribute :name, ROM::Types::String
attribute :email, ROM::Types::String
end

def by_name(name)
restrict(name: name)
end
end
end

before do
configuration.register_relation(users_relation)
end

describe ROM::CSV::Relation do
describe '#by_name' do
subject(:jane) { rom.relations[:users].by_name('Jane').one }

it 'returns object by name' do
expect(jane[:name]).to eql 'Jane'
expect(jane[:email]).to eql '[email protected]'
expect(jane[:user_id]).to eql 3
end
end
end

describe 'with a repository' do
let(:repo) do
Class.new(ROM::Repository[:users]).new(rom)
end

it 'auto-maps to structs' do
user = repo.users.by_name('Jane').one

expect(user.name).to eql 'Jane'
expect(user.email).to eql '[email protected]'
expect(user.user_id).to eql 3
end
end
end
end
Loading