Forum: Ruby on Rails Foxy Fixtures making inconsistent ids

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Mark S. (Guest)
on 2009-02-17 11:54
(Received via mailing list)
I'm trying to set up some new unit tests for classes I'm adding to a
project. Since I'm on Rails 2.1, I figured I'd make use of the Foxy
Fixtures to make things oh so much easier. Except that's not the way
my day has turned out.

I've got three classes where the parent class has a list of children,
which in turn has a list of grandchildren:

parent:
  id: integer
  name: text

  has_many :children, :order => :position

child:
  id: integer
  parent_id: integer
  name: text
  position: integer

  has_many :grandchildren, :order => :position
  belongs_to :parent
  acts_as_list :scope => :parent

grandchild:
  id: integer
  child_id: integer
  name: text
  position: integer

  belongs_to: child
  acts_as_list :scope => :child

(These aren't the real class names, I'm just using them to make my
explanation a bit clearer.)

When I created my fixtures, I made several parent objects without
using any erb:

parent_1:
   name: Some Parent

parent_2:
   name: Some Parent

This resulted in DB entries (MySQL) like this:

id    name      created_at      updated_at
461483557  Some Parent    2009-02-17 01:13:54    2009-02-17 01:13:54
461483556  Some Parent    2009-02-17 01:13:54    2009-02-17 01:13:54

The ids were hashed from the labels of the YAML fixture as expected.

Clearly I'm going to have some massive growth in the number of entries
I need for the children and grandchildren fixtures, so I wanted to use
ERB to help keep things clean and simple. For the child.yml file, I
wanted to have code that looks like this, but I ran into two problems:

<%
     parents = [ "parent_1", "parent_2" ]
%>

<% parents.each do |parent| %>

<%= parent %>_child1:
   position: 1
   name: Kid One
   parent: <%= parent %>
<%= parent %>_child2:
   position: 2
   name: Kid Two
   parent: <%= parent %>
<%= parent %>_child3:
   position: 3
   name: Kid Three
   parent: <%= parent %>

<% end %>

First, the database reports this error:
Mysql::Error: Unknown column 'parent' in 'field list': INSERT INTO
`children` (`name`, `parent`, `position`) VALUES ('Kid One',
'parent_1', 1)

I did find a workaround for this problem, but I don't like it and I'd
much prefer being able to simply use the name of the parent object in
the parent.yml file. Here's the workaround I used:
   parent_id: <%= parent.hash.abs %>

Which led me to a second problem in the IDs that are generated for the
child objects. They're simply sequential numbers, like this:
id  parent_id    name      created_at      updated_at
1  461483557    Kid One      2009-02-17 01:13:54    2009-02-17 01:13:54
2  461483557    Kid Two      2009-02-17 01:13:54    2009-02-17 01:13:54
3  461483557    Kid Three    2009-02-17 01:13:54    2009-02-17 01:13:54

I was expecting the id column to contain hashed values from
"parent1_child1", "parent1_child2", "parent1_child3" and so on, but
since they're not, I can't use my workaround when I create the
fixtures in the grandchildren.yml file.

Ideally, I'd like to be able to specify the belongs_to fixture object
by its label in the .yml file and not use my workaround at all. Though
it does concern me that sometimes fixtures seem to use the hashed
value of the label as an ID and sometimes just use a sequence
unrelated to the label.

If anyone could give me some idea of where I should look for the
problem, I'd really appreciate it.

Thank you,

Mark
MaD (Guest)
on 2009-02-17 14:11
(Received via mailing list)
it just tried it in a new rails project. foxy fixtures are working
fine for me. neither of your problems occurr:
- ids are hashed values.
- relationships in yml-files work

here is my fixture-code:

# products.yml
first:
  name: first

second:
  name: second

# pictures.yml
one:
  product: second

two:
  product: first


maybe you got some other problems in your real code ( the one you
posted looked quite ok).
markds75 (Guest)
on 2009-02-17 20:01
(Received via mailing list)
Okay, well here's the real code I'm dealing with (sorry if its long).
I'm adding surveys to a research project I've been working on, So I've
got three migration files, one to create the surveys, one to create
the survey questions, and another to create the possible survey
answers.

###_create_surveys.rb:

class CreateSurveys < ActiveRecord::Migration
  def self.up
    create_table :surveys do |t|
      t.boolean :required
      t.string :title
      t.datetime :go_live

      t.timestamps
    end
  end

  def self.down
    drop_table :surveys
  end
end


###_create_survey_answers.rb:

class CreateSurveyQuestions < ActiveRecord::Migration
  def self.up
    create_table :survey_questions do |t|
      t.integer :position
      t.text :question
      t.integer :survey_id
      t.string :answer_style

      t.timestamps
    end
  end

  def self.down
    drop_table :survey_questions
  end
end


###_create_survey_possible_answers:

