Updating multiple models with one form in Rails - ruby-on-rails

I am new to Rails and trying to build a form that allows users to complete and submit a form. The form completes their profile. I want the form to update the Users model (and database table) as well as the Interests model (hobbies). I am using a form with fields_for.
However submitting the form does not update the Interests model. It either only updates the User model or returns various errors (the following produces Interest user must exist error):
MODELS:
class User < ApplicationRecord
has_many :interests, foreign_key: "interests_user_id"
accepts_nested_attributes_for :interests
end
class Interest < ApplicationRecord
belongs_to :user
self.primary_key = "interest_id"
end
CONTROLLER:
class UsersController < ApplicationController
def index
#allUsers = User.all
end
def new
#user = User.new
#user.interests.build
end
def create
#user = User.new permitted_params
=begin
#user = User.new(
:author => params[:user][:author],
:user_name => params[:user][:user_name],
:user_bio => params[:user][:user_bio],
)
#user.interests.new(
:interest_name => params[:user][:interests_attributes][:interest_name],
:interest_experience_level => params[:user][:interests_attributes][:interest_experience_level],
:interest_positon => params[:user][:interests_attributes][:interest_positon],
)
=end
if #user.save
redirect_to users_url
else
render 'new'
end
end
private
def permitted_params
#params.require(:interest).permit(User.attribute_names.map(&:to_sym),interest.attribute_names.map(&:to_sym))
params.require(:user).permit(User.attribute_names.map(&:to_sym), interests_attributes: [:interest_name,:interest_experience_level,:interest_positon])
end
end
FORM:
<%= form_with model: #user do |newUser| %>
<% if #user.errors.any? %>
<ul>
<% #user.errors.full_messages.each do |message| %>
<li> <%= message %></li>
<%end%>
</ul>
<%end%>
<div class="form-sections" id="user-profile">
<h3>General Information</h3>
<table class="formTables" id="formMainInfo">
<%= newUser.hidden_field :author, value:1 %>
<tr class="formRows">
<td class="formDescriptionCol"><%= newUser.label :user_name, "Your Name" %></td>
<td class="formInputCol">
<%= newUser.text_field :user_name %>
</td>
</tr>
<tr class="formRows">
<td class="formDescriptionCol"> <%= newUser.label :user_bio, "Biography" %></td>
<td class="formInputCol">
<%= newUser.text_area :user_bio %>
</td>
</tr>
<h3>Interests</h3>
<%= newUser.fields_for :interests do |newInterest| %>
<tr class="interestRows">
<td >Interest Name:</td>
<td>
<%= newInterest.text_field :interest_name%>
</td>
</tr>
<tr class="interestRows">
<td ><%=newInterest.label :interest_experience_level, "Experience Level" %></td>
<td >
<%= newInterest.text_field :interest_experience_level %>
</td>
</tr>
<tr class="interestRows">
<td ><%= newInterest.label :interest_position, "Position" %></td>
<td >
<%= newInterest.text_field :interest_position %>
</td>
</tr>
<%end%>
</table>
</div>
<div class="formSections" id="buttonsSection">
<%= newUser.submit "submit" %>
</div>
<%end%>
SCHEMA:
create_table "interests", primary_key: "interest_id", id: :integer, force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t|
t.integer "interest_user_id", null: false
t.string "interest_name", limit: 45, null: false
t.string "interest_experience_level", limit: 45, null: false
t.string "interest_position", limit: 45, null: false
t.index ["interest_user_id"], name: "user_id_idx"
end
create_table "users", primary_key: "user_id", id: :integer, force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t|
t.string "user_name", limit: 60, null: false
t.string "author", limit: 60, null: false
t.string "user_bio", limit: 500, null: false
end
add_foreign_key "interests", "users", column: "interest_user_id", primary_key: "user_id", name: "interest_user_name", on_update: :cascade, on_delete: :cascade

Related

Doing a joined search in rails

