Labeled fixtures for associations in Rails 3 broken - ruby-on-rails

After upgrading to Rails 3, fixtures that refer to other labelled fixtures (for relationships) stop working. Instead of finding the actual fixture with that name, the fixture label is interpreted as a string.
Example:
# Dog.yml
sparky:
name: Sparky
owner: john
# Person.yml
john:
name: John
Where Dog "belongs to" person.
The error message is:
SQLite3::SQLException: table dogs has no column named 'owner'

Try
# Dog.yml
sparky:
name: Sparky
owner: john (Person)
# Person.yml
john:
name: John
See the "polymorphic belongs_to" section of http://api.rubyonrails.org/classes/Fixtures.html

try this:
sparky:
name: Sparky
owner: john (Person)

Related

Nil Associations with Rails Fixtures... how to fix?

I have a Rails 5.1 project using rspec/fixtures and I am having trouble getting fixtures to load objects associated with belongs_to/has_one/has_many: the object I requested the fixture for comes back with its _id columns filled with a seemingly-random number and ActiveRecord sees the association as nil. This occurs on large classes with many associations as well as small data classes with only a few fields.
If, in my test code, I assign those associations with normal Ruby code, objects behave as normal and my tests pass. However when loading the same data through fixtures, associated records are not available and tests that require data spanning across associations fail.
As an example, here are two affected classes:
#app/models/location.rb
class Location < ActiveRecord::Base
has_many :orders
has_many :end_user
belongs_to :retailer
belongs_to :depot
end
#app/models/retailer.rb
class Retailer < ActiveRecord::Base
has_many :locations
end
And here are two corresponding fixtures files:
#spec/fixtures/locations.yml
loc_paris:
retailer: ret_europe (Retailer)
name: "Paris"
nickname: "paris"
loc_washington:
retailer: ret_usa (Retailer)
name: "Washington"
nickname: "washington"
#spec/fixtures/retailers.yml
ret_europe:
name: "AcmeCo France"
nickname: "acmecofr"
currency_type: "EUR"
ret_usa:
name: "AcmeCo USA"
nickname: "acmecousa"
currency_type: "USD"
With the above data, running pp locations(:loc_paris) results in:
#<Location:0x0000000006eee1d8
id: 35456173,
name: "Paris",
nickname: "paris",
retailer_id: 399879241,
created_at: Wed, 23 May 2018 22:39:56 UTC +00:00,
updated_at: Wed, 23 May 2018 22:39:56 UTC +00:00>
Those id numbers are consistent through multiple calls, at least in the same RSpec context. (I put pp locations(:loc_paris) in a let block.) Yet pp locations(:loc_paris).retailer returns nil.
I tried using FactoryBot however we had to switch away from it. I am trying to give fixtures an honest shake but it seems like we are best off simply building data objects in the actual test code... because that solutions works without complaining :/
Am I doing something wrong here? Are we asking too much of fixtures?
Thank you!
Tom
Problem with fixtures
Looking at what you've done, locations(:loc_paris) will find the record described in locations.yml, but locations(:loc_paris).retailer won't.
Rails Associations work like this:
locations(:loc_paris).retailer will look for the retailer with retailer_id mentioned in locations(:loc_paris) record. In your case retailer_id: 399879241 and there is no reseller with this id that's why it returns Nil.
Solution:
Describe fixtures like this:
#spec/fixtures/locations.yml
loc_paris:
retailer_id: 1
name: "Paris"
nickname: "paris"
loc_washington:
retailer_id: 2
name: "Washington"
nickname: "washington"
#spec/fixtures/retailers.yml
ret_europe:
id: 1
name: "AcmeCo France"
nickname: "acmecofr"
currency_type: "EUR"
ret_usa:
id: 2
name: "AcmeCo USA"
nickname: "acmecousa"
currency_type: "USD"
Now, locations(:loc_paris).retailer will look for the retailer with retailer_id mentioned in locations(:loc_paris) record i.e. retailer_id: 1 and there is a reseller ret_europe with this id. Problem Solved
When you run rspec, at first rspec saves these fixtures into your database with some auto-generated id values (if id not provided explicitly), that's why id and reseller_id are some random values. If you don't want the id of locations.yml record to be some random value, you can provide it yourself like this:
loc_paris:
id: 1
retailer_id: 1
name: "Paris"
nickname: "paris"
Tips:
As rspec runs in test environment (mentioned in app/spec/rails_helper.rb) and as I mentioned earlier whenever you run rspec, at first it saves the fixtures into your database. If your local and test database are same, fixtures will replace the actual database records of your database. In your case, records in locations and resellers table record will be completely erased and replaced with these fixtures. So, make different database for test environment.
Hope this answer is helpful

