Nested attributes in Ruby on Rails not saving - ruby-on-rails

I'll preface this by saying I've looked at the following answers and still have not hit a solution that works (however, given the possibility I might have overlooked something, I'm including them for reference):
Ruby on Rails - Not saving User - Nested Attributes and Nested Forms
Nested Attributes in ruby on rails
Ruby on Rails nested attributes not saving into database?
Nested attributes not saving in database? Does not display values - Ruby on Rails
Description of problem: I have a form Block with a nested form for Cue. The form renders correctly and the Block saves correctly, but the Cue does not appear in the Cue table, i.e. the Cue isn't saving when the Block is submitted. I'm using Rails 4.2.5.1. I also don't get any errors on submit, making this a bit difficult to diagnose.
Code:
_form.html.erb - block
<%= 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>Does this block have a cue associated with it?</label>
<input type="radio" name="cue" value="cueYes" data-type="cueYes" data-radio="cue"> Yes
<input type="radio" name="cue" value="cueNo" data-type="cueNo" data-radio="cue" checked> No
<div class="field" id="cueYes">
<%= f.fields_for :cues 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"} %>
</div>
<div class="field">
<%= f.label "Scene" %><br>
<%= collection_select :block, :scene_code, Scene.all, :scene_code, :actAndScene, {prompt: "Select a scene..."}, {class: "form-control"} %>
</div>
<div class="field">
<%= f.label "Block Description" %><br>
<%= f.text_area :block_description, class: "form-control" %>
</div>
<div class="actions">
<%= f.submit "Create Block", class: "btn btn-primary" %>
</div>
<% end %>
blocks_controller.rb
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, :cues_attributes => [:cue_code, :cue_type_code, :cue_description, :cue_method_name])
end
end
block.rb
class Block < ActiveRecord::Base
has_one :cue, -> { where processed: true }
accepts_nested_attributes_for :cue, allow_destroy: true
end
cue.rb
class Cue < ActiveRecord::Base
belongs_to :block
end
cues_controller.rb
class CuesController < ApplicationController
before_action :set_cue, only: [:show, :edit, :update, :destroy]
# GET /cues
# GET /cues.json
def index
#cues = Cue.all
end
# GET /cues/1
# GET /cues/1.json
def show
end
# GET /cues/new
def new
#cue = Cue.new
# Set cue code as next integer after max cue code.
#cue.cue_code = (Cue.maximum(:cue_code).to_i.next).to_s(2)
end
# GET /cues/1/edit
def edit
end
# POST /cues
# POST /cues.json
def create
#cue = Cue.new(cue_params)
respond_to do |format|
if #cue.save
format.html { redirect_to #cue, notice: 'Cue was successfully created.' }
format.json { render :show, status: :created, location: #cue }
else
format.html { render :new }
format.json { render json: #cue.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /cues/1
# PATCH/PUT /cues/1.json
def update
respond_to do |format|
if #cue.update(cue_params)
format.html { redirect_to #cue, notice: 'Cue was successfully updated.' }
format.json { render :show, status: :ok, location: #cue }
else
format.html { render :edit }
format.json { render json: #cue.errors, status: :unprocessable_entity }
end
end
end
# DELETE /cues/1
# DELETE /cues/1.json
def destroy
#cue.destroy
respond_to do |format|
format.html { redirect_to cues_url, notice: 'Cue was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_cue
#cue = Cue.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def cue_params
params.require(:cue).permit(:cue_code, :cue_type_code, :cue_description, :cue_method_code)
end
end
If anything else is needed, please let me know! (Also sorry if the formatting isn't great).
Any help is much appreciated!! Thanks!!
UPDATE 1
I'm currently getting the error undefined method 'encoding' for 7:Fixnum on the line if #block.save in blocks_controller.rb (above). I have changed the following things based on the answer given by IngoAlbers (below) and the answer found here.
I've changed the following things:
blocks_controller.rb
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])
end
_form.html.erb - blocks
<%= f.fields_for :cue, #block.build_cue do |ff| %>
block.rb
class Block < ActiveRecord::Base
has_one :cue
accepts_nested_attributes_for :cue, allow_destroy: true
end
Thanks so much for the help so far! I think I'm really close!
UPDATE 2
So I've added block_id as an attribute to Cue and run the following two migrations:
class AddBlockIdToCues < ActiveRecord::Migration
def self.up
add_column :cues, :block_id, :binary
end
def self.down
remove_column :cues, :block_id
end
end
class AddBelongsToToCues < ActiveRecord::Migration
def change
add_reference :cues, :blocks, index: true
add_foreign_key :cues, :blocks
end
end
I'm still getting the error undefined method 'encoding' for 7:Fixnum on the line if #block.save in the blocks_controller.rb.

The problem should be in your fields_for. It should probably be:
<%= f.fields_for :cue do |ff| %>
Not cues since it is only one. Then you need to build the cue. This can be done either in controller or in the view directly, for example like this:
<%= f.fields_for :cue, #block.build_cue do |ff| %>
In your block params you then also need to change it to cue_attributes, and also allow id.
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_name])
end
You can also read a lot more information here:
http://guides.rubyonrails.org/form_helpers.html#nested-forms
Regarding your second Update:
Your first migration adds a column block_id of type binary. It should definitely be integer instead. That said, you don't even need the first migration at all, because your second migration will handle all of it correctly, if you change blocks to block in add_reference. It should look like this:
class AddBelongsToToCues < ActiveRecord::Migration
def change
add_reference :cues, :block, index: true
add_foreign_key :cues, :blocks
end
end
The add_reference needs to add a reference to one block not multiple. This will then create the right column for you.
See also: http://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/SchemaStatements.html#method-i-add_reference

Related

Rails link_to path

I am trying to make an app in Rails 4.
I have 3 models: Project, Project_Question, Project_Answer
The associations are:
Project:
has_many :project_questions
and accepts nested attributes for project questions.
Project Question:
belongs_to :project
has_one :project_answer
and accepts nested attributes for Project Answers.
My routes are nested as follows:
resources :projects do
resources :project_questions do
resources :project_answers
end
end
In my Project Questions partial, I want a link to answer the question. I've tried:
<%= link_to 'Answer this question', new_project_project_question_project_answer_path(:project_question_id => project_question.id) %>
I have a route with that name in my routes file, but I'm getting this error message:
undefined local variable or method `project_question' for #<#<Class:0x0000010742b9d8>:0x0000010f810b68>
What should go in the brackets?
View:
<div class="containerfluid">
<div class="row">
<div class="col-md-10 col-md-offset-1">
<% #project.project_questions.each do |singleQuestion| %>
<div class="categorytitle">
<%= singleQuestion.title %>
</div>
<div class="generaltext">
<%= singleQuestion.try(:content) %>
</div>
<span class="editproject">
<% if current_user.id == #project.creator_id %>
<%= link_to 'Answer this question', new_project_project_questions_project_answer_path(:project_question_id => project_question.id) %>
<% end %>
</span>
<% end %>
</div>
</div>
</div>
Project Question controller:
class ProjectQuestionsController < ApplicationController
before_action :set_project_question, only: [:show, :edit, :update, :destroy]
# GET /project_questions
# GET /project_questions.json
def index
#project_questions = ProjectQuestion.all
end
# GET /project_questions/1
# GET /project_questions/1.json
def show
end
# GET /project_questions/new
def new
#project_question = ProjectQuestion.new
#project = Project.find(params[:project_id])
# #project_id = params[:project_id]
#project_question.project_answers[0] = ProjectAnswer.new
end
# GET /project_questions/1/edit
def edit
end
# POST /project_questions
# POST /project_questions.json
def create
#project_question = ProjectQuestion.new(project_question_params)
#project_question.project_id = project_question_params[:project_id]
respond_to do |format|
if #project_question.save
format.html { redirect_to project_url(Project.find(project_question_params[:project_id])), notice: 'Project question was successfully created.' }
format.json { render action: 'show', status: :created, location: #project_question }
else
format.html { render action: 'new' }
format.json { render json: #project_question.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /project_questions/1
# PATCH/PUT /project_questions/1.json
def update
respond_to do |format|
if #project_question.update(project_question_params)
format.html { redirect_to #project_question, notice: 'Project question was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #project_question.errors, status: :unprocessable_entity }
end
end
end
# DELETE /project_questions/1
# DELETE /project_questions/1.json
def destroy
#project_question.destroy
respond_to do |format|
format.html { redirect_to project_questions_url }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_project_question
#project_question = ProjectQuestion.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def project_question_params
params[:project_question].permit(:id, :title, :content, :project_id, :user_id,
project_answer_atttibutes: [:id, :answer, :project_question_id, :user_id]
)
end
end
When you run rake routes, you will find this one
new_project_project_question_project_answer GET /projects/:project_id/project_questions/:project_question_id/project_answers/new(.:format) project_answers#new
That means it requires :project_id and :project_question_id as keys.
This should work
<%= link_to 'Answer this question', new_project_project_question_project_answer_path(:project_id => #project.id, :project_question_id => singleQuestion.id) %>
Notice new_project_project_question_project_answer_path not new_project_project_questions_project_answer_path
Your link_to should be something below
<%= link_to 'Answer this question', new_project_project_questions_project_answer_path(:project_id => #project.id, :project_question_id => singleQuestion.id) %>
View will look like below
<div class="containerfluid">
<div class="row">
<div class="col-md-10 col-md-offset-1">
<% #project.project_questions.each do |singleQuestion| %>
<div class="categorytitle">
<%= singleQuestion.title %>
</div>
<div class="generaltext">
<%= singleQuestion.try(:content) %>
</div>
<span class="editproject">
<% if current_user.id == #project.creator_id %>
<%= link_to 'Answer this question', new_project_project_questions_project_answer_path(:project_question_id => singleQuestion.id) %>
<% end %>
</span>
<% end %>
</div>
</div>
</div>
Check that params
def project_question_params
params[:project_question].permit(:id, :title, :content, :project_id, :user_id,
project_answer_atttibutes: [:id, :answer, :project_question_id, :user_id]
)
end
There is project_id
and you did not pass it in link_to
so it thwos new errormissing required keys: [:project_id]

Rendering partial in Rails - nested objects

I am trying to render a partial in my rails app.
I have done this successfully with other partials, but the difference between those that worked and this one is that this partial belongs to a nested model. It is nested inside the model's view that I am trying to use to render the partial.
I have two models, Project and Project_question.
Project has many project questions and accepts nested attributes for project question.
Project question belongs to Project.
My routes are:
resources :projects do
resources :project_questions do
resources :project_answers
end
end
My project question controller has:
class ProjectQuestionsController < ApplicationController
before_action :set_project_question, only: [:show, :edit, :update, :destroy]
# GET /project_questions
# GET /project_questions.json
def index
#project_questions = ProjectQuestion.all
end
# GET /project_questions/1
# GET /project_questions/1.json
def show
end
# GET /project_questions/new
def new
#project_question = ProjectQuestion.new
#project = Project.find(params[:project_id])
# #project_id = params[:project_id]
#project_question.project_answers[0] = ProjectAnswer.new
end
# GET /project_questions/1/edit
def edit
end
# POST /project_questions
# POST /project_questions.json
def create
#project_question = ProjectQuestion.new(project_question_params)
#project_question.project_id = project_question_params[:project_id]
respond_to do |format|
if #project_question.save
format.html { redirect_to project_url(Project.find(project_question_params[:project_id])), notice: 'Project question was successfully created.' }
format.json { render action: 'show', status: :created, location: #project_question }
else
format.html { render action: 'new' }
format.json { render json: #project_question.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /project_questions/1
# PATCH/PUT /project_questions/1.json
def update
respond_to do |format|
if #project_question.update(project_question_params)
format.html { redirect_to #project_question, notice: 'Project question was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #project_question.errors, status: :unprocessable_entity }
end
end
end
# DELETE /project_questions/1
# DELETE /project_questions/1.json
def destroy
#project_question.destroy
respond_to do |format|
format.html { redirect_to project_questions_url }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_project_question
#project_question = ProjectQuestion.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def project_question_params
params[:project_question].permit(:id, :title, :content, :project_id, :user_id,
project_answer_atttibutes: [:id, :answer, :project_question_id, :user_id]
)
end
end
My project question form has:
<%= simple_form_for [#project, #project_question] do |f| %>
<%= f.input :project_id, as: :hidden, input_html: {value: #project.id} %>
<%= f.input :title, label: 'Question:', :label_html => {:class => 'question-title'}, placeholder: 'Type your question here', :input_html => {:style => 'width: 100%', :rows => 4, class: 'response-project'} %>
<%= f.input :content, label: 'Is there any context or other information?', :label_html => {:class => 'question-title'}, placeholder: 'Context might help to answer your question', :input_html => {:style => 'width: 100%', :rows => 5, class: 'response-project'} %>
<br><br><br>
<%= f.button :submit, 'Send!', :class => "cpb" %>
My project question partial has:
</div>
<div class="generaltext">
<%= #project.project_question.try(:content) %>
</div>
Inside my project#show, I try to render the protect question partial as follows:
<%= render 'project_questions/pqps' %>
and the project_questions/_pqps.html.erb file contains:
<div class="containerfluid">
<div class="row">
<div class="col-md-10 col-md-offset-1">
<div class="categorytitle">
<%= #project.project_question.title %>
</div>
<div class="generaltext">
<%= #project.project_question.try(:content) %>
</div>
<span class="editproject">
<% if current_user.id == #project.creator_id %>
<%= link_to 'Answer this question', new_project_question_project_answer_path(:project_quesetion_id => #project_question.id) %>
<% end %>
</span>
</div>
</div>
</div>
The error message I get when I try is:
undefined method `project_question' for #<Project:0x0000010d8bad40>
My problem was the has_many relationship between project and project questions. I had to make a loop to show each question.
This worked for me:
<% #project.project_questions.each do |singleQuestion| %>
<div class="categorytitle">
<%= singleQuestion.title %>
</div>
<div class="generaltext">
<%= singleQuestion.try(:content) %>
</div>

Basic Rails - how do automatically assign a new database entry to an associated entry it belongs to?

I'd like to automatically associate a new database entry with the database entry it belongs to without having to make a choice while on the form as the user can only come from the category page, so that once you're in a category and you decide to make a new entry within that category, the newly created entry is automatically within that category upon submission. Can anyone offer any help?
My models are as follows:
class Category < ActiveRecord::Base
has_many :guides
end
class Guide < ActiveRecord::Base
belongs_to :user
belongs_to :category
has_many :ratings
def average_rating
average = ratings.inject(0.0){ |sum, el| sum + el.value }.to_f / ratings.size
average.round(2)
end
end
The link to create the new guide for the category is pretty standard, though I thought that adding an instance variable might automatically associate the entry with the category though it doesn't:
<%= link_to 'New Guide', new_guide_path(#category) %>
Here is the controller for the guide:
class GuidesController < ApplicationController
before_action :set_guide, only: [:show, :edit, :update, :destroy]
# GET /guides
# GET /guides.json
def index
#guides = Guide.all
end
# GET /guides/1
# GET /guides/1.json
def show
end
# GET /guides/new
def new
#guide = Guide.new
end
# GET /guides/1/edit
def edit
end
# POST /guides
# POST /guides.json
def create
#guide = Guide.new(guide_params)
respond_to do |format|
if #guide.save
format.html { redirect_to #guide, notice: 'Guide was successfully created.' }
format.json { render :show, status: :created, location: #guide }
else
format.html { render :new }
format.json { render json: #guide.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /guides/1
# PATCH/PUT /guides/1.json
def update
respond_to do |format|
if #guide.update(guide_params)
format.html { redirect_to #guide, notice: 'Guide was successfully updated.' }
format.json { render :show, status: :ok, location: #guide }
else
format.html { render :edit }
format.json { render json: #guide.errors, status: :unprocessable_entity }
end
end
end
# DELETE /guides/1
# DELETE /guides/1.json
def destroy
#guide.destroy
respond_to do |format|
format.html { redirect_to guides_url, notice: 'Guide was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_guide
#guide = Guide.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def guide_params
params.require(:guide).permit(:name, :category_id, :user_id, :stepOneText, :stepOnePhoto, :stepTwoText, :stepTwoPhoto, :stepThreeText, :stepThreePhoto)
end
end
Form is pretty standard too, is there anything I should put in here to automatically assign it to the category entry it belongs to?
<%= form_for(#guide) do |f| %>
<% if #guide.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#guide.errors.count, "error") %> prohibited this guide from being saved:</h2>
<ul>
<% #guide.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :name %>
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :stepOneText %>
<%= f.text_field :stepOneText %>
</div>
<div class="field">
<%= f.label :stepOnePhoto %>
<%= f.text_field :stepOnePhoto %>
</div>
<div class="field">
<%= f.label :stepTwoText %>
<%= f.text_field :stepTwoText %>
</div>
<div class="field">
<%= f.label :stepTwoPhoto %>
<%= f.text_field :stepTwoPhoto %>
</div>
<div class="field">
<%= f.label :stepThreeText %>
<%= f.text_field :stepThreeText %>
</div>
<div class="field">
<%= f.label :stepThreePhoto %>
<%= f.text_field :stepThreePhoto %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Seems to me that you could go for something like a nested route here :
resources :categories do
resources :guides
end
and then use your new route
<%= link_to 'New Guide', new_category_guide_path(#category) %>
This should make it easier to get the guide's category back when getting the form back.
Assuming that you have a column on your guide table that stores category ID, and your routes are nested as has been recommended, you should be able to add
#guide.category_id = #category.id
To your guides controller create action. And in your form change the first line to
<%= form_for[#category, #guide] do |f| %>
Now this should work
<%= link_to 'new guide', new_category_guide_path(#category) %>
And the current category should be assigned to your guide when it's created.

Why is my Rails hidden_field not picking up any value when all other fields work fine?

I have a model for a "timeline_event" which belongs_to a sales_opportunity. For example it could be "call the prospect" or similar, with a due_date, activity_details (optional), and a checkbox to say whether it's complete or not. This works fine. I can add new timeline_events to the database via a modal on the sales_opportunity page, which also works fine. However when I try to edit the timeline_event (via the timeline_events edit controller action) the hidden_field for sales_opportunity_id refuses to pick up the value (it has no value whatsoever). Even when I try to force a value:
<%= f.hidden_field :sales_opportunity_id, :value => #sales_opportunity.id %>
It won't add any value to the hidden_field. I've tried moving the field around within the form group, but nothing seems to work. I have other forms that are similar in my model that work fine, but for some reason this isn't working - can anyone help please?
My Form:
<%= form_for(#timeline_event, :html => {:class => "form-horizontal"}) do |f| %>
<div class="form-group">
<%= f.hidden_field :sales_opportunity_id %>
<%= f.label :activity, :class => "col-md-4 control-label" %>
<div class ="col-md-8">
<%= f.text_field :activity, :placeholder => "Enter activity details" %>
</div>
</div>
<div class="form-group">
<%= f.label :due_date, :class => "col-md-4 control-label" %>
<div class ="col-md-8">
<div class='input-group date' id='datetimepicker' data-date-format="YY.MM.DD">
<%= f.text_field :due_date, class: "form-control", data: { date_format: 'YYYY/MM/DD' }, :placeholder => "YYYY/MM/DD" %>
<span class="input-group-addon">
<span class="glyphicon glyphicon-calendar"></span>
</span>
</div>
</div>
</div>
<div class="form-group">
<%= f.label :event_notes, 'Activity Details', :class => "col-md-4 control-label" %>
<div class ="col-md-8">
<%= f.text_area(:event_notes, :placeholder => "Put any notes about the activity here") %>
</div>
</div>
<div class="col-md-6 col-md-offset-4">
<div class="checkbox input">
<label>
<%= f.check_box :completed %> Task Completed?
</label>
</div>
<br>
</div>
<%= #sales_opportunity.id %>
<%= f.submit "Save", class: "btn btn-large btn-success" %>
<% end %>
*Note - I include the line <%= #sales_opportunity.id %> here and this does output the correct sales_opportunity_id for the timeline_event. All other fields (activity, due_date, completed) are populated with the information of the timeline_event I'm trying to edit.
Timeline_Events_Controller:
class TimelineEventsController < ApplicationController
before_action :set_timeline_event, only: [:show, :edit, :update, :destroy]
before_action :signed_in_user, only: [:edit, :update, :show, :index]
before_action :correct_org, only: [:edit, :update, :show, :index]
# GET /timeline_events
# GET /timeline_events.json
def index
#timeline_events = TimelineEvent.all
end
# GET /timeline_events/1
# GET /timeline_events/1.json
def show
end
# GET /timeline_events/new
def new
#timeline_event = TimelineEvent.new(sales_opportunity_id: params[:sales_opportunity_id])
end
# GET /timeline_events/1/edit
def edit
#timeline_event = TimelineEvent.find(params[:id])
#sales_opportunity = #timeline_event.sales_opportunity
end
# POST /timeline_events
# POST /timeline_events.json
def create
#timeline_event = TimelineEvent.new(timeline_event_params)
#sales_opportunity = #timeline_event.sales_opportunity
respond_to do |format|
if #timeline_event.save
format.html { redirect_to #timeline_event.sales_opportunity, :flash => {:success => 'Timeline event was successfully created.'} }
format.json { render :show, status: :created, location: #timeline_event }
format.js
else
format.html { render :new }
format.json { render json: #timeline_event.errors, status: :unprocessable_entity }
format.js { render json: #sales_opportunity.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /timeline_events/1
# PATCH/PUT /timeline_events/1.json
def update
respond_to do |format|
if #timeline_event.update(timeline_event_params)
format.html { redirect_to #timeline_event.sales_opportunity, :flash => {:success => 'Timeline event was successfully updated.'} }
format.json { render :show, status: :ok, location: #timeline_event }
else
format.html { render :edit }
format.json { render json: #timeline_event.errors, status: :unprocessable_entity }
end
end
end
# DELETE /timeline_events/1
# DELETE /timeline_events/1.json
def destroy
#timeline_event.destroy
respond_to do |format|
format.html { redirect_to timeline_events_url, :flash => {:success => 'Timeline event was successfully destroyed.'} }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_timeline_event
#timeline_event = TimelineEvent.find(params[:id])
end
def timeline_event_params
params.require(:timeline_event).permit(:sales_opportunity_id, :due_date, :activity, :completed, :event_notes)
end
#before filters
def signed_in_user
unless signed_in?
store_location
redirect_to signin_url, notice: "Please sign in." unless signed_in?
end
end
def correct_org
timeline_org = #timeline_event.sales_opportunity.user.organization
#user = current_user
if #user.organization_id == timeline_org.id
else
redirect_to root_url, notice: "You are not permitted to visit that page. Please create an account or sign in"
end
end
end
My timeline_event model:
class TimelineEvent < ActiveRecord::Base
belongs_to :sales_opportunity
validates :activity, presence: true
validates :due_date, presence: true
validates :sales_opportunity_id, presence: true
end
I can only imagine this is some syntax error or other stupid error on my part, because I just can't see anything wrong with the code (it's identical to all other forms on my site). Can anyone spot where I'm going wrong here please?
Thanks!
I disagree with #smathy as you indeed can explicitly pass a value to a hidden_field tag like you have done.
However, that's not even necessary because you are doing a circular assignment. By that I mean you are declaring #sales_opportunity and assigning it the value of #timeline_event.sales_opportunity in the edit action of your controller.
You then go into the view and try to assign #timeline_event.sales_opportunity back to #sales_opportunity. That's circular logic.
If the sales_opportunity for the timeline_event you are editing is already present, and you aren't wanting to allow the user to edit it, why include it in the form at all? Delete the #sales_opportunity instance variable from the edit action in the controller, and just remove the hidden field entirely from the view.
See if doing that makes it work as desired.
The form_for field helpers don't work like that, they don't take a :value key in the options. Basically the name of the field must correspond to a method on the object you've passed into form_for (in your case #timeline_event), and that's where the form will get the value from.
If you want to provide your own field and value, then use the _tag family of helpers, eg.:
<%= hidden_field_tag :name_of_field, #sales_opportunity.id %>
Or use f.fields_for to create a sub-field (usually in combination with accepts_nested_attributes_for)

acts_as_taggable issue - Everything looks almost fine

I have just followed step by step this other question, but my app is still giving me some errors regarding tagging (rails 4)
Error that Im experiencing is: Desktop/hack/app/controllers/jacks_controller.rb:85: syntax error, unexpected end-of-input, expecting keyword_end end ^
I have already re-intended as suggested in the chat, but nothing changed.
Code for reference
I have no associations between my models, (in the link that I have referred, there are associations)
jack form
<%= form_for(#jack) do |f| %>
<% if #jack.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#jack.errors.count, "error") %> prohibited this jack from being saved: </h2>
<ul>
<% #jack.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :title %><br>
<%= f.text_field :title %>
</div>
<div class="field">
<%= f.label :description %><br>
<%= f.text_area :description %>
</div>
<div class="field">
<%= f.label :tag_list, "Tags (separated by comma)" %><br>
<%= f.text_field :tag_list %>
</div>
<div class="field">
<%= f.label :picture %><br>
<%= f.text_field :picture %>
</div>
<div class="actions">
<%= f.submit %>
jack.rb
class Jack < ActiveRecord::Base
acts_as_taggable_on :tags
end
Routes
Rails.application.routes.draw do
get 'tagged/index'
root :to => redirect('/jacks')
get 'about' => "about#info"
get 'submit' => "jacks#create"
resources :jacks
match 'tagged', to: 'jacks#tagged', :as => 'tagged', via: 'get'
resources :users
jack active helper
module JacksHelper
include ActsAsTaggableOn::TagsHelper
end
And controller
class JacksController < ApplicationController
before_action :set_jack, only: [:show, :edit, :update, :destroy]
# GET /jacks
# GET /jacks.json
def index
if params [:tag]
#jacks = Jack.tagged_with(params[:tag])
else
#jacks = Jack.all
end
# GET /jacks/1
# GET /jacks/1.json
def show
end
# GET /jacks/new
def new
#jack = Jack.new
end
# GET /jacks/1/edit
def edit
end
# POST /jacks
# POST /jacks.json
def create
#jack = Jack.new(jack_params)
respond_to do |format|
if #jack.save
format.html { redirect_to #jack, notice: 'Jack was successfully created.' }
format.json { render :show, status: :created, location: #jack }
else
format.html { render :new }
format.json { render json: #jack.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /jacks/1
# PATCH/PUT /jacks/1.json
def update
respond_to do |format|
if #jack.update(jack_params)
format.html { redirect_to #jack, notice: 'Jack was successfully updated.' }
format.json { render :show, status: :ok, location: #jack }
else
format.html { render :edit }
format.json { render json: #jack.errors, status: :unprocessable_entity }
end
end
end
# DELETE /jacks/1
# DELETE /jacks/1.json
def destroy
#jack.destroy
respond_to do |format|
format.html { redirect_to jacks_url, notice: 'Jack was successfully destroyed.' }
format.json { head :no_content }
end
end
def tagged
if params[:tag].present?
#jacks = Jack.tagged_with(params[:tag])
else
#jacks = Jack.postall
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_jack
#jack = Jack.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def jack_params
params.require(:jack).permit(:title, :description, :picture, :tag_list)
end
end
index method is missing an 'end'
def index
if params[:tag]
#jacks = Jack.tagged_with(params[:tag])
else
#jacks = Jack.all
end
end

Resources