I'm working on doing a simple joined search within a rails project. What I want to do is find a description of an item based on what the user enters in a search box. The error that I'm most commonly getting is:
Mysql2::Error: Unknown column 'item.description' in 'where clause': SELECT item_instances.* FROM item_instances INNER JOIN items ON items.id = item_instances.item_id WHERE item.description = 'server'
The search.html.erb page looks like the following:
<p>
Search results base on database field <span class='bold'><%= #columnType %></span>
with value: <span class='bold'><%= #search_value %> </span>
</p>
<p>Total Report Cost: <span class='bold'>$<%= #cost %><span></p>
<table class='reportTable'>
<thead>
<tr>
<th class='reportTableHeaderCell'>Inv number</th>
<th class='reportTableHeaderCell'>Description</th>
<th class='reportTableHeaderCell'>Serial</th>
<th class='reportTableHeaderCell'>PO number</th>
<th class='reportTableHeaderCell'>PO date</th>
<th class='reportTableHeaderCell'>Invoice</th>
<th class='reportTableHeaderCell'>Date Out</th>
<th class='reportTableHeaderCell'>Cost</th>
<th class='reportTableHeaderCell'>Acro</th>
</tr>
</thead>
<tbody>
<% #item_instances.each do |item_instance| %>
<tr class='searchTableRow'>
<td class='reportTableCell'><%= link_to item_instance.inv_number, edit_item_instance_path(item_instance) %></td>
<td class='reportTableCell'><%= item_instance.item.description %></td>
<td class='reportTableCell'><%= item_instance.serial %></td>
<td class='reportTableCell'><%= item_instance.po_number %></td>
<td class='reportTableCell'><%= item_instance.po_date %></td>
<td class='reportTableCell'><%= item_instance.invoice %></td>
<td class='reportTableCell'><%= item_instance.date_out %></td>
<td class='reportTableCell'><%= item_instance.cost %></td>
<td class='reportTableCell'><%= item_instance.acro %></td>
</tr>
<% end %>
</tbody>
</table>
item_instances.rb (model) file
class ItemInstance < ApplicationRecord
validates :inv_number, :serial, :cost, presence: true
belongs_to :item
scope :in_order, ->{order(:description)}
# Named Scopes
scope :search_for_records_by_date, ->(startDate, endDate) { where(date_out: startDate..endDate) }
scope :search_for_records_by_column_and_value, ->(columnName, value) { where("#{columnName}": "#{value}") }
#I know something may be wrong in here.
scope :search_for_records_by_column_and_value_item_table, ->(columnName, value) { where(item: "#{columnName}": "#{value}") }
end
The items model:
class Item < ApplicationRecord
validates :description, :cost, :list_price, presence: true
has_many :item_instances, dependent: :delete_all
scope :in_order, ->{order(:description)}
scope :search_for_active_items, ->(active) { where(active: active) }
scope :search_for_records_by_column_and_value_on_items, ->(columnName, value) { where("#{columnName}": "#{value}") }
end
The item_instances Controller:
class ItemInstancesController < ApplicationController
def search
# Getting the params from what the user submitted
#columnType = params[:columnType]
#search_value = params[:search_value]
if #columnType == 'description'
# SIMPLE THINGS I've TRIED:
# #item_instances = ItemInstance.joins(:item).where(item: {description: "server"})
##item_instances = ItemInstance.joins(:items)
#I TRIED THIS JUST TO SEE IF I COULD GET ANYTHING
#item_instances = ItemInstance.joins(:item).where(:item => {description: "server"})
##item_instances = ItemInstance.joins(:item).search_for_records_by_column_and_value_item_table(#columnType, #search_value)
end
respond_to do |format|
format.html { render :search }
end
end
end
The Routes file:
Rails.application.routes.draw do
resources :item_instances
get '/report', to: 'item_instances#report'
get '/search', to: 'item_instances#search'
resources :items
get '/active', to: 'items#active'
# Route to the home page
root 'item_instances#home'
end
schema.rb File:
ActiveRecord::Schema.define(version: 2020_08_17_190727) do
create_table "item_instances", options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
t.integer "inv_number"
t.string "serial"
t.integer "po_number"
t.date "po_date"
t.date "invoice"
t.date "date_out"
t.decimal "cost", precision: 8, scale: 2
t.string "acro"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.bigint "item_id"
t.index ["item_id"], name: "fk_rails_6ea33fd9d0"
end
create_table "items", options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
t.string "description"
t.decimal "cost", precision: 8, scale: 2
t.decimal "list_price", precision: 8, scale: 2
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.boolean "active"
end
add_foreign_key "item_instances", "items"
end
Please let me know if anything else is needed. I've looked through multiple articles and stackoverflow posts with no luck. Anything that can help will be appreciated.
In your item_instances_controller.rb, replace item with items in where condition. While where condition you must specify complete table name for comparison.
class ItemInstancesController < ApplicationController
def search
#yourcode
#item_instances = ItemInstance.joins(:item).where(:items => {description: "server"})
#yourcode
end
end

