factory_girl - has_many relationships and refreshing the parent model - factory-bot

I keep running into the same issue, and I would be surprised if I am the only person experiencing this and expect someone has a better way of doing this. When I create a Factory which has a dependent Factory (association), then the parent model is not updated with the model that has been added. Probably easier to explain in code.
Say I have:
Factory.define :company do |a|
a.name 'Acme'
end
Factory.define :office do |a|
a.name 'London'
a.association :company, :factory => :company
end
and I execute this code:
london = Factory.create(:office)
sanfran = Factory.create(:office, :name => 'San Fran' , :company = london.company)
then if I run this test
london.company.offices.count.should eql(2)
it fails, because company Acme was instantiated before London or even San Fran were created, and because company.offices.new was not used to create the new models, the company model was never updated.
The only way I have been able to work around this issue is to write my tests as follows:
london.company(true).offices.count.should eql(2)
which forces a refresh.
However, this is really not ideal to do this every time in my tests, especially when the code it is testing should not have to rely on that.

Is there a reason you can't create the parent company first? I don't seem to have a problem getting a count from a pre-instantiated parent after creating child objects.
describe Company do
describe "office associations" do
before(:each) do
#company = Factory(:company)
end
it "should have the correct number of offices" do
o1 = Factory(:office, :company => #company)
o2 = Factory(:office, :company => #company)
#company.offices.should =~ [o1, o2].flatten # <= Not sure why, but each call to Factory appears to return an array
end
end

Related

NullReferenceException using Where() in AutoMapper.MapFrom

I'm modelling a 3rd party database using Automapper 8 and EF 6.
One of my DTO classes needs to use a Where clause on an association to locate the correct record.
// Community table is mapped and working.
// Mapping breaks when mapping dest.Subjects
cfg.CreateMap<Person, PersonDto>()
// snip many mappings
.ForMember(dest => dest.Id, act => act.MapFrom(src => src.ID))
.ForMember(dest => dest.UserName, act => act.MapFrom(src => src.Community.NetworkLogin))
.ForMember(
dest => dest.Subjects,
act => act.MapFrom(
src => src.Community.StudentClasses.Where(
subject => subject.Year == CurrentSemester.Year && subject.Semester == CurrentSemester.Semester)))
.ForMember(
dest => dest.Contacts,
act => act.MapFrom(
src => src.Community.Contacts.Where(
contact => Contact.UseThis).Select(contact => contact.ContactDetails)));
This code works in production, but I'd really like to Unit Test this model. Running a simple test (get all records in the Mock) I'm hit with a NullReferenceException when it tries to access the Community.StudentClasses object.
I found this answer relating to NullReferenceExceptionexceptions and AutoMapper, which helped me fix the rest of the references in this config, but I'm still having issues with this one. The test works when I remove the Community.StudentClasses mapping.
I'm mocking objects using code similar to:
public static Person Person19788 =>
new SchoolContact
{
ID = 19788,
NetworkLogin = "username",
// Tried various creation methods
// StudentClasses = new List<StudentClass> {new StudentClass()},
// StudentClasses = new List<StudentClass> {new StudentClass {Year = 0, Semester = 0}},
StudentClasses = null,
StudentContacts = null,
Address = Address19788
};
CurrentSemester has been checked, and returns valid non-zero values for Year and Semester.
The strange thing is that the Contacts mapping works fine, even with null values. So I assume that I've broken my Subjects mapping somewhere along the line, but I'm unsure where else to look.
It turns out that the problem was with my Subjects mapping after all.
The top-level associations were mapped correctly, however the lower-level associations were not. (I didn't include these mappings because a) I didn't think about them, and b) there's only so much code that anyone would be willing to wade through).
After fixing up the w > x > y > z mappings everything is working as expected. I thought I'd exhausted all options before posting this question. Lesson learned: don't post to SO until you've slept on it and taken a fresh look at the code the next day.

Accessing values from one-to-many relationship in PonyORM

For a database of games, where one game is called different names by different users, I have two tables, set up as one-to-many:
class Game(db.Entity):
name = Set('Name')
...
class Name(db.Entity):
game = Required(Game)
name = Required(str)
...
How can I access the names for a specific game? They come back as "Multiset", which (I think) is a special Counter object, when I do this:
games = Game.select()
for g in games:
names = g.name.name
print(names)
>>> Multiset({'Sticks And Stones': 1, 'May Break Your Bones': 1 })
This also seems pretty ugly to me, I suppose there must be a better way?
It turns out the to_dict() method, well documented in PonyORM's API Reference, helps greatly with to-many relationships.
for g in games:
this_game = g.to_dict(
with_collections=True,
related_objects=True,
exclude=['game_meta', 'statistics']
)
And then access the dict() entries like this: this_game['name']

Exclude derived entities from requests to the base class

I have this DbContext:
public class DataContext : DbContext
{
public DbSet<Base> Bases {get;set}
public DbSet<Sub> Subs {get;set}
}
Sub is a subclass of Base.
When I'm querying the list of Base entities like so:
Context.Bases.ToListAsync()
It returns me every entities, either Base or Sub.
How can I configure my model context to get only the entities that are of Base type and not the ones that derives from it.
The best (or least worst) solution I found is to directly use the shadow property:
Context.Bases.Where(b => EF.Property<string>(b, "Discriminator") == "Base")).ToListAsync();
It works but needs to be repeted now and then, each time I need to query Bases. I'd have prefered a solution in the OnModelCreating method.
I'll accept this answer unless someone else find a better solution.
You'd have to use OfType<T>:
var basesOnly = await _context.Bases.OfType<Base>().ToListAsync();
UPDATE
Sorry, then. I could have sworn the above works, but it doesn't. The next best method I can think of is to simply filter out the types you don't want. It's not ideal, because it requires specifying all subtypes in your query, which then means you need to remember to update it if you add more subtypes.
var basesOnly = await _context.Bases.Where(x => !(x is Sub)).ToListAsync();
How can I configure my model context to get only the entities that are
of Base type and not the ones that derives from it.
You cannot. Every Sub is a Base. So querying all Bases includes all Subs. Eg code like the following must succeed:
Base b = db.Bases.Where(i => i.Id == 1).Single();
if (b is Sub)
begin
Sub s = (Sub)b;
. . .
end
else //other Sub
begin
Sub2 s = (Sub2)b;
. . .
end
You can fetch an anonymous type with the just the base class properties.
And asking this question suggests that inheritance might is not the right modeling technique for your scenario.
If what you want it to fetch the Entities of type Base, but not the subtype Sub, then you can do that with a query like:
var q = from b in db.Bases
where !(b is Sub)
select b;
Which translates to :
SELECT [b].[Id], [b].[Discriminator], [b].[Name], [b].[Size]
FROM [Bases] AS [b]
WHERE [b].[Discriminator] IN (N'Sub', N'Base')
AND NOT ([b].[Discriminator] = N'Sub')
But you can't (currently) exclude all subtypes without enumerating them. Eg this query:
var q2 = from b in db.Bases
where b.GetType() == typeof(Base)
select b;
Will not be completely translated to SQL, and will filter out the subtypes on the client.

Retrieving data from a has_many relationship in DBIx::Class

Given a simple case of two tables - Term and Definition - where Term has_many Definitions and Definition belongs_to Term, all terms and the corresponding definitions are to be fetched and displayed somehow.
Here is what I've come up with so far:
my $terms= $schema->resultset('Term')->search(undef, {
prefetch => 'definitions',
});
while (my $term = $terms->next) {
my #terms;
push #terms, $term->term;
my $definitions = $term->definitions;
my #definitions;
while (my $definition = $definitions->next) {
push #definitions, $definitions;
}
...
}
It does the job but I was wondering if a different, less crufty approach could be taken.
my $terms= $schema->resultset('Term')->search(undef, {
prefetch => 'definitions',
});
my #terms = $terms->all;
my #definitions = map $_->definitions->all, #terms;
This looks like what you are trying to do; I can't really tell. The fact that you make a new array, push onto it, and then let it go out of scope doesn't really make any sense at all. Anyway, if I understand you correctly all you wanted was the all method from DBIx::Class::ResultSet.
DBIx::Class::Manual::Joining should help. See, for example, Whole related objects.

How to Use ActiveResource with Shallow Nested Routes?

I have a Rails application that has a Company resource with a nested resource Employee. I'm using shallow routing, so to manipulate Employee, my routes are:
GET /employees/1
PUT /employees/1
DELETE /employees/1
POST /companies/1/employees
How can I create, read, update, and destroy Employees using ActiveResource?
To create employees, I can use:
class Employee < ActiveResource::Base
self.site = "http://example.com/companies/:company_id"
end
But if I try to do:
e=Employee.find(1, :params => {:company_id => 1})
I get a 404 because the route /companies/:company_id/employees/:id is not defined when shallow routes are used.
To read, edit, and delete employees, I can use:
class Employee < ActiveResource::Base
self.site = "http://example.com"
end
But then there doesn't seem to be a way to create new Employees, due to the lack of the companies outer route.
One solution would be to define separate CompanyEmployee and Employee classes, but this seems overly complex.
How can I use a single Employee class in ActiveResource to perform all four CRUD operations?
I'm using Rails 3.0.9. You can set the prefix like this:
class Employee < ActiveResource::Base
self.prefix = "/companies/:company_id/"
end
And then
Employee.find(:all, :params => {:company_id => 99})
or
e = Employee.new(:name => "Corey")
e.prefix_options[:company_id] = 1
It will replace :company_id with the value from prefix_options.
There is a protected instance method named collection_path that you could override.
class Employee < ActiveResource::Base
self.site = "http://example.com"
def collection_path(options = nil)
"/companies/#{prefix_options[:company_id]}/#{self.class.collection_name}"
end
end
You would then be able to this to create employees.
e = Employee.new(:name => "Corey")
e.prefix_options[:company_id] = 1
e.save
It doesn't seem like the prefix_options is documented other than in the clone method so this might change in future releases.
See this article: http://blog.flame.org/2009/11/04/activeresource-and-shallow-nested-routes.html
Here, the author proposes to override class method collection_path. This makes sense, since this method is used also by new_element_path and will retrieve the same path in both cases.
Example:
class Employee < ActiveResource::Base
self.site = "http://example.com"
def self.collection_path(prefix_options = {},query_options=nil)
super
"/companies/#{query_options[:company_id]}/#{collection_name}.#{format.extension}#{query_string(query_options)}"
end
end
Then you can find employees for a company by doing:
company = Company.find(:first)
Employee.find(:all, :params => {:company_id => company.id })
I found it best to override ActiveResource::Base.element_path with the same functionality as defined in the library, but omitting the use of prefix_options in the returned value. There is no
class Employee < ActiveResource::Base
self.site = 'http://example.com'
self.prefix = '/companies/:company_id/'
# Over-ride method and omit `#{prefix(prefix_options)}` from the returned string
def self.element_path(id, prefix_options = {}, query_options = nil)
"/#{collection_name}/#{URI.parser.escape id.to_s}.#{format.extension}"
end
end
The Employee class will then behave as usual, with no need to assign prefix_options to the instance as suggested in other solutions.