Rails not loading fixtures in test with similar names with STI

I have 3 classes with STI and I want to load fixtures for each:
Employee
Admin < Employee
OtherEmployee < Employee
My test_helper files has fixtures :all
and the fixtures are in:
employees.yml
admins.yml
other_employees.yml
and yet only the data from other_employees.yml is loaded into the database. Any idea why or how to fix this?
Fixtures:
#employees.yml
one:
id: 1
name: Name1
full_name: FName1
type: Admin
two:
name: Name2
full_name: FName2
type: Admin
three:
name: Name3
full_name: FName3
type: OtherEmployee
#admins.yml
adminone:
name: Admin1
full_name: FAdmin1
type: Admin
admintwo:
name: Admin2
full_name: FAdmin2
type: Admin
#other_employees.yml
oeone:
name: Oemp1
full_name: FOemp1
type: OtherEmployee
oetwo:
name: Oemp2
full_name: FOemp2
type: OtherEmployee
Which version of Rails are you using? It appears that this was a bug and was fixed in Rails 5 and 4.2
https://github.com/rails/rails/issues/18492
There is also some info in the last comment that may be helpful.
https://github.com/rails/rails/issues/18492#issuecomment-218479248
For anyone still running into this problem you need to add a type
attribute to your fixtures, which represents the STI attribute on your
model. For the provided example this would be:
#teachers.yml
presto:
name: Test Teacher
type: Teacher
#students.yml
testo:
name: Test Person
teacher: presto
type: Student

Intersection of 2 arrays of hashes by hash value (such as id)

In my rails app, I have a user model and a linkedin_connection model. Linkedin_connection belongs to user and user has_many linkedin_connections.
What's the best way to create a crossover array of connections between user1 and user2?
============== EDIT ============== EDIT ============== EDIT ==============
I realized that this is sort of a different problem than I originally thought. I have 2 arrays of hashes. Each hash has an id element. How can I find the intersection of two hashes by their ids?
Example
user1.linkedin_connections => [{id: "123xyz", name: "John Doe"}, {id: "789abc", name: "Alexander Supertramp"}]
user2.linkedin_connections => [{id: "456ijk", name: "Darth Vader"}, {id: "123xyz", name: "John Doe"}]
cross_connections => [{id: "123xyz", name: "John Doe"}]
How can I calculate "cross_connections?"
Thanks!
What you want is the intersection of the two arrays. In ruby, that's easy, using the & operator:
crossover_connections = user1.linkedin_connections.to_a & user2.linkedin_connections.to_a

Categories and subcategories with seeds.rb

I have a form and want to be able to select category & subcategory.
This is an automatic example from seeds.rb:
Examples:
cities = City.create([{ name: 'Chicago' }, { name: 'Copenhagen' }])
Mayor.create(name: 'Emanuel', city: cities.first)
There is cities.first - but can you do it for cities.sixth or cities.twelfth...?
Is there a different way to do it and connect subcategories with categories in the file?
I would personally advise against using positions to assign subcategories. The possibility exists that there is data on another devs machine or a server.
I generally do it something like:
city = City.find_or_create_by_name(
name: "Chicago"
)
mayor = Mayor.find_or_create_by_city_id(
city_id: city.id,
name: 'Emanuel')

Doctrine: Define many-to-many relation inline in fixture

I want to know the correct way of defining many-to-many relations inline in a Doctrine Fixture. Consider sfDoctrineGuardPlugin for example. The schema can be found here
I'm defining a fixture like:
I already have 2 groups in the sfGuardGroup table, so I wish to refer the group_id
sfGuardUser:
soc-sfUser-1:
first_name: Mrs
last_name: Balasubramanium
email_address: balasubramanium#gmail.com
username: balasubramanium#gmail.com
password: admin
Groups: [{group_id: 2}]
is_active: 1
Is this correct?
If you are also defining the groups in that fixture, you can reference them by name:
sfGuardGroup:
GroupAdmin: ...
GroupEditor: ...
sfGuardUser:
...
Groups: [GroupEditor]
If you want to specify an actual ID you should write it this way:
sfGuardUser:
foo:
first_name: Foo
last_name: Bar
...
sfGuardUserGroup: [{group_id: 2}]
Why? If you take a look at the schema.yml file of sfDoctrineGuardPlugin you can see a refClass property on sfGuardUser relations:
relations:
Groups:
...
refClass: sfGuardUserGroup
It's a little tricky and not so well documented in Doctrine, but it seems to work.

Resources