Coder Social home page Coder Social logo

rom-factory's People

Contributors

actions-user avatar alassek avatar alexandru-calinoiu avatar amhol avatar deepj avatar flash-gordon avatar graceful-potato avatar grzegorz-wcislo avatar gustavocaso avatar ianks avatar janavpetrova avatar janjiss avatar k0va1 avatar katafrakt avatar leoarnold avatar lsimoneau avatar mensfeld avatar olleolleolle avatar parndt avatar psparrow avatar rawburt avatar rom-bot avatar smaximov avatar solnic avatar swilgosz avatar timriley avatar v-kolesnikov avatar wilsonsilva avatar wuarmin 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

Watchers

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

rom-factory's Issues

Inconsistent behaviour with default schema values in factories

Describe the bug

I am using rom-rb with rom-sql and rom-factory.
In short, a struct creation via factory (Factory.structs[:foo]) is not using default type value unless schema also has unrelated jsonb type field.
Took me forever to isolate the source of issue to that jsonb type column ๐Ÿ˜…

To Reproduce

Example repo:
https://github.com/trafium/rom_factory_bug

To run:

bundle exec rake db:create
bundle exec rake db:migrate
ruby test.rb

The output is:

#<Entities::Foo column_with_default=nil id=1 random_column=nil>
#<Entities::Bar column_with_default="default" id=1 random_column=nil>

Expected behavior

#<Entities::Foo column_with_default="default" id=1 random_column=nil>
#<Entities::Bar column_with_default="default" id=1 random_column=nil>

I am not sure what is the expected behaviour for rom-factory, but I would expect it should always use default values for factory structs creation.

My environment

  • Affects my production application: Not yet
  • Ruby version: 2.6.6
  • OS: MacOS 11.2.3

It is not possible to overwrite an association with nil.

Describe the bug

It is not possible to overwrite an association with nil.

class Units < ROM::Relation[:sql]
  schema(:units, infer: true) do
    associations do
      has_many :users
    end
  end
end

class Users < ROM::Relation[:sql]
  schema(:users, infer: true) do
    associations do
      belongs_to :unit
    end
  end
end
Factory.define(:user) do |f|
  f.id { fake(:number, :number, digits: 3) }
  f.name { fake(:name, :name) }
  f.association(:unit)
end

Following overwrite of the association unit fails:

Factory[:user, id: 1, unit: nil] 
NoMethodError:
       undefined method `fetch' for nil:NilClass
     
               child.merge(fk => parent.fetch(pk))
# /usr/local/bundle/gems/rom-core-5.2.5/lib/rom/associations/many_to_one.rb:45:in `associate'
# /usr/local/bundle/bundler/gems/rom-factory-94c8d02faf68/lib/rom/factory/attributes/association.rb:57:in `call'

Expected behavior

the expected behavior should be a resulting user-db-entry holding a unit_id of NULL and the returned ruby-object should be look like this:

{ id: 1, name: "Michael Knight", unit: nil }

Workaround

Factory[:user, id: 1, unit: { id: nil }] 

WDYT? How should we fix this?
Thanks and best regards

Has many association does not allow overrides

This test will fail. Overriding has_many association does not work.

    context 'has_many' do
      before do
        factories.define(:user) do |f|
          # ...
          f.association(:tasks, count: 2)
        end

        factories.define(:task) do |f|
          f.sequence(:title) { |n| "Task #{n}" }
        end
      end

      # ...

      it 'allows overrides' do
        task = factories[:task]
        user = factories[:user, tasks: [task]]

        expect(rom.relations[:tasks].count).to eq 1

        task = rom.relations[:tasks].one
        expect(task[:user_id]).to_not be(nil) # fail
        expect(user.tasks.count).to eq 1 # fail
      end
    end

Allow for creating multiple instances in one DB call

Testing features such as pagination requires presence of a number of objects in the repository. Creation of these entities takes more time, since each faked object is created separately. Yet ROM allows for calling commands with multiple instances, which is much more efficient. It would be a nice feature if instead of

10.times { Factory[:user] }

we had

Factory[:user, instances: 10]

which would be executed as a single DB call.

Argument error could be more informative

