1

So this may be somewhat related to my question that I asked earlier, so here is a link to it, just in case.

So, currently I'm getting the error undefined method 'location' for #<Block:0x6503478>.

I've already gotten the has_one relation for cue working, but what seems to be the problem is the has_many relations with block_block and block_character.

The parameters being passed are:

{"utf8"=>"✓",
 "authenticity_token"=>"blahblahblah",
 "block"=>{"block_code"=>"1",
 "block_duration"=>"",
 "cue"=>"no",
 "cue_attributes"=>{"cue_code"=>"",
 "cue_type_code"=>"",
 "cue_description"=>"",
 "cue_method_code"=>""},
 "location_code"=>"1",
 "scene_code"=>"1",
 "block_description"=>"",
 "block_block"=>{"block_block_code"=>"",
 "primary_block_code"=>"",
 "secondary_block_code"=>"",
 "block_block_start"=>""},
 "block_character"=>{"block_character_code"=>"",
 "character_code"=>"",
 "block_code"=>"",
 "character_action"=>"",
 "character_motivation"=>""}},
 "blockblock"=>{"block"=>"no"},
 "blockblockdirect"=>{"blockdirect"=>"before"},
 "blockchar"=>{"character"=>"no"},
 "commit"=>"Create Block"}

Here is my form for block (views/block/_form.html.erb):

<%= form_for(@block) do |f| %>
  <% if @block.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(@block.errors.count, "error") %> prohibited this block from being saved:</h2>

      <ul>
      <% @block.errors.full_messages.each do |message| %>
        <li><%= message %></li>
      <% end %>
      </ul>
    </div>
  <% end %>

  <div class="field hidden">
    <%= f.label :block_code, class: "hidden" %><br>
    <%= f.text_field :block_code, class: "form-control hidden" %>
  </div>
  <div class="field">
    <%= f.label :block_duration %><br>
    <div class="input-group">
      <%= f.number_field :block_duration, class: 'text_field form-control', :step => 'any' %>
      <div class="input-group-addon">seconds</div>
    </div>
  </div>

  <div class="field">
    <%= label "cue", "Does this block have a cue associated with it?" %>
    <!-- Add whether it is specific/generic cue -->
    <%= radio_button_tag "block[cue]", "yes", false %> Yes
    <%= radio_button_tag "block[cue]", "no", true %> No
    <div class="field" id="cue_fields" style="display:none;">
      <%= f.fields_for :cue, @block.build_cue do |ff| %>
        <div class="field hidden">
          <%= ff.label :cue_code, class: "hidden" %><br>
          <%= ff.text_field :cue_code, class: "hidden" %>
        </div>
        <div class="field">
          <%= ff.label "Cue Type" %><br>
          <%= ff.collection_select(:cue_type_code, CueType.all, :cue_type_code, :cue_type_name, {prompt: "Select a cue type..."}, {class: "form-control"}) %>
        </div>
        <div class="field">
          <%= ff.label "Cue Description" %><br>
          <%= ff.text_area :cue_description, class: "form-control" %>
        </div>
        <div class="field">
          <%= ff.label "Cue Method" %><br>
          <%= ff.collection_select( :cue_method_code, CueMethod.all, :cue_method_code, :cue_method_name, {prompt: "Select a cue method..."}, {class: "form-control"}) %>
        </div>
      <% end %>
    </div>
  </div>


  <div class="field">
    <%= f.label "Location" %><br>
    <%= collection_select :block, :location_code, Location.all, :location_code, :location_name, {prompt: "Select a location..."}, {class: "form-control", required: true} %>
  </div>
  <div class="field">
    <%= f.label "Scene" %><br>
    <%= f.collection_select :scene_code, Scene.all, :scene_code, :actAndScene, {prompt: "Select a scene..."}, {class: "form-control", required: true} %>
  </div>
  <div class="field">
    <%= f.label "Block Description" %><br>
    <%= f.text_area :block_description, class: "form-control" %>
  </div>

  <!-- This needs work -->
  <div class="field">
    <%= label "blockblock", "Is this block associated with any other blocks?" %>
    <%= radio_button_tag "blockblock[block]", "yes", false %> Yes
    <%= radio_button_tag "blockblock[block]", "no", true %> No
    <div class="field" id="blockblock_fields" style="display:none;">
      <ol>
        <li>
          <%= label "blockdirect", "Does this block come directly before or after another block?" %>
          <%= radio_button_tag "blockblockdirect[blockdirect]", "before", true %> Before
          <%= radio_button_tag "blockblockdirect[blockdirect]", "after", false %> After
          <%= f.fields_for :block_block do |gg| %>
            <div class="field hidden">
              <%= gg.label :block_block_code, class: 'hidden' %><br>
              <%= gg.text_field :block_block_code, class: 'hidden' %>
            </div>
            <div class="field" id="blockblock_after_fields" style="display:none;">
              <%= gg.label "Primary Block Code" %><br>
              <%= gg.text_field :primary_block_code, class: 'form-control' %>
            </div>
            <div class="field" id="blockblock_before_fields">
              <%= gg.label "Secondary Block Code" %><br>
              <%= gg.text_field :secondary_block_code, class: 'form-control' %>
            </div>
            <div class="field">
              <%= gg.label "Block Start" %><br>
              <p><i>This field indicates the amount of time after the first block starts that the second block should begin, i.e. if you type "1" here, then the second block will start 1 second after the first block starts</i></p>
              <div class="input-group">
                <%= gg.number_field :block_block_start, class: 'text_field form-control', :step => 'any' %>
                <div class="input-group-addon">seconds</div>
              </div>
            </div>
          <% end %>
        </li>
      </ol>
    </div>
  </div>

  <!-- This needs work -->
  <div class="field">
    <%= label "character", "Are any characters associated with this block?" %>
    <%= radio_button_tag "blockchar[character]", "yes", false %> Yes
    <%= radio_button_tag "blockchar[character]", "no", true %> No
    <div class="field" id="character_fields" style="display:none;">
      <ol>
                <%= f.fields_for :block_character do |hh| %>
        <li>
          <div class="field hidden">
            <%= hh.label :block_character_code, class: 'hidden' %><br>
            <%= hh.text_field :block_character_code, class: 'hidden' %>
          </div>
          <div class="field">
            <%= hh.label "Character" %><br>
            <%= hh.collection_select :character_code, Character.all, :character_code, :character_name, {prompt: "Select a character..."}, {class: "form-control"} %>
          </div>
          <div class="field hidden">
            <%= hh.label :block_code, class: 'hidden' %><br>
            <%= hh.text_field :block_code, class: 'hidden' %>
          </div>
          <div class="field">
            <%= hh.label :character_action %><br>
            <%= hh.text_field :character_action, class: 'form-control' %>
          </div>
          <div class="field">
            <%= hh.label :character_motivation %><br>
            <%= hh.text_area :character_motivation, class: 'form-control' %>
          </div>
        </li>
      <% end %>
      </ol>
    </div>
  </div>

  <div class="actions">
    <%= f.submit "Create Block", class: "btn btn-primary" %>
  </div>