Rails accepts_nested_attributes_for not working with has_many relationship and cocoon gem

I'm using the cocoon gem to build a form that creates a Tournament. A Tournament has_many Games. Cocoon lets me dynamically add more games to the form.
When I call #tournament.save, it generates the following errors:
Games team one must exist
Games team two must exist
tournament.rb
class Tournament < ApplicationRecord
has_many :games
accepts_nested_attributes_for :games, allow_destroy: true
end
game.rb
class Game < ApplicationRecord
belongs_to :tournament, optional: false
belongs_to :team_one, polymorphic: true
belongs_to :team_two, polymorphic: true
belongs_to :field, optional: true
end
schema.rb
ActiveRecord::Schema.define(version: 2019_12_24_011346) do
...
create_table "club_teams", force: :cascade do |t|
t.string "name"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
end
create_table "fields", force: :cascade do |t|
t.string "name"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
end
create_table "games", force: :cascade do |t|
t.bigint "tournament_id", null: false
t.string "team_one_type", null: false
t.bigint "team_one_id", null: false
t.string "team_two_type", null: false
t.bigint "team_two_id", null: false
t.bigint "field_id", null: false
t.date "date"
t.datetime "start_time"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.index ["field_id"], name: "index_games_on_field_id"
t.index ["team_one_type", "team_one_id"], name: "index_games_on_team_one_type_and_team_one_id"
t.index ["team_two_type", "team_two_id"], name: "index_games_on_team_two_type_and_team_two_id"
t.index ["tournament_id"], name: "index_games_on_tournament_id"
end
create_table "high_school_teams", force: :cascade do |t|
t.string "school_name"
t.string "team_name"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
end
create_table "tournaments", force: :cascade do |t|
t.string "name"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
end
add_foreign_key "games", "fields"
add_foreign_key "games", "tournaments"
end
tournaments_controller.rb
class TournamentsController < ApplicationController
...
def create
#tournament = Tournament.new(tournament_params)
if #tournament.save
redirect_to #tournament
else
render 'new'
end
end
private
def tournament_params
params
.require(:tournament)
.permit(:name, games_attributes: [:id, :_destroy, :team_one_id, :team_two_id, :field_id, :date, :start_time])
end
end
request parameters in tournaments_controller#create
{
"authenticity_token"=>"iB4JefT9jRdiOFKok38OtjzMwd6Dv3hlHP/QZRtlFgMuVZfbn9PFD7Lebc1DuvfL6/IatDpS5CiubTci5MsCFg==",
"tournament"=>{
"name"=>"foo",
"games_attributes"=>{
"1577935885397"=>{
"team_one_id"=>"high-school-team-2",
"team_two_id"=>"club-team-2",
"date"=>"",
"start_time"=>"",
"_destroy"=>"false"
}
}
},
"commit"=>"Create Tournament"
}
tournament_params in tournaments_controller#create
<ActionController::Parameters {
"name"=>"foo",
"games_attributes"=><ActionController::Parameters {
"1577937916236"=><ActionController::Parameters {
"_destroy"=>"false",
"team_one_id"=>"high-school-team-2",
"team_two_id"=>"club-team-2",
"date"=>"",
"start_time"=>""
} permitted: true>
} permitted: true>
} permitted: true>
It seems to me that the tournament_params match what the accepts_nested_attributes documentation is expecting under One-to-many, so I don't see why there is an error.
Nested attributes for an associated collection can also be passed in
the form of a hash of hashes instead of an array of hashes:
Member.create(
name: 'joe',
posts_attributes: {
first: { title: 'Foo' },
second: { title: 'Bar' }
}
)
has the same effect as
Member.create(
name: 'joe',
posts_attributes: [
{ title: 'Foo' },
{ title: 'Bar' }
]
)
Edit:
tournaments/new.html.erb
<h1>Create a tournament</h1>
<%= render 'form' %>
<%= link_to 'Back', tournaments_path %>
tournaments/_form.html.erb
<%= form_with model: #tournament, class: 'tournament-form' do |f| %>
<p>
<%= f.label :name %><br>
<%= f.text_field :name %>
</p>
<section class="games">
<%= f.fields_for :games do |game| %>
<%= render 'game_fields', f: game %>
<% end %>
<hr>
<p>
<%= link_to_add_association "Add game", f, :games,
data: {
association_insertion_node: '.games',
association_insertion_method: :prepend
}
%>
</p>
</section>
<p>
<%= f.submit %>
</p>
<% end %>
tournaments/_game_fields.html.erb
<section class="nested-fields">
<hr>
<p><strong>Game</strong></p>
<%= render "games/form_fields", f: f %>
<p><%= link_to_remove_association "Remove game", f %></p>
</section>
games/_form_fields.html.erb
<section>
<% if HighSchoolTeam.all.count + ClubTeam.all.count < 2 %>
<p>You neeed at least two teams to create a game. Create more high school and/or club teams first.</p>
<% else %>
<section class="game-form">
<p>
<%= f.label :team_one %><br>
<%= f.select :team_one_id, nil, {}, class: "team-one-dropdown" do %>
<optgroup label="High School Teams">
<% HighSchoolTeam.all.each do |high_school_team| %>
<option value="high-school-team-<%= high_school_team.id %>"><%= high_school_team.school_name %></option>
<% end %>
</optgroup>
<optgroup label="Club Teams">
<% ClubTeam.all.each do |club_team| %>
<option value="club-team-<%= club_team.id %>"><%= club_team.name %></option>
<% end %>
</optgroup>
<% end %>
</p>
<p>
<%= f.label :team_two %><br>
<%= f.select :team_two_id, nil, {}, class: "team-two-dropdown" do %>
<optgroup label="High School Teams">
<% HighSchoolTeam.all.each do |high_school_team| %>
<option value="high-school-team-<%= high_school_team.id %>"><%= high_school_team.school_name %></option>
<% end %>
</optgroup>
<optgroup label="Club Teams">
<% ClubTeam.all.each do |club_team| %>
<option value="club-team-<%= club_team.id %>"><%= club_team.name %></option>
<% end %>
</optgroup>
<% end %>
</p>
<p>
<%= f.label :field %><br>
<%= f.collection_select(:field_id, Field.all, :id, :name) %>
</p>
<p>
<%= f.label :date %><br>
<%= f.date_field :date %>
</p>
<p>
<%= f.label :start_time %><br>
<%= f.time_field :start_time %>
</p>
</section>
<% end %>
</section>
You seem to have problem saving team and not an issue of Cocoon gem.
Since you customize your select value to club-team-id and high-school-team-id. I think you just need to change it to something like this:
<option value="HighSchoolTeam-<%= high_school_team.id %>"><%= high_school_team.school_name %></option>
and
<option value="ClubTeam-<%= club_team.id %>"><%= club_team.name %></option>
Then the params will be
{
"authenticity_token"=>"iB4JefT9jRdiOFKok38OtjzMwd6Dv3hlHP/QZRtlFgMuVZfbn9PFD7Lebc1DuvfL6/IatDpS5CiubTci5MsCFg==",
"tournament"=>{
"name"=>"foo",
"games_attributes"=>{
"1577935885397"=>{
"team_one_id"=>"HighSchoolTeam-2",
"team_two_id"=>"ClubTeam-2",
"date"=>"",
"start_time"=>"",
"_destroy"=>"false"
}
}
},
"commit"=>"Create Tournament"
}
then you need to modified your params by:
# Adding before_action on top of your controller
before_action :modify_params, only: [:create, :update]
private
# Not the cleanest way, but this is what I can think of right now.
def modify_params
params.dig(:tournament, :games_attributes).each do |game_id, game_attribute|
team_one_type = game_attribute[:team_one_id].split('-').first
team_one_id = game_attribute[:team_one_id].split('-').last
team_two_type = game_attribute[:team_two_id].split('-').first
team_two_id = game_attribute[:team_two_id].split('-').last
params[:tournament][:games_attributes][game_id] = game_attribute.merge(
team_one_type: team_one_type,
team_one_id: team_one_id,
team_two_type: team_two_type,
team_two_id: team_two_id
)
end
end
# And update this method to allow team_one_type and team_two_type
def tournament_params
params.require(:tournament)
.permit(:name, games_attributes: [:id, :_destroy, :team_one_id, :team_two_id, :team_one_type, :team_two_type, :field_id, :date, :start_time])
end