I recently managed to create a join table for image attachments on news items in which I failed to define a primary key like the below:

primary_key [:news_item_id, :asset_id]

The first sign of my mistake was rom-factory raising the following error when calling the relation's factory:

ArgumentError:
       ROM::Relation::Combined#by_pk arity is 1 (0 args given)

I was able to find my mistake with help from @timriley, but I wonder if we could add mention to that error to check one's primary key as a pointer to others?

The top of the stacktrace was:

/Users/andrewcroome/.rbenv/versions/2.4.2/lib/ruby/gems/2.4.0/gems/rom-core-4.2.0/lib/rom/relation/curried.rb:73:in `to_a'
/Users/andrewcroome/.rbenv/versions/2.4.2/lib/ruby/gems/2.4.0/gems/rom-core-4.2.0/lib/rom/relation/materializable.rb:55:in `first'
/Users/andrewcroome/.rbenv/versions/2.4.2/lib/ruby/gems/2.4.0/gems/rom-factory-0.6.0/lib/rom/factory/builder/persistable.rb:31:in `create'

Ruby 2.7 deprecations

Describe the bug

rom-factory causes deprecation warnings when used with Ruby 2.7.

To Reproduce

  • Use rom-factory with Ruby 2.7
  • See warnings in logs for RSpec

Example

ruby/2.7.0/lib/ruby/gems/2.7.0/gems/rom-factory-0.10.1/lib/rom/factory/dsl.rb:18: warning: Using the last argument as keyword parameters is deprecated; maybe ** should be added to the call

Expected behavior

It should not cause deprecation warnings.

Your environment

  • Ruby version: 2.7.0

Error with `factories.structs[:relation]` after upgrade to 0.7.0

In-memory struct creation that worked under 0.6.0 no longer works with 0.7.0

Factories defined as:

factories.define(:account) do |f|
  f.email { fake(:internet, :email) }
  # ...
end

factories.define(:member) do |f|
  f.association(:account)
  f.name { fake(:name) }
  # ...
end

When I call factories.structs[:member], I get the following error:

[ROM::Struct::Member.new] :account is missing in Hash input (Dry::Struct::Error)

I believe the problem is related to this line:

attributes = relation.output_schema.call(attributes)

Before that method call, attributes does contain a value for the :account key, afterwards it does not.

Inconsistent behaviour of Factory.structs between v0.11 and v0.12

Describe the bug

IDs are not created for associations in v0.12 as they were in v0.11

To Reproduce

with Factories:

Factory.define(:operator) do |f|
  f.id { SecureRandom.uuid }
  f.name 'Some Operator'
  f.created_at { Date.today.prev_month }
  ...
end

Factory.define(:membership) do |f|
  f.id { SecureRandom.uuid }
  f.customer_id { SecureRandom.uuid }
  f.created_at { Date.today.prev_month }
  f.status 'active'
  f.association(:operator)
  ...
end

def build(name, **args)
  Factory.structs[name, **args]
end

and called in rspec tests with

  let(:membership) { build(:membership) }

Expected behavior

in v0.11 it returned:

membership: #<ROM::Struct::Membership
  id="8e2225df-a2bb-4305-b949-67587bd4c949"
  customer_id="f2e10f3c-52cc-43fe-9958-6a17255208fb"
  created_at=#<Date: 2024-03-05 ((2460375j,0s,0n),+0s,2299161j)>
  status="active"
  operator_id="93f53cca-603f-41b3-bb67-e2f3fa8b6fc3"
  operator=#<ROM::Struct::Operator
    id="93f53cca-603f-41b3-bb67-e2f3fa8b6fc3"
    name="Some Operator"
    created_at=#<Date: 2024-03-05 ((2460375j,0s,0n),+0s,2299161j)>
    ...
  >
  ...
>

in v0.12 it returns:

membership: #<ROM::Struct::Membership
  id="8e2225df-a2bb-4305-b949-67587bd4c949"
  customer_id="f2e10f3c-52cc-43fe-9958-6a17255208fb"
  created_at=#<Date: 2024-03-05 ((2460375j,0s,0n),+0s,2299161j)>
  status="active"
  operator_id=nil
  operator=#<ROM::Struct::Operator
    id=nil
    name="Some Operator"
    created_at=#<Date: 2024-03-05 ((2460375j,0s,0n),+0s,2299161j)>
    ...
  >
  ...

I would have expected the same result as in v0.11

My environment

  • Affects my production application: NO, currently only using factory for tests
  • Ruby version: 2.7.7, and 3.2.2
  • OS: linux/alpine

Switch to commands

Currently this is tied to rom-sql as it uses Relation#insert, when we switch to commands it'll be possible to use it with any rom adapter.

โš ๏ธ Let's target rom 4.0 as it'll provide a command generator ported from rom-repository โš ๏ธ

Add possibility to use unique-ft of faker

Describe the bug

At the moment it's not possible to use unique-feature of faker.

To Reproduce

Factory.define(:company) do |f|
  f.id { fake(:alphanumeric, :unique, :alpha, number: 3).upcase } # will fail
  f.name { fake(:name, :name) }
end

Expected behavior

id should be unique

Proposal

What do you think about following solution:
We could allow a unique-option at our DSL and if unique is set to true, the method unique is called in front of the specified method (alpha in this case)

Factory.define(:company) do |f|
  f.id { fake(:alphanumeric, :alpha, number: 3, unique: true).upcase }
  # resulting call will be Faker::Alphanumeric.unique.alpha(number: 3)
end

WDYT?

Thanks and best regards

Question: what do you think about traits (like in FactoryGirl)?

http://www.rubydoc.info/gems/factory_girl/file/GETTING_STARTED.md#Traits

factory :user, aliases: [:author]

factory :story do
  title "My awesome story"
  author

  trait :published do
    published true
  end

  trait :unpublished do
    published false
  end

  trait :week_long_publishing do
    start_at { 1.week.ago }
    end_at   { Time.now }
  end

  trait :month_long_publishing do
    start_at { 1.month.ago }
    end_at   { Time.now }
  end

  factory :week_long_published_story,    traits: [:published, :week_long_publishing]
  factory :month_long_published_story,   traits: [:published, :month_long_publishing]
  factory :week_long_unpublished_story,  traits: [:unpublished, :week_long_publishing]
  factory :month_long_unpublished_story, traits: [:unpublished, :month_long_publishing]
end

overriding factory attributes is causing related field callbacks to fail

Describe the bug

Overriding attributes is causing factory field resolver to receive nil instead of overwritten value.

To Reproduce

create file app_spec.rb with:

require 'rom'
require 'rom-factory'

ROM_CONTAINER = ROM.container(:sql, 'sqlite::memory') do |conf|
  conf.default.create_table(:users) do
    primary_key :id
    column :name, String, null: false
    column :email, String, null: false
  end

  class Users < ROM::Relation[:sql]
    schema(infer: true)
  end

  conf.register_relation(Users)
end

Factory = ROM::Factory.configure do |config|
  config.rom = ROM_CONTAINER
end

Factory.define(:user) do |f|
  f.name 'John'
  f.email { |name| name.downcase + '@example.com' }
end

RSpec.describe 'app' do
  let(:data) do
    { name: 'Alice' }
  end

  let(:user) { Factory[:user, data] }

  specify do
    pp user
  end
end

now rspec app_spec.rb is producing following error:

 NoMethodError:
       undefined method `downcase' for nil:NilClass
     # ./app_spec.rb:24:in `block (2 levels) in <top (required)>'
     # ./app_spec.rb:32:in `block (2 levels) in <top (required)>'
     # ./app_spec.rb:35:in `block (2 levels) in <top (required)>'

