1

I have a rails app with the following:

class Habit < ActiveRecord::Base
  has_many :habit_journals
  has_many :road_blocks

class RoadBlock < ActiveRecord::Base
  belongs_to :habit
  has_many :road_block_histories


class HabitJournal < ActiveRecord::Base
   belongs_to :habit
   end

I have a form that creates HabitJournals, although within this form I am trying to create RoadBlockHistories (which is just a rating on a RoadBlock over time)

I can't seem to work out how to create the form for this.

Habits have many HabitJournals and RoadBlocks. RoadBlockHistories don't relate directly to HabitJournals, but I would still like to capture these at the same form submission.

Any help would be appreciated.

Cheers M


Sorry, I realised I need to add additional info. This is Rails 4.1

A user will create a habit such as 'Be healthier'. They then will create a number of road blocks to this habit such as 'Eating chocolate at night' and 'sleeping in instead of exercising'.

When the user views a habit they can add a journal entry (an update of how they are doing establishing the habit).

When adding a journal entry I'd like the user to be displayed with all their "road blocks" with a dropdown to select a rating (which is a mark out of 10 of how they are going with that road block). This rating would create a road_block_history object.

Hopefully this clarifies.

Cheers M

4
  • Which Rails version you are using? Commented Jul 22, 2014 at 7:12
  • accepts_nested_attributes Commented Jul 22, 2014 at 7:14
  • 1
    I guess it would be easy when you create a form with habit,then you can easily nest the road_block_histories. Commented Jul 22, 2014 at 7:18
  • I updated with additional info. Commented Jul 22, 2014 at 7:45

1 Answer 1

1

Objects

I understand what you want - still trying to consider how to get it working.

Something you need to consider is the nature of Ruby on Rails (Ruby in particular). Ruby is an object orientated language, meaning everything it does is based around objects.

The problem you have is the object you're trying to create ("RoadBlockHistories") has no direct association to your "parent" object that you're trying to create ("HabitJournals").


accepts_nested_attributes_for

The "way" you'd surmount this problem typically is to use the accepts_nested_attributes_for method - basically allowing you to pass data from a parent model to a child.

The important thing to note here is that this only works if your models are directly associated, IE that it's either a has_many, belongs_to or has_many :through for the model you're trying to create.

This is not magic - it's core Ruby. If you have a model you're trying to populate, if it has associated data, you'll be able to send that through your original model. However, as the language is object orientated, you cannot just populate an unrelated object without having that association


Fix

From what you've written, I would certainly look at treating the two forms as separate data objects (IE not associating them)

Perhaps you could do this (although it will need tweaking):

#app/models/habit.rb
class Habit < ActiveRecord::Base
  has_many :habit_journals
  has_many :road_blocks
end

#app/models/road_block.rb
class RoadBlock < ActiveRecord::Base
  belongs_to :habit
  has_many :road_block_histories
end

#app/models/habit_journal.rb
class HabitJournal < ActiveRecord::Base
   belongs_to :habit
   has_many :road_blocks
end

Although this is not tested, nor do I think it would work, the reason I included this is to give you the idea about how you could pass an "unassociated" object through to Rails.

You can actually pass objects / data through others - so you could actually use something like the following:

#app/controllers/habit_journals_controller.rb
Class HabitJournalsController < ApplicationController
   def new
       @habit_journal = HabitJournal.new
       @habit_journal.road_blocks.build.road_block_histories.build #-> again, not sure if will work
   end

   def create
       @habit_journal = HabitJournal.new(habit_journal_params)
       @habit_journal.save
   end

   private

   def habit_journal_params 
       params.require(:habit_journal).permit(:x, :y, :z, road_blocks_attributes: [road_block_histories_attributes:[] ])
   end
end

If the associations are correct, this should allow you to create the following form:

#app/views/habit_jorunals/new.html.erb
<%= form_for @habit_journal do |f| %>
   <%= f.fields_for :road_blocks do |rb| %>
       <%= rb.fields_for :road_blocks_histories do |h| %>
           <%= h.text_field :rating %>
       <% end %>
   <% end %>
<% end %>
Sign up to request clarification or add additional context in comments.

5 Comments

You have a typo here in this line @habit_journal - HabitJournal.new(habit_journal_params) :)
And road_block_attributes should be road_blocks_attributes :)
Thanks Rich, I've been working through this and now for form build properly. Although when I submit the form I get an error "Cannot modify association 'HabitJournal#road_blocks' because the source reflection class 'RoadBlock' is associated to 'Habit' via :has_many." Any comment or advise?
Hmmmmm - let me have a a little think about it :) Thanks for the update!
To clarify, I did the following: class HabitJournal < ActiveRecord::Base belongs_to :habit has_many :road_blocks, through: :habit accepts_nested_attributes_for :road_blocks end

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.