RoR: Collection_select not working

UPDATED
The official docs for this are not the best and a little confusing. I am gathering options from a feedback table and rendering them in a dropdown on a form and then saving them in a table called "answers" and column called "feedback_request" using collection_select:
<%= f.collection_select :feedback_request, Feedback.order(:feedback_option), :id, :feedback_request, {prompt: "Feedback"}, {class: "select large-1 behaviourForm"} %>
Answers table:
create_table "answers", force: :cascade do |t|
t.integer "user_id", limit: 4
t.string "subject", limit: 4
t.string "source", limit: 45
t.text "description", limit: 65535
t.string "significance", limit: 45
t.string "feedback_request"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "answers", ["feedback_request"], name: "feedback_index"
add_index "answers", ["significance"], name: "signif_index"
add_index "answers", ["source"], name: "source_index"
add_index "answers", ["subject"], name: "FK_HOM_MOD_idx"
add_index "answers", ["user_id"], name: "teacher_answer_index"
Feedback table
create_table "feedback", force: :cascade do |t|
t.string "feedback_option", limit: 45
end
Relationships
feedback.rb
class Feedback < ActiveRecord::Base
self.table_name = 'feedback'
has_many :answers, :class_name => 'Answer'
end
answer.rb
belongs_to :feedback, :class_name => 'Feedback', :foreign_key => :feedback_request
Table (as requested):
<thead>
<tr>
<% if current_user.teacher? %>
<th style="width:5%;", bgcolor="#313E4E" ></th>
<th bgcolor="#313E4E"><font color="#FFFFFF">Answer Title</font></th>
<% else %>
<th bgcolor="#313E4E"><font color="#FFFFFF">Subject</font></th>
<% end %>
<th bgcolor="#313E4E"><font color="#FFFFFF">Source</font></th>
<th bgcolor="#313E4E"><font color="#FFFFFF"><%= sort_link(#q, :created_at, "Assigned/Scheduled") %></font></th>
<th bgcolor="#313E4E"><font color="#FFFFFF"><%= sort_link(#q, :Due, "Due") %></font></th>
</tr>
</thead>
<tfoot>
</tfoot>
<%= form_tag destroy_multiple_answers_path, method: :delete do %>
<% #answers.each do |answer| %>
<tbody>
<tr>
<% if current_user.teacher? %>
<td><%= check_box_tag "answer[id][]", answer.id, class: "narrowtr" %></input></td>
<td height="1"><font color="#000000"><%= link_to answer.subject, answer, class: "blackLink" %></font></td>
<% else %>
<td height="1"><%= answer.subject %></td>
<% end %>
<td height="1"></td>
<td height="1"><%= answer.created_at %></td>
<td height="1"><%= answer.Due %></td>
</tr>
</tbody>
<% end %>
</table>
This gives me the following error on submit:
**undefined method `feedback_request' for #<Feedback id: 1, feedback_option: "Curriculum Management">**
Any guidance much appreciated.

Survey App Using Nested Models, Partials, & Rails Form Builder

I extracted this code from the following engine:
Link to Demo:
https://rapidfire.herokuapp.com/rapidfire/question_groups/1110/answer_groups/new
Link to Code:
https://github.com/code-mancers/rapidfire/blob/master/app/services/rapidfire/answer_group_builder.rb
I trying to modify it so that I can create custom answer types, called "kind"(s) (see schema). One kind called "indicator" (see _indicator.html.erb), has multiple columns.
My models are setup as follows:
Survey
has_many :question_groups
accepts_nested_attributes_for :question_groups
end
QuestionGroup
belongs_to :survey
has_many :questions
accepts_nested_attributes_for :questions
end
AnswerGroup
belongs_to :survey
has_many :answers
accepts_nested_attributes_for :answers
end
Answer
belongs_to :question
belongs_to :answer_group, inverse_of: :answers
end
Question 1: What does this line do? (see build_answer_group method)
#answers = question_group.questions.collect do |question|
In the console,
#answers = [#<Answer id: nil, answer_group_id: nil, question_id: 1034,
answer_text: nil, created_at: nil, updated_at: nil>, #<Answer id: nil,
answer_group_id: nil, question_id: 1035, answer_text: nil, created_at: nil,
updated_at: nil>]
question_ids 1034 and 1035 refer to the last items in the array produced by
question_group.questions
Instead, I need #answers to be the Answer class equivalent of all questions.
Why is it returning only two items?
Question 2:
For the indicator partial, I need to display the name of the Question Group and the names of each subitem, e.g. "Questions", and five additional columns with unique html names and ids. So, if I had two question groups of kind "indicator", I need to produce something like:
QuestionGroup1.name
id = answer_group_1034_answer_text name = answer_group[1034][answer_text]
id = answer_group_1035_answer_text name = answer_group[1035][answer_text]
etc...
QuestionGroup2.name
id = answer_group_1036_answer_text name = answer_group[1036][answer_text]
id = answer_group_1037_answer_text name = answer_group[1037][answer_text]
Currently, it is producing:
For QuestionGroup1:
<textarea rows="5" name="answer_group[1034][answer_text]"
id="answer_group_1034_answer_text"></textarea>
<textarea rows="5" name="answer_group[1034][answer_text]"
id="answer_group_1034_answer_text"></textarea>
For QuestionGroup2:
<textarea rows="5" name="answer_group[1035][answer_text]"
id="answer_group_1034_answer_text"></textarea>
<textarea rows="5" name="answer_group[1035][answer_text]"
id="answer_group_1034_answer_text"></textarea>
Goal: Assign a unique id and name for each row within a question group for the indicator partial
views/answer_groups/_fidelitychecklist.html.erb
<%= form_for([#survey, #answer_group_builder]) do |f| %>
<% #answer_group_builder.answers.each do |answer| %>
<%= f.fields_for("#{answer.question.id}", answer) do |answer_form| %>
<%= render_answer_form_helper(answer, answer_form) %>
<% end %>
<% end %>
<%= f.submit "Save" %>
<% end %>
services/answer_group_builder.rb
class AnswerGroupBuilder < BaseService
attr_accessor :user, :survey, :questions, :answers, :params
def initialize(params = {})
super(params)
build_answer_group
end
def to_model
#answer_group
end
...
private
def build_answer_group
#answer_group = AnswerGroup.new(user: user, survey: survey)
#survey.question_groups.each do |question_group|
#answers = question_group.questions.collect do |question|
#answer_group.answers.build(question_id: question.id)
end
end
end
AnswerGroupsController
before_filter :find_survey!
def new
#answer_group_builder = AnswerGroupBuilder.new(answer_group_params)
end
def create
#answer_group_builder = AnswerGroupBuilder.new(answer_group_params)
if #answer_group_builder.save
redirect_to surveys_path
else
render :new
end
end
private
def find_survey!
#survey = Survey.find(params[:survey_id])
end
def answer_group_params
answer_params = { params: params[:answer_group] }
answer_params.merge(user: current_user, survey: #survey)
end
module ApplicationHelper
def render_answer_form_helper(answer, form)
partial = Question.where(id: answer.question_id).last.question_group.kind.to_s
questiongroup = Question.find(answer.question_id).question_group
render partial: "/answers/#{partial}", locals: {f: form, answer: answer, questiongroup: questiongroup }
end
views/answers/_indicator.html.erb
<%= render partial: "answers/errors", locals: {answer: answer} %>
<fieldset>
<table class="indicator">
<thead>
<th class="first head-row">Indicators</th>
<th class="head-row">Presence</th>
<th class="head-row">Rating</th>
<th class="head-row">Element(s) Implemented Well</th>
<th class="head-row">Element(s) Requiring Further Support</th>
<th class="head-row">Comments/Action Steps</th>
</thead>
<tbody>
<tr><td colspan="6" class="indicator-title"><%= questiongroup.name %></td></tr>
<% questiongroup.questions.each do |question| %>
<tr>
<td class="first row">
<%= question.question_text %>
</td>
<td class="row">
<%= f.select :answer_text, options_for_select([["N/O", "n/o"], ["N", "n"]]) %>
</td>
<td class="row">
<%= f.select :answer_text, options_for_select([["1", "1"], ["2", "2"], ["3", "3"]]) %>
</td>
<td class="row">
<%= f.text_area :answer_text, rows: 5 %>
</td>
<td class="row">
<%= f.text_area :answer_text, rows: 5 %>
</td>
<td class="row">
<%= f.text_area :answer_text, rows: 5 %>
</td>
</tr>
<% end %>
</tbody>
</table>
</fieldset>
schema.rb
create_table "surveys", force: :cascade do |t|
t.string "name", limit: 255
end
create_table "question_groups", force: :cascade do |t|
t.string "name", limit: 255
t.integer "position", limit: 4
t.integer "survey_id", limit: 4
t.text "kind", limit: 65535
end
create_table "questions", force: :cascade do |t|
t.string "question_text", limit: 255
t.integer "position", limit: 4
t.integer "question_group_id", limit: 4
end
create_table "answer_groups", force: :cascade do |t|
t.integer "survey_id", limit: 4
end
create_table "answers", force: :cascade do |t|
t.integer "answer_group_id", limit: 4
t.integer "question_id", limit: 4
t.text "answer_text", limit: 65535
end
routes.rb
resources :surveys do
resources :answer_groups, only: [:new, :create] do
end
end

how to insert multi textbox array in ruby on rails

I'm new to ruby. i need insert the array textbox values to has_many and belongs_to relationship.i used two models intrrattes and intrsetups.
here is my new.html.erb file
<%= form_for #intrsetup do |f| %>
<div class='row'>
<div class='span6'>
<div class="control-group">
<label class=" control-label">Effective From<abbr title="required">*</abbr></label>
<div class="controls">
<%= f.text_field :effective_from, :onclick => "return calender()" %>
</div>
</div>
</div>
<div class='span6'>
<div class="control-group">
<label class=" control-label">Effective To</label>
<div class="controls">
<%= f.text_field :effective_to %>
</div>
</div>
</div>
</div>
<%= f.fields_for :intrrates do |builder| %>
<h3>Interest Rates</h3>
<table class='table condensed-table'>
<tr>
<td>
Days From
</td>
<td>
Days To
</td>
<td>
Rate
</td>
<td>
Senior Increment
</td>
<td>
Super Senior Increment
</td>
<td>
Widow Increment
</td>
</tr>
<tr>
<td>
<%(1..2).each do |i|%>
<%= builder.text_field(:days_from, :name => "intrrate[days_from][]", :id => "intrrate_days_from_#{i}") %>
<%end%>
<%= builder.text_field :days_to, multiple: true %>
<%= builder.text_field :rate, multiple: true %>
<%= builder.text_field :senior_increment %>
<%= builder.text_field :super_senior_increment %>
<%= builder.text_field :widow_increment %>
<% end %>
<%= f.submit %>
here is my Intrrate and Intrsetup model code
class Intrrate < ActiveRecord::Base
belongs_to :intrsetup
#attr_accessor :effective_from, :effective_to
attr_accessible :effective_from, :effective_to
attr_accessible :days_from, :days_to, :rate, :senior_increment, :super_senior_increment, :widow_increment, :intrsetup_id
end
class Intrsetup < ActiveRecord::Base
has_many :intrrates
accepts_nested_attributes_for :intrrates
attr_accessible :intrrates_id, :effective_from, :effective_to, :intrrates_attributes
end
here is my controller page
class IntrsetupsController < ApplicationController
def new
#intrsetup = Intrsetup.new
#intrrate = #intrsetup.intrrates.build
end
def create
#intrsetup = Intrsetup.new(params["intrsetup"])
#intrsetup.save
end
end
class IntrratesController < ApplicationController
def index
#intrrate = Intrrate.all
end
def new
#intrrate = Intrrate.new
end
def create
puts #intrrate = Intrrate.new(params["intrrate"])
#intrrate.save
end
end
my schema.rb
create_table "intrrates", :force => true do |t|
t.integer "days_from"
t.integer "days_to"
t.float "rate"
t.float "senior_increment"
t.float "super_senior_increment"
t.float "widow_increment"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.integer "intrsetup_id"
t.integer "deposit_id"
end
create_table "intrsetups", :force => true do |t|
t.date "effective_from"
t.date "effective_to"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
my error page
NoMethodError in IntrsetupsController#create
undefined method `[]' for nil:NilClass
Rails.root: /home/tbf/rails_projects/ccddeposit
Application Trace | Framework Trace | Full Trace
app/controllers/intrsetups_controller.rb:9:in `create'
Request
Parameters:
{"utf8"=>"✓",
"authenticity_token"=>"WsfTU31o9LLfcoieNL3pgpRRu/swqreaXDdo6LxrdsM=",
"intrsetup"=>{"effective_from"=>"1994/12/06",
"effective_to"=>"1994/12/06"},
"intrrate_days_from_1"=>"1",
"intrrate_days_to_1"=>"45",
"intrrate_rate_1"=>"0.5",
"intrrate_senior_increment_1"=>"0.5",
"intrrate_super_senior_increment_1"=>"0.56",
"intrrate_widow_increment_1"=>"0.5",
"intrrate_days_from_2"=>"45",
"intrrate_days_to_2"=>"95",
"intrrate_rate_2"=>"0.5",
"intrrate_senior_increment_2"=>"0.7",
"intrrate_super_senior_increment_2"=>"0.8",
"intrrate_widow_increment_2"=>"0.5",
"commit"=>"Create Intrsetup"}
but i'm getting the following error
how to solve this error?
As I said, the problem is rate is attending a float and you give to it an Array.
So here is a code which force your parameter "rate" as a float value and give you the average of all rates entered in your form :
def create
# In case where you want the average value of all different rates you enter in your form
rate_avg = params["intrsetup"]["intrrates_attributes"]["0"]["rate"].inject(0.0) do |value, rate|
value += rate.to_f
end
params["intrsetup"]["intrrates_attributes"]["0"]["rate"] = rate_avg / params["intrsetup"]["intrrates_attributes"]["0"]["rate"].count
#intrsetup = Intrsetup.new(params["intrsetup"])
#intrsetup.save
end
Try this and tell me if it works now.

Resources