Expected behavior

I was expecting email callback to receive Alice value.

My environment

  • Affects my production application: YES/NO
  • Ruby version: 2.6.5
  • OS: 10.15.5

Top-Level custom structs are not recognized

Describe the bug

We can define custom structs nested in a module, and then pointing to it via structs_namespace option. It works fine, but it does not work with top-level custom struct classes.

Reasoning:
It makes it problematic to update Hanami 1 applications to Hanami 2, because Hanami-Model (Hanami 1) assumed top-level entities to be defined.

Other than that, this behaviour is inconsistent.

To Reproduce

I've written rspec examples for this usecase: swilgosz@b0afeb7

class User < ROM::Struct
end

factories.define(:user) do |f|
  f.first_name "Jane"
end

factories.define(admin: :user) do |f|
  f.first_name "John"
end

Factory[:user].class
=> ROM::Struct::User
Factory[:admin]
=> ROM::Struct::Admin.class


module Entities
  class User < ROM::Struct
  end
end

factories.define(:user, struct_namespace: Entities) do |f|
  f.first_name "Jane"
end

factories.define(admin: :user, struct_namespace: Entities) do |f|
  f.first_name "John"
end

Factory[:user].class
=> Entities::User
Factory[:admin].class
=> ROM::Struct::Admin