class CreateSurveyPossibleAnswers < ActiveRecord::Migration
  def self.up
    create_table :survey_possible_answers do |t|
      t.integer :position
      t.text :answer
      t.integer :survey_question_id

      t.timestamps
    end
  end

  def self.down
    drop_table :survey_possible_answers
  end
end


And I've got 3 models to go with the new classes.

survey.rb:

class Survey < ActiveRecord::Base
  has_many :survey_questions, :order => :position
end


survey_questions.rb:

class SurveyQuestions < ActiveRecord::Base
  belongs_to :survey
  acts_as_list :scope => :survey

  has_many :survey_possible_answers
end


survey_possible_answers.rb:

class SurveyPossibleAnswers < ActiveRecord::Base
  belongs_to :survey_questions, :order => :position
  acts_as_list :scope => :survey_questions
end


And finally, here's the test data I was trying to use.

surveys.yml:

initial_survey:
  required: true
  title: Initial Survey
  go_live: 2009-01-01 00:00:00

past_weekly_1:
  required: false
  title: Past Weekly One
  go_live: 2009-02-01 00:00:00

past_weekly_2:
  required: false
  title: Past Weekly Two
  go_live: 2009-02-01 00:00:00

future_weekly_1:
  required: false
  title: Future Weekly One
  go_live: <%= Date.today.next.strftime( "%Y-%m-%d" ) %>

future_requred_1:
  required: true
  title: Future Required
  go_live: <%= Date.today.next.strftime( "%Y-%m-%d" ) %>


survey_questions.yml:

# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html

<%
    surveys = [ "initial_survey", "past_weekly_1", "past_weekly_2",
"future_weekly_1", "future_requred_1" ]
%>

<% surveys.each do |survey| %>

<%= survey %>_q1:
  position: 1
  question: My Question?
  survey: <%= survey %>

<%= survey %>_q2:
  position: 2
  question: My Question?
  survey: <%= survey %>

<%= survey %>_q3:
  position: 3
  question: My Question?
  survey: <%= survey %>

<% end %>


survey_possible_answers.yml:

<%
    surveys = [ "initial_survey", "past_weekly_1", "past_weekly_2",
"future_weekly_1", "future_requred_1" ]
    numQuestions = 3
%>

<% surveys.each do |survey| %>
    <% for i in (1..numQuestions) %>

<%= survey %>_q<%= i %>_a1:
  position: 1
  answer: Some Answer
  survey_question: <%= survey %>_q<%= i %>

<%= survey %>_q<%= i %>_a2:
  position: 2
  answer: Some Answer
  survey_question: <%= survey %>_q<%= i %>

<%= survey %>_q<%= i %>_a3:
  position: 3
  answer: Some Answer
  survey_question: <%= survey %>_q<%= i %>
    <% end %>
<% end %>



So .... after all that, I get errors like this when I try to run rake
test:units:

ActiveRecord::StatementInvalid: Mysql::Error: Unknown column
'survey_question' in 'field list': INSERT INTO
`survey_possible_answers` (`answer`, `survey_question`, `position`)
VALUES ('Some Answer', 'future_requred_1_q1', 1)
Matt J. (Guest)
on 2009-02-18 01:47
(Received via mailing list)
On Feb 17, 1:00 pm, markds75 <removed_email_address@domain.invalid> wrote:
> Okay, well here's the real code I'm dealing with (sorry if its long).
> I'm adding surveys to a research project I've been working on, So I've
> got three migration files, one to create the surveys, one to create
> the survey questions, and another to create the possible survey
> answers.
[snip]
> class SurveyQuestions < ActiveRecord::Base
>   acts_as_list :scope => :survey_questions
> end

The problem: the belongs_to here is going to fail. In the vast
majority of cases,
belongs_to should have a singular name. The code here won't ever work,
as you've
got the DB field (survey_question_id) named correctly, and it won't
match.

BTW, tiny typos like this are why I prefer to start by poking at the
models in console;
frequently, that will drive the first tests of the models, and if
you've got a typo it will
be very apparent...

--Matt J.
MaD (Guest)
on 2009-02-18 09:22
(Received via mailing list)
good morning,

matt's post did fix your problems, didn't it?

should be somethign like this then (no :order needed for
one :survey_question):

  class SurveyPossibleAnswers < ActiveRecord::Base
    belongs_to :survey_question
    acts_as_list :scope => :survey_question
  end
markds75 (Guest)
on 2009-02-18 09:51
(Received via mailing list)
Thanks Matt, that was the problem. I'll keep the console in mind next
time around... it never occurred to me to try that this time.

The Survey model didn't change. The corrected models are:

survey_question.rb:

class SurveyQuestion < ActiveRecord::Base
  belongs_to :survey
  acts_as_list :scope => :survey

  has_many :survey_possible_answers
end


survey_possible_answer.rb:

class SurveyPossibleAnswer < ActiveRecord::Base
  belongs_to :survey_question
  acts_as_list :scope => :survey_question
end

The migrations and fixture files didn't have to change.

Mark
This topic is locked and can not be replied to.