<% end %>

Additionally, here are the models associated with block, block_character, and block_block, respectively:

class Block < ActiveRecord::Base
    validates_presence_of :location
    validates_presence_of :scene

  has_one :cue
  has_many :block_blocks
  has_many :block_characters

  accepts_nested_attributes_for :cue, allow_destroy: true
  accepts_nested_attributes_for :block_blocks, allow_destroy: true
  accepts_nested_attributes_for :block_characters, allow_destroy: true

    attr_accessor :block_blocks
    attr_accessor :block_characters
end

class BlockBlock < ActiveRecord::Base
  belongs_to :block
end

class BlockCharacter < ActiveRecord::Base
  belongs_to :block
end

Here is the controller for block:

class BlocksController < ApplicationController
  before_action :set_block, only: [:show, :edit, :update, :destroy]

  # GET /blocks
  # GET /blocks.json
  def index
    @blocks = Block.all
  end

  # GET /blocks/1
  # GET /blocks/1.json
  def show
  end

  # GET /blocks/new
  def new
    @block = Block.new

    # Set block code as next integer after max block code.
    @block.block_code = (Block.maximum(:block_code).to_i.next).to_s(2)

  end

  # GET /blocks/1/edit
  def edit
  end

  # POST /blocks
  # POST /blocks.json
  def create
    @block = Block.new(block_params)

    respond_to do |format|
      if @block.save
        format.html { redirect_to @block, notice: 'Block was successfully created.' }
        format.json { render :show, status: :created, location: @block }
      else
        format.html { render :new }
        format.json { render json: @block.errors, status: :unprocessable_entity }
      end
    end
  end

  # PATCH/PUT /blocks/1
  # PATCH/PUT /blocks/1.json
  def update
    respond_to do |format|
      if @block.update(block_params)
        format.html { redirect_to @block, notice: 'Block was successfully updated.' }
        format.json { render :show, status: :ok, location: @block }
      else
        format.html { render :edit }
        format.json { render json: @block.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /blocks/1
  # DELETE /blocks/1.json
  def destroy
    @block.destroy
    respond_to do |format|
      format.html { redirect_to blocks_url, notice: 'Block was successfully destroyed.' }
      format.json { head :no_content }
    end
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_block
      @block = Block.find(params[:id])
    end

    # Never trust parameters from the scary internet, only allow the white list through.
    def block_params
      params.require(:block).permit(:block_code, :block_duration, :cue_code, :location_code, :scene_code, :block_description, :cue_attributes => [:id, :cue_code, :cue_type_code, :cue_description, :cue_method_code], :block_block_attributes => [:id, :block_block_code, :primary_block_code, :secondary_block_code, :block_block_start], :block_character_attributes => [:id, :block_character_code, :character_code, :block_code, :character_action, :character_motivation])
    end
end

And finally, the migrations I added for id and foreign_key for both block_block and block_character:

class AddBelongsToToBlockBlocks < ActiveRecord::Migration
  def change
    add_reference :block_blocks, :block, index: true
    add_foreign_key :block_blocks, :blocks
  end
end

class AddBelongsToToBlockCharacters < ActiveRecord::Migration
  def change
    add_reference :block_characters, :block, index: true
    add_foreign_key :block_characters, :blocks
  end
end

Honestly, thank you all so much for your help through this, I am by no means an advanced Rails user and this has all been amazingly helpful. Please let me know if you need any more information!

UPDATE 1

So I changed the following in block.rb (the model file), as suggested by Vijay (thanks so much!!!):

class Block < ActiveRecord::Base
    validates_presence_of :location_code
    validates_presence_of :scene_code

  has_one :cue
  has_many :block_blocks
  has_many :block_characters

  accepts_nested_attributes_for :cue, allow_destroy: true
  accepts_nested_attributes_for :block_blocks, allow_destroy: true
  accepts_nested_attributes_for :block_characters, allow_destroy: true

    attr_accessor :block_blocks
    attr_accessor :block_characters
end

At this point, the block saves (and appears in the index view), but the block_block and block_character do not do so. There is no associated error however...

UPDATE 2

This is currently what the params submitted look like:

Params submitted

Which is odd because it says that cue, block_block, and block_character are unpermitted parameters, even though, in the controller they are:

def block_params
  params.require(:block).permit(:block_code, :block_duration, :cue_code, :location_code, :scene_code, :block_description, :cue_attributes => [:id, :cue_code, :cue_type_code, :cue_description, :cue_method_code], :block_block_attributes => [:id, :block_block_code, :primary_block_code, :secondary_block_code, :block_block_start], :block_character_attributes => [:id, :block_character_code, :character_code, :block_code, :character_action, :character_motivation])
end
1
  • For cue unpermitted params you have added :cue_code instead of cue in strong params methos block_params Commented Apr 18, 2016 at 5:24

2 Answers 2

2

Are you triggering the error in the validation?

validates_presence_of :location

From your code it looks like it should be

validates_presence_of :location_code
Sign up to request clarification or add additional context in comments.

2 Comments

Looks like you'll have the same issue with ':scene' validation
I changed both of those (...I'm an idiot), but the issue continuing/spurring from this is the fact that neither block_character or block_block save to their respective tables...
1

Not sure why you've added these in Rails 4

    attr_accessor :block_blocks
    attr_accessor :block_characters

Try removing them and see if they are interfering with the controller (I'm guessing, but happy to play if you put up a jsfiddle)

4 Comments

I tried removing them, but they still do not save in their respective tables. I'm super sorry, but I'm afraid I'm not exactly sure how to get Rails running in jsfiddle?
Has your params submitted changed at all? Don't see block_block_attributes anywhere (but cue_attributes exist). You may want to check that your nested form is set up the right way and that your controller isn't stripping them out. Probably best to do in the console.
I updated (Update 2) the question with a picture of parameters passed and the controller parameters. Thank you so so so much for all of your help!!!!!
You're not creating the block_block_attributes => or block_character_attributes params (although you are with cue). Take a look at your fields_for settings...noticed you're not passing in an @ in the fields_for line for block_block or block_character. Also, you have a plural in your params for block_block but not block_character. Finally, cue is stripped because it isn't connected with cue_attributes nor defined in your params

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.