I am working on a website, where a user can have multiple projects and multpile users can contribute to a single project.
I have a project model
class Project < ActiveRecord::Base
#associations
has_and_belongs_to_many :users
end
and a users model
class User < ActiveRecord::Base
#associations
has_and_belongs_to_many :projects
end
and I have created a joins table by the name - :projects_users
everything works fine when I run the code on rails console.
but when I try to do the save thing in the controller, the data is not being saved in the joins table.
Code for the controller
please help
class ProjectsController < ApplicationController
def new
#project = Project.new
end
def create
#user = User.find(session[:user_id])
#project = Project.new(project_params)
if #project.save
#project.users << #user
redirect_to #project
else
flash[:error] = "Project has not been created due to some error"
render 'new'
end
end
private
def project_params
params.require(:project).permit(:name,:description)
end
end
Try using nestes_attributes_for
class Answer < ActiveRecord::Base
belongs_to :question
end
class Question < ActiveRecord::Base
has_many :answers
accepts_nested_attributes_for :answers, allow_destroy: true
end
Controlller
def new
#question = Question.new
#question.answers.build
end
def create
#question = Question.new(question_params)
respond_to do |format|
if #question.save
format.html { redirect_to #question, notice: 'question was successfully created.' }
format.json { render action: 'show', status: :created, location: #question }
else
format.html { render action: 'new' }
format.json { render json: #question.errors, status: :unprocessable_entity }
end
end
end
def question_params
params.require(:question).permit(:name, :description, answers_attributes:[:content, :id, :question_id])
end
You form should look like this
<%= form_for(#question) do |f| %>
<% if #question.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#question.errors.count, "error") %> prohibited this question from being saved:</h2>
<ul>
<% #question.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :name %><br>
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :description %><br>
<%= f.text_field :description %>
</div>
<%= f.fields_for :answer do |builder| %>
<%= builder.label :content %>
<%= builder.text_area :content %>
<% end %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
just changed
#project.users << #user
to
#user.projects << #project
and it started working.Dont know the reason yet but its working
Related
I am building simple ROR app which has survey question and answers. Survey is generated using scaffolding method while question and answer are model only.
Survey.rb
class Survey < ApplicationRecord
has_many :questions
accepts_nested_attributes_for :questions, allow_destroy: true
validates :name, presence: true
end
Question.rb
class Question < ApplicationRecord
belongs_to :survey
has_many :answers
accepts_nested_attributes_for :answers
validates :question_content, presence: true
end
Answer.rb
class Answer < ApplicationRecord
belongs_to :question
end
survey_controller.rb
class SurveysController < ApplicationController
before_action :set_survey, only: [:show, :edit, :update, :destroy]
def index
#surveys = Survey.all
end
def show
#survey= Survey.find(params[:id])
end
def new
#survey = Survey.new
#questions = #survey.questions.new
#answers = #questions.answers.new
end
def edit
end
def create
#survey = Survey.new(survey_params)
Survey.create(survey_params)
respond_to do |format|
if #survey.save
format.html { redirect_to #survey, notice: 'Survey was successfully created.' }
format.json { render :show, status: :created, location: #survey }
else
format.html { render :new }
format.json { render json: #survey.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #survey.update(survey_params)
format.html { redirect_to #survey, notice: 'Survey was successfully updated.' }
format.json { render :show, status: :ok, location: #survey }
else
format.html { render :edit }
format.json { render json: #survey.errors, status: :unprocessable_entity }
end
end
end
def destroy
#survey.destroy
respond_to do |format|
format.html { redirect_to surveys_url, notice: 'Survey was successfully destroyed.' }
format.json { head :no_content }
end
end
private
def set_survey
#survey = Survey.find(params[:id])
end
def survey_params
params.require(:survey).permit(:name, questions_attributes: [:id, :question_content], answers_attributes: [:id, :answer_content, :answer_type])
end
end
Survey form partial
<%= form_for(#survey) do |form| %>
<% if survey.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(survey.errors.count, "error") %> prohibited this survey from being saved:</h2>
<ul>
<% survey.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= form.label :name %>
<%= form.text_field :name, id: :survey_name %>
</div>
<%= form.fields_for :questions do |builder| %>
<fieldset>
<%= builder.label :question_content, "Question" %><br/>
<%= builder.text_area :question_content %><br/>
<%= form.fields_for :answers do |f| %>
<fieldset>
<%= f.text_area :answer_type %>
<%= f.text_area :answer_content %><br/>
</fieldset>
</fieldset>
<% end %>
<%end %>
<div class="actions">
<%= form.submit %>
</div>
I want to implement question and answer in single page i.e survey. Any help will appreciated.
Problem : Unable to save answers_attributes to database but Question attributes work perfectly fine. I am probably making mistake somewhere in controller not sure.
You need to change the way you're building the answer fields, so that they're referenced as fields_for questions, not surveys. Try changing this piece of code:
<%= form.fields_for :questions do |builder| %>
<fieldset>
<%= builder.label :question_content, "Question" %><br/>
<%= builder.text_area :question_content %><br/>
<%= form.fields_for :answers do |f| %>
<fieldset>
<%= f.text_area :answer_type %>
<%= f.text_area :answer_content %><br/>
</fieldset>
</fieldset>
<% end %>
<%end %>
to this:
<%= form.fields_for :questions do |builder| %>
<fieldset>
<%= builder.label :question_content, "Question" %><br/>
<%= builder.text_area :question_content %><br/>
<%= builder.fields_for :answers do |f| %>
<fieldset>
<%= f.text_area :answer_type %>
<%= f.text_area :answer_content %><br/>
</fieldset>
<% end %>
</fieldset>
<% end %>
(Note: the meaningful change is changing form.fields_for to builder.fields_for)
I'm trying to create a nested form in Ruby on Rails. The form appears as expected. But when it is saved the nested attribute, Booking, is not saved.
cleaner.rb
class Cleaner < ActiveRecord::Base
validates_presence_of :first_name
validates_presence_of :last_name
validates_presence_of :quality_score
validates :quality_score, inclusion: 0.0...5.0
has_many :assignments
has_many :bookings
has_many :cities, through: :assignments
has_many :customers, through: :bookings
end
customer.rb
class Customer < ActiveRecord::Base
validates_presence_of :first_name
validates_presence_of :last_name
validates_uniqueness_of :phone_number
belongs_to :city
has_many :bookings
has_many :cleaners, through: :bookings
accepts_nested_attributes_for :bookings
end
booking.rb
class Booking < ActiveRecord::Base
belongs_to :customer
belongs_to :cleaner
validates_presence_of :customer
validates_presence_of :cleaner
validates_presence_of :date
end
customers_controller.rb
class CustomersController < ApplicationController
before_action :set_customer, only: %i[show edit update destroy]
def index
#customers = Customer.all
end
def show; end
def new
#customer = Customer.new
end
def edit; end
def create
#customer = Customer.find_or_initialize_by(phone_number: params[:phone_number])
#customer.assign_attributes(customer_params)
respond_to do |format|
if #customer.save
format.html { redirect_to #customer, notice: 'Customer was successfully created.' }
format.json { render :show, status: :created, location: #customer }
else
format.html { render :new }
format.json { render json: #customer.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #customer.update(customer_params)
format.html { redirect_to #customer, notice: 'Customer was successfully updated.' }
format.json { render :show, status: :ok, location: #customer }
else
format.html { render :edit }
format.json { render json: #customer.errors, status: :unprocessable_entity }
end
end
end
def destroy
#customer.destroy
respond_to do |format|
format.html { redirect_to customers_url, notice: 'Customer was successfully destroyed.' }
format.json { head :no_content }
end
end
private
def set_customer
#customer = Customer.find(params[:id])
end
def customer_params
params.require(:customer).permit(:first_name, :last_name, :phone_number, :city, :city_id, bookings_attributes: %i[cleaner_id date])
end
end
HomeController.rb
class HomeController < ApplicationController
def index
#customer = Customer.new
#customer.bookings.build
end
end
Parameters
{"utf8"=>"✓", "authenticity_token"=>"c4xo2M4r57+/xBsmcc+7yajpQU13u1kiwmOthx/nP7HiJXJIfS9/OqC0MrWCcaDrSW/xN8UGk2+LVfnUnbTb3A==", "customer"=>{"first_name"=>"adfad", "last_name"=>"fad", "phone_number"=>"9392323", "city_id"=>"1", "bookings_attributes"=>{"0"=>{"cleaner_id"=>"1"}}}, "#<ActionView::Helpers::FormBuilder:0x007f86bec96480>"=>{"date(1i)"=>"2017", "date(2i)"=>"8", "date(3i)"=>"2"}, "commit"=>"Create Customer"}
updated form
<h1>Sign Up Now</h1>
<%= form_for #customer do |f| %>
<% if #customer.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#customer.errors.count, "error") %> prohibited this customer from being saved:</h2>
<ul>
<% #customer.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :first_name %><br>
<%= f.text_field :first_name %>
</div>
<div class="field">
<%= f.label :last_name %><br>
<%= f.text_field :last_name %>
</div>
<div class="field">
<%= f.label :phone_number %><br>
<%= f.text_field :phone_number %>
</div>
<div class="field">
<%= f.label :city %><br>
<%= f.select :city_id, options_for_select(City.pluck(:name, :id)) %>
</div>
<%= f.fields_for :bookings do |b| %>
<%= b.date_select :date %>
<br>
<%= b.select :cleaner_id, Cleaner.all.pluck(:first_name, :id) %>
<% end %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
It's now failing with 2 errors
Bookings customer can't be blank
Bookings date can't be blank
use the iteration of the first #customer so rails can read properly
i saw this example https://www.sitepoint.com/complex-rails-forms-with-nested-attributes/
<%= f.fields_for :booking do |ff| %>
<%= ff.select :city_id,options_for_select(City.pluck(:name, :id)) %>
i hope it works cross finger :)
I'm trying to create a post that will contain it's forum_id that the form resides in. I need both ID to save in the object to achieve that.
I initialize a new #post in the new action using #post = Forum.find(params[:forum_id]).posts.build
Which will spit out unsaved instance of a post containing it the forum_id just as intended.
I then fill out my form here:
<%= form_for #post, :url => {:controller => "posts", :action => "create"} do |f| %>
<% if #post.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#post.errors.count, "error") %> prohibited this post from being saved:</h2>
<ul>
<% #post.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :title %>
<%= f.text_field :title, class: "form-control" %>
</div>
<div class="field">
<%= f.label :description %>
<%= f.text_area :description, class: "form-control" %>
</div>
<div class="actions">
<%= f.submit class: "btn btn-primary" %>
</div>
<% end %>
And when I click the submit button and inspect post_params with byebug after the line #post = Post.new(post_params) in the create action, only the :title and :description come through. The forum_id is lost in between actions and I cannot the save #post without it. I have :forum_id whitelisted in my post_params but it's not coming through. I would think that if an instance of post is created in the new action with a forum_id that it should persist into the create action inside post_params but something is wrong here. Here is the relevant information that might help with my issue.
My model's relationships:
# User model
has_many :forums
has_many :posts
# Forum model
belongs_to :user
has_many :posts
# Post model
belongs_to :user
belongs_to :forum
# post_controller
def new
#post = Forum.find(params[:forum_id]).posts.build
end
Post Controller
def create
#post = Post.new(post_params)
respond_to do |format|
if #post.save
format.html { redirect_to #post, notice: 'Post was successfully created.' }
format.json { render :show, status: :created, location: #post }
else
format.html { render :new }
format.json { render json: #post.errors, status: :unprocessable_entity }
end
end
end
...
# Rest of actions
...
def post_params
params.require(:post).permit(:title, :description, :forum_id, :user_id)
end
end
Form doesn't submit forum_id because it doesn't exist on there
I think you need to add this to that form
<%= f.hidden_field :forum_id %>
I'm making a survey app, I've got 3 models: Survey, Question, and Answer. Survey has_many questions, Question has_many answers.
I've got two main errors:
My code is supposed to generate 4 answer fields for each question but only 1 answer field is generated.
When I press submit on my form, I get
unknown attribute 'answers' for Survey.
Extracted source (around line #33):
# POST /surveys.json
def create
#survey = Survey.new(survey_params)
respond_to do |format|
if #survey.save
I think the second problem is related to the answers model in some way but I'm not sure how. Here's my code:
surveys_controller:
class SurveysController < ApplicationController
before_action :set_survey, only: [:show, :edit, :update, :destroy]
# GET /surveys
# GET /surveys.json
def index
#surveys = Survey.all
end
# GET /surveys/1
# GET /surveys/1.json
def show
end
# GET /surveys/new
def new
#survey = Survey.new
3.times do
question = #survey.questions.build
4.times { question.answers.build }
end
end
# GET /surveys/1/edit
def edit
end
# POST /surveys
# POST /surveys.json
def create
#survey = Survey.new(survey_params)
respond_to do |format|
if #survey.save
format.html { redirect_to #survey, notice: 'Survey was successfully created.' }
format.json { render :show, status: :created, location: #survey }
else
format.html { render :new }
format.json { render json: #survey.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /surveys/1
# PATCH/PUT /surveys/1.json
def update
respond_to do |format|
if #survey.update(survey_params)
format.html { redirect_to #survey, notice: 'Survey was successfully updated.' }
format.json { render :show, status: :ok, location: #survey }
else
format.html { render :edit }
format.json { render json: #survey.errors, status: :unprocessable_entity }
end
end
end
# DELETE /surveys/1
# DELETE /surveys/1.json
def destroy
#survey.destroy
respond_to do |format|
format.html { redirect_to surveys_url, notice: 'Survey was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_survey
#survey = Survey.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def survey_params
params.require(:survey).permit!
end
end
surveys/_form.html.erb
<%= form_for(#survey) do |f| %>
<% if #survey.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#survey.errors.count, "error") %> prohibited this survey from being saved:</h2>
<ul>
<% #survey.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :name %><br>
<%= f.text_field :name %>
</div>
<%= f.fields_for :questions do |builder| %>
<p>
<%= builder.label :content, "Question" %><br />
<%= builder.text_area :content, :rows => 3 %>
</p>
<%= f.fields_for :answers do |builder| %>
<p>
<%= builder.label :content, "Answer" %>
<%= builder.text_field :content %>
</p>
<% end %>
<% end %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
surveys/show.html.erb
<p id="notice"><%= notice %></p>
<p>
<strong>Name:</strong>
<%= #survey.name %>
</p>
<ol>
<% #survey.questions.each do |question| %>
<li><%= question.content %>
<ul>
<% for answer in question.answers %>
<li><%= answer.content %></li>
<% end %>
</ul>
</li>
<% end %>
</ol>
<%= link_to 'Edit', edit_survey_path(#survey) %> |
<%= link_to 'Back', surveys_path %>
survey.rb:
class Survey < ActiveRecord::Base
has_many :questions, :dependent => :destroy
accepts_nested_attributes_for :questions, :reject_if => -> (a) {a[:content].blank? }, :allow_destroy => true
end
question.rb:
class Question < ActiveRecord::Base
belongs_to :survey
has_many :answers, :dependent => :destroy
accepts_nested_attributes_for :answers, :reject_if => -> (a) {a[:content].blank? }, :allow_destroy => true
end
answer.rb
class Answer < ActiveRecord::Base
belongs_to :question
end
Any help would be appreciated, I've been stuck on this for hours now!
I don't know if the errors could be related to the fields_for, what happens when you do:
<%= f.fields_for :questions do |question_attribute| %>
<p>
<%= question_attribute.label :content, "Question" %><br />
<%= question_attribute.text_area :content, :rows => 3 %>
</p>
<%= question_attribute.fields_for :answers do |answer_attribute| %>
<p>
<%= answer_attribute.label :content, "Answer" %>
<%= answer_attribute.text_field :content %>
</p>
<% end %>
<% end %>
Let me know what is the outcome of that.
In my post view, I have a _form with a title and releaseDate parameter.
In my controller I get the value from params[:post][:title], but the params[:post][:releaseDate] is empty.
post _form
<%= form_for(#post) do |f| %>
<% if #post.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#post.errors.count, "error") %> prohibited this post from being saved:</h2>
<ul>
<% #post.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :title %><br />
<%= f.text_field :title %>
</div>
<div class="field">
<%= f.label :releaseDate %><br />
<%= f.datetime_select :releaseDate %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
posts_controller
def create
#title = params[:post][:title]
#date = params[:post][:releaseDate]
#post = Post.new(title: #title, releaseDate: #date)
#post.user_id = current_user.id
respond_to do |format|
if #post.save
format.html { redirect_to #post, notice: 'Post was successfully created.' }
format.json { render json: #post, status: :created, location: #post }
else
format.html { render action: "new" }
format.json { render json: #post.errors, status: :unprocessable_entity }
end
end
end
(I am not using #post = Post.new(params[:post]) because I want to do something with the title and releaseDate in the controller.)
post.rb (model)
class Post < ActiveRecord::Base
attr_accessible :releaseDate, :title, :user_id
belongs_to :user
end
Any suggestions on how I can get the datetime value from the form and into my controller?
releaseDate is not rails convention, try to rename field to release_date. Maybe this will help.
To proof this concept you can use so called virtual attributes: add release_date getter and setter to model like this (note that logs can help you to narrow down the problem) :
class Post < ActiveRecord::Base
attr_accessible :releaseDate, :title, :user_id
belongs_to :user
def release_date
date = read_attribute('releaseDate')
logger.debug("READ DATE IS #{date} aND CLASS IS #{date.class}") # see this in rails server logs
end
def release_date=(date)
logger.debug("WRITE DATE IS #{date} aND CLASS IS #{date.class}") # see this in rails server logs
write_attribute('releaseDate', date)
end
end
And in view replace all releaseDate with release_date