Expected behavior

I expect that either, by passing struct_namespace: nil or by default, ROM-Factory will try to call the top-level structs if they are defined. It should fallback to ROM::Struct::[[FactoryClass]] in the constant is not found, or is not a kind of ROM::Struct

My environment

  • Affects my production application: YES
  • Ruby version: 3.0.2
  • OS: Mac OS

Rom factory crashing on associations with version 4.0 of rom

The association now crashes when run against the latest version of rom:

It appears that for associations the key that is being passed in to the 'def fetch(key)' method is the actual factory that has been initialized, instead of the key.

The error:

NoMethodError:
  undefined method `to_sym' for #<IdentityProviders:0x007fe1c0554e58>
  Did you mean?  to_s
# /Users/cmavromoustakos/.rvm/gems/ruby-2.4.1/gems/rom-core-4.0.0/lib/rom/registry.rb:63:in `fetch'
# /Users/cmavromoustakos/.rvm/gems/ruby-2.4.1/gems/rom-factory-0.4.0/lib/rom/factory/dsl.rb:59:in `association'
# ./spec/support/factories.rb:12:in `block in <main>'
# /Users/cmavromoustakos/.rvm/gems/ruby-2.4.1/gems/rom-factory-0.4.0/lib/rom/factory/dsl.rb:31:in `initialize'

Debugger

From: /Users/cmavromoustakos/.rvm/gems/ruby-2.4.1/gems/rom-core-4.0.0/lib/rom/registry.rb @ line 66 ROM::Registry#fetch:

    60: def fetch(key)
    61:   raise ArgumentError.new('key cannot be nil') if key.nil?
    62:
    63:   require 'pry'
    64:   binding.pry
    65:
 => 66:   elements.fetch(key.to_sym) do
    67:     return yield if block_given?
    68:
    69:     raise self.class.element_not_found_error.new(key, self)
    70:   end
    71: end

[1] pry(#<ROM::RelationRegistry>)> key
=> #<IdentityProviders name=ROM::Relation::Name(identity_providers) dataset=#<Sequel::Postgres::Dataset: "SELECT \"identity_providers\".\"id\", \"identity_providers\".\"name\", \"identity_providers\".\"saml_metadata_url\", \"identity_providers\".\"created_at\", \"identity_providers\".\"updated_at\" FROM \"identity_providers\" ORDER BY \"identity_providers\".\"id\"">>


Factory.define(:user) do |f|
  ...
  f.association(:identity_provider)
  f.timestamps
end

Gemfile.lock

  โ”† rom (4.0.0)
  โ”† โ”† rom-changeset (~> 1.0)
  โ”† โ”† rom-core (~> 4.0)
  โ”† โ”† rom-mapper (~> 1.0)
  โ”† โ”† rom-repository (~> 2.0)
  โ”† rom-changeset (1.0.0)
  โ”† โ”† dry-core (~> 0.3, >= 0.3.1)
  โ”† โ”† rom-core (~> 4.0.0.rc)
  โ”† โ”† transproc (~> 1.0)
  โ”† rom-core (4.0.0)
  โ”† โ”† concurrent-ruby (~> 1.0)
  โ”† โ”† dry-container (~> 0.6)
  โ”† โ”† dry-core (~> 0.3)
  โ”† โ”† dry-equalizer (~> 0.2)
  โ”† โ”† dry-initializer (~> 2.0)
  โ”† โ”† dry-types (~> 0.12, >= 0.12.1)
  โ”† โ”† rom-mapper (~> 1.0)
  โ”† rom-factory (0.4.0)
  โ”† โ”† dry-configurable (~> 0.1)
  โ”† โ”† dry-core (~> 0.2)
  โ”† โ”† dry-struct (~> 0.2)
  โ”† โ”† faker (~> 1.7)
  โ”† rom-mapper (1.0.0)
  โ”† โ”† dry-core (~> 0.3, >= 0.3.1)
  โ”† โ”† dry-equalizer (~> 0.2)
  โ”† โ”† transproc (~> 1.0)
  โ”† rom-repository (2.0.0)
  โ”† โ”† dry-struct (~> 0.3)
  โ”† โ”† rom-mapper (~> 1.0)
  โ”† rom-sql (2.0.0)
  โ”† โ”† dry-core (~> 0.3)
  โ”† โ”† dry-equalizer (~> 0.2)
  โ”† โ”† dry-types (~> 0.12, >= 0.12.1)
      rom-core (~> 4.0)
  โ”† โ”† sequel (>= 4.49)

Factory assumes my primary key is an integer sequence

I have primary keys which are bytea strings. If I have a relation like this

class Thing < ROM::Relation[:sql]
  schema(:things) do
    attribute :custom_id, ROM::SQL::Types::Blob
    attribute :name, String

    primary_key :custom_id
  end
end

and then my factory definition looks like this

Factory = ROM::Factory.configure { |c| c.rom = rom }

Factory.define(:thing) do |f|
  f.sequence(:custom_id) { |_| File.binread('/dev/urandom', 10) }
  f.name 'some thing'
end

then the factory builder will clobber it.

It would be nice if it didn't. If I have a non-numeric primary key then I'd also love if it raised an error if I didn't define a sequence for it.

Unexpected behaviour of dependent attributes

Description

Dependent attributes are not taking into account when the source attribute is passed to factory call.

Factory.define(:user) do |f|
  f.user_name { fake(:name) }
  f.email { |user_name| "#{user_name}@example.com" }
end

Factory[:user] #=> <#User user_name="rand" email="[email protected]">
Factory[:user, user_name: "rrom"] #=> <#User user_name="rrom" email="@example.com">

has_one, has_many associations seem not working

I found that has_one and has_many associations didn't work properly.
In this reproduction code, has_many is used, but has_one results in the same.
I traced into rom-factory and dry, but there was no idea about the root cause.

Steps for Reproduction

require 'rom'
require 'rom-factory'

rom = ROM.container(:sql, 'sqlite::memory') do |conf|
  conf.default.create_table(:companies) do
    primary_key :id
    column :name, String, null: false
  end

  conf.default.create_table(:users) do
    primary_key :id
    column :name, String, null: false
    column :company_id, Integer, null: false
  end

  conf.relation(:companies) do
    schema(:companies, infer: true) do
      associations do
        has_many :users
      end
    end
  end

  conf.relation(:users) do
    schema(:users, infer: true) do
      associations do
        belongs_to :companies, as: :company
      end
    end
  end
end

MyFactory = ROM::Factory.configure do |c|
  c.rom = rom
end

MyFactory.define(:company) do |f|
  f.name { fake(:company, :name) }
  f.association(:users, count: 2)
end

MyFactory.define(:user) do |f|
  f.name { fake(:name) }
  f.association(:company)
end

p MyFactory.structs[:user]
p MyFactory.structs[:company]

Expected behavior:

#<ROM::Struct::User id=1 name="Emmet Koss" company_id=1 company=#<ROM::Struct::Company id=1 name="Heaney, Wilkinson and Senger">>
#<ROM::Struct::Company id=1 name="Acme Inc" users=[#<ROM::Struct::User id=1 name="Emmet Koss" company_id="1">, #<ROM::Struct::User id=2 name="Bryce Lehner" company_id="1">]>

Actual behavior:

#<ROM::Struct::User id=1 name="Emmet Koss" company_id=1 company=#<ROM::Struct::Company id=1 name="Heaney, Wilkinson and Senger">>
Traceback (most recent call last):
	12: from assoc_test.rb:48:in `<main>'
	11: from /Users/tokitake/workspace/rom/vendor/bundle/ruby/2.5.0/gems/rom-factory-0.6.0/lib/rom/factory/factories.rb:43:in `[]'
	10: from /Users/tokitake/workspace/rom/vendor/bundle/ruby/2.5.0/gems/rom-factory-0.6.0/lib/rom/factory/builder.rb:30:in `struct'
	 9: from /Users/tokitake/workspace/rom/vendor/bundle/ruby/2.5.0/gems/rom-factory-0.6.0/lib/rom/factory/tuple_evaluator.rb:34:in `struct'
	 8: from /Users/tokitake/workspace/rom/vendor/bundle/ruby/2.5.0/gems/dry-struct-0.4.0/lib/dry/struct/class_interface.rb:95:in `new'
	 7: from /Users/tokitake/workspace/rom/vendor/bundle/ruby/2.5.0/gems/dry-types-0.12.2/lib/dry/types/constructor.rb:47:in `call'
	 6: from /Users/tokitake/workspace/rom/vendor/bundle/ruby/2.5.0/gems/dry-types-0.12.2/lib/dry/types/hash/schema.rb:27:in `call'
	 5: from /Users/tokitake/workspace/rom/vendor/bundle/ruby/2.5.0/gems/dry-types-0.12.2/lib/dry/types/hash/schema.rb:97:in `coerce'
	 4: from /Users/tokitake/workspace/rom/vendor/bundle/ruby/2.5.0/gems/dry-types-0.12.2/lib/dry/types/hash/schema.rb:110:in `resolve'
	 3: from /Users/tokitake/workspace/rom/vendor/bundle/ruby/2.5.0/gems/dry-types-0.12.2/lib/dry/types/hash/schema.rb:110:in `each'
	 2: from /Users/tokitake/workspace/rom/vendor/bundle/ruby/2.5.0/gems/dry-types-0.12.2/lib/dry/types/hash/schema.rb:112:in `block in resolve'
	 1: from /Users/tokitake/workspace/rom/vendor/bundle/ruby/2.5.0/gems/dry-types-0.12.2/lib/dry/types/hash/schema.rb:99:in `block in coerce'
 /Users/tokitake/workspace/rom/vendor/bundle/ruby/2.5.0/gems/dry-types-0.12.2/lib/dry/types/array/member.rb:20:in `call': undefined method `map' for #<Proc:0x00007fb77731e698> (NoMethodError)
Did you mean?  tap

Platforms:
macOS 10.13.3
ruby 2.5.0

Version:
rom 4.1.3
rom-factory 0.6.0

Trait and dependent attributes conflicting

Describe the bug

When using the dependent attribute feature of factories there is an unforeseen result. If the method that is being defined is created as a part of the trait and another method uses the dependent attribute feature to access that value the result of said method corresponds with the parent factory object and not the trait. This can be fixed by defining the method value directly in the creation of the factory object. But should also work in the previous statement.

To Reproduce

Factory.define(:store) do |f|
  f.name { fake(:company, :name) }
  f.location_name { |name| "#{name} west" }
end

 f.trait :new_store do |t|
    t.name { 'New Store' }
  end


create :store
result = { name: 'Random Store Name, location_name: 'Random Store Name West'} #Correct

create :store, :new_store
result = { name: 'New Store', location_name: 'Random Store Name West'} # Incorrect

HOWEVER

create :store, :new_store, name: 'Explicit Store Name'
result = { name: 'Explicit Store Name', location_name: 'Explicit Store Name West'} #Correct

Expected behavior

Factory.define(:store) do |f|
  f.name { fake(:company, :name) }
  f.location_name { |name| "#{name} west" }
end

 f.trait :new_store do |t|
    t.name { 'New Store' }
  end


create :store
result = { name: 'Random Store Name, location_name: 'Random Store Name West'}

create :store, :new_store
result = { name: 'New Store', location_name: 'New Store West'}

My environment

  • Affects my production application: YES
  • Ruby version:2.7.4
  • OS: Mac

has_many or has_one with 3 or more factories not workig

Hi all!

It seems that when we have a cascade has_many or has_one with 3 or more factories some records are not created properly.

In the example below, when I call MyFactory[:company] the actual result is:

#<ROM::Struct::Company id=1 name="Reilly-Labadie" users=[#<ROM::Struct::User id=1 name="Bernie Mueller" company_id=1>, #<ROM::Struct::User id=2 name="Jeff Dickens" company_id=1>]>

But should be:
#<ROM::Struct::Company id=1 name="Reilly-Labadie" users=[#<ROM::Struct::User id=1 name="Bernie Mueller" company_id=1 tasks=#<ROM::Struct::Task id=18 name="Jessie Roob" user_id=1>>, #<ROM::Struct::User id=2 name="Jeff Dickens" company_id=1 tasks=#<ROM::Struct::Task id=19 name="Jessie Roob" user_id=2>>]>

require 'rom'
require 'rom-factory'

rom = ROM.container(:sql, 'sqlite::memory') do |conf|
  conf.default.create_table(:companies) do
    primary_key :id
    column :name, String, null: false
  end

  conf.default.create_table(:users) do
    primary_key :id
    column :name, String, null: false
    column :company_id, Integer, null: false
  end

  conf.default.create_table(:tasks) do
    primary_key :id
    column :name, String, null: false
    column :user_id, Integer, null: false
  end

  conf.relation(:companies) do
    schema(:companies, infer: true) do
      associations do
        has_many :users
      end
    end
  end

  conf.relation(:users) do
    schema(:users, infer: true) do
      associations do
        belongs_to :companies, as: :company
        has_one :tasks
      end
    end
  end

  conf.relation(:tasks) do
    schema(:tasks, infer: true) do
      associations do
        belongs_to :users, as: :user
      end
    end
  end
end

MyFactory = ROM::Factory.configure do |c|
  c.rom = rom
end

MyFactory.define(:company) do |f|
  f.name { fake(:company, :name) }
  f.association(:users, count: 2)
end

MyFactory.define(:user) do |f|
  f.name { fake(:name) }
  f.association(:company)
  f.association(:tasks)
end

MyFactory.define(:task) do |f|
  f.name { fake(:name) }
  f.association(:user)
end

Allow usage of relations in dependant attributes

Noticed that when using a relation as dependency in creating an attribute the relation always comes in nil, any way I can achieve this?

I have tables that have some of the data denormalized and some attributes need to have the same value on the entity and on the relation.

Has many association does not seem to work as expected

Here is what I am trying to build:

        Factory[:shift,
                shift_positions: [
                  Factory[:shift_position],
                  Factory[:shift_position]
                ]
        ]

My factory definitions are:

Factory.define :shift do |f|
  f.association(:shift_positions, count: 2)
end
Factory.define :shift_position do |f|
  f.association(:shift)
end

The problem is the top code will return the shift_positions code empty.

Overriding attributes doesn't affect dependent attributes

Describe the bug

Whenever I have an attribute which depends on another one, overriding the dependency (i.e. with a trait) doesn't affect the calculated attribute.

Seems similar to #63, but a bit different

To Reproduce

require 'bundler/inline'

gemfile do
  source 'https://rubygems.org'
  gem 'rom'
  gem 'rom-sql'
  gem 'sqlite3'
  gem 'rom-factory', '~> 0.10.2'
end

require 'rom'
require 'rom-factory'

ROM_CONTAINER = ROM.container(:sql, 'sqlite::memory') do |conf|
  conf.default.create_table(:users) do
    primary_key :id
    column :name, String, null: false
    column :email, String, null: false
  end

  class Users < ROM::Relation[:sql]
    schema(infer: true)
  end

  conf.register_relation(Users)
end

Factory = ROM::Factory.configure do |config|
  config.rom = ROM_CONTAINER
end

Factory.define(:user) do |f|
  f.name 'John'
  f.email { |name| name.downcase + '@example.com' }

  f.trait :jane do |t|
    t.name 'Jane'
  end
end

pp Factory[:user, :jane] # #<ROM::Struct::User id=1 name="Jane" email="[email protected]">

Expected behavior

I expect calculated field to change its value depending on name, even if I override name in a trait.

My environment

  • Affects my production application: YES (kind of? )
  • Ruby version: 3.0.1
  • OS: macOS Big Sur 11.2.2

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.