I have a rails form to collect information on people for a family tree application. There are two drop down boxes that are used to assign the parents of the person being edited/created, however when a selection is made in either, or both, of these boxes, it is not committed to the database. It doesn't throw any exceptions, however when I check the database, the fatherID and motherID fields remain as null.
Here is the complete code for the form:
Does anybody have any ideas where I'm going astray?
Thanks.
<%= form_for(#person) do |f| %>
<% if #person.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#person.errors.count, "error") %> prohibited this person from being saved:</h2>
<ul>
<% #person.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :FirstName %><br>
<%= f.text_field :FirstName %>
</div>
<div class="field">
<%= f.label :LastName %><br>
<%= f.text_field :LastName %>
</div>
<div class="field">
<%= f.label :MaidenName %><br>
<%= f.text_field :MaidenName %>
</div>
<div class="field">
<%= f.label :Sex %><br>
<%= f.select(:Sex, options_for_select([['Male', 'M'], ['Female', 'F']]))%>
</div>
<div class="field">
<p>Parents:</p>
Mother: <%= select(:motherID, options_from_collection_for_select(Person.all, :id, :FirstName), :include_blank => true)%>
Father: <%= select(:fatherID, options_from_collection_for_select(Person.all, :id, :FirstName), :include_blank => true)%>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Controller code
class PeopleController < ApplicationController
before_action :set_person, only: [:show, :edit, :update, :destroy]
# GET /people
# GET /people.json
def index
#people = Person.all
end
# GET /people/1
# GET /people/1.json
def show
end
# GET /people/new
def new
#person = Person.new
end
# GET /people/1/edit
def edit
end
# POST /people
# POST /people.json
def create
#person = Person.new(person_params)
respond_to do |format|
if #person.save
format.html { redirect_to #person, notice: 'Person was successfully created.' }
format.json { render action: 'show', status: :created, location: #person }
else
format.html { render action: 'new' }
format.json { render json: #person.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /people/1
# PATCH/PUT /people/1.json
def update
respond_to do |format|
if #person.update(person_params)
format.html { redirect_to #person, notice: 'Person was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #person.errors, status: :unprocessable_entity }
end
end
end
# DELETE /people/1
# DELETE /people/1.json
def destroy
#person.destroy
respond_to do |format|
format.html { redirect_to people_url }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_person
#person = Person.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def person_params
params.require(:person).permit(:FirstName, :LastName, :MaidenName, :Sex)
end
end
Model Code
class Person < ActiveRecord::Base
has_ancestry
end
:motherID and :fatherID need to be in params.require(:person).permit(:FirstName, :LastName, :MaidenName, :Sex) otherwise the controller does not pass these values to the model for them to be saved.
For more information about strong parameters, see the rails guide: http://guides.rubyonrails.org/action_controller_overview.html#strong-parameters
Related
I am currently re-working my routes, which leads to a lot of mistakes in my Rails App. I am coming from something like
users/:user_id/profiles/id/reviews
to
/users/:user_id/profile/reviews
After registering a user gets redirected (redirect_after_sign_up) to a profile
/users/:user_id/profile/new
where the user can fill out the form (a allow nested attributes for profile)
<%= form_for(#user, url: user_profile_path, method: :post) do |form| %>
<div class="field">
<%= form.label :street %>
<%= form.text_area :street %>
</div>
<%= fields_for(:profile) do |profile_fields| %>
<div class="field">
<%= profile_fields.label :about %>
<%= profile_fields.text_area :about %>
</div>
<div class="field">
<%= profile_fields.file_field :avatar %>
<% profile_fields.label "Profile photo" %>
</div>
<% end %>
<div class="actions">
<%= form.submit "Save your profile", class: "btn btn-default" %>
</div>
<% end %>
After I click submit, these data won't save anywhere. The user also won't get redirected to the #show, as, there are obviously some problems with my profiles controller. Neither #show, nor #create works. Here is the controller
class ProfilesController < ApplicationController
before_action :set_profile, only: [:show, :edit, :update, :destroy]
def show
#profile = current_user.profile
#review = Review.new
Review.where(profile: #profile)
end
def new
#user = User.eager_load(:profile).find(params[:user_id])
#profile = Profile.new
end
def edit
#profile = #user.profile
end
def create
#user = current_user
#profile = current_user.build_profile(profile_params)
respond_to do |format|
if #profile.save
format.html { redirect_to user_profile_path(current_user.id), notice: 'Profile was successfully created.' }
format.json { render :show, status: :created, location: #profile }
else
format.html { render :new }
format.json { render json: #profile.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #profile.update(profile_params)
format.html { redirect_to user_profile_path(current_user.id), notice: 'Profile was successfully updated.' }
format.json { render :show, status: :ok, location: #profile }
else
format.html { render :edit }
format.json { render json: #profile.errors, status: :unprocessable_entity }
end
end
end
# DELETE /profiles/1
# DELETE /profiles/1.json
def destroy
#profile.destroy
respond_to do |format|
format.html { redirect_to users_url, notice: 'Profile was successfully destroyed.' }
format.json { head :no_content }
end
end
private
def set_profile
#profile = current_user.profile
end
def profile_params
params.permit(:about, :avatar)
end
end
I really need help adjusting the controller, so it works without a profile_id. Here is the show page, just in case:
<% if #profile == current_user.profile %>
<strong> Welcome </strong><%= current_user.first_name %>
<% else %>
<strong> This is a profile of </strong><%= #profile.user.first_name %> <%= #profile.user.last_name %>
<% end %>
<p>
<strong>About:</strong>
<%= #profile.about %>
</p>
<strong>Profile image</strong>
<%= image_tag(url_for(#profile.avatar), style: 'width:50px; height:50px;') %>
</p>
<%= render 'reviews/form' %>
<% #reviews.each do |review| %>
<%= review.user.first_name %> <%= review.user.last_name %> wrote <small> <%= time_ago_in_words(review.created_at) %> ago </small>
<p>
<%= review.content %>
<br>
<strong> Rating </strong><%= review.rating %>
</p>
<% end %>
<%= link_to 'Edit', edit_user_profile(current_user.profile) %>
<%= link_to 'Show other profiles', users_path %>
<div class="container">
Thank you.
P.S. I tried to work with a ProfileController (single), but this didn't work at all, as the app wouldn't find the controller.
UPDATE:
So, I tried to play with the form, looks like the form won't save neither to profile nor to user. Even if I get rid of the nested attributes, it still doesn't save. This stays unresoled ...
as i can see you're using fields_for, so check a structure od params which are send when posting. I suppose they may look like:
user: { :street, profile_attributes: { :about, :avatar } }
and if yes, you need to change the permitted params method to match what is actually send.
Next advise is to add accepts_nested_attributes_for :profile in user model, and use fields_for proper way by saving profile in addition to saving user, because current code is little messy (form_for user with fields for profile leading to profile controller).
If you don't wan't to deal with nested attributes you may also rewrite form as form_for #profile ...
I know this question has been asked a lot but none of the other solutions worked for me. I have created a scaffold called Properties and have not changed any of the code for it, when I click on the automatically generated link to create a new property, it throws the error message in the title, specifically targeting my def set_property in my properties_controller. I have already created a default scaffold for Users which worked perfectly, which is why I am very confused.
I am on rails v 5.0.2 and ruby v 2.3.3
My Routes.rb:
Rails.application.routes.draw do
get 'sessions/create'
get 'sessions/destroy'
get 'users/about'
resources :users
resources :properties
get 'admin' => 'admin#index'
controller :sessions do
get 'login' => :new
post 'login' => :create
delete 'logout' => :destroy
end
root 'users#home'
end
My properties_controller.rb
class PropertiesController < ApplicationController
before_action :set_property, only: [:show, :edit, :update, :destroy, :new]
# GET /properties
# GET /properties.json
def index
#properties = Property.all
end
# GET /properties/1
# GET /properties/1.json
def show
end
# GET /properties/new
def new
#property = Property.new
end
# GET /properties/1/edit
def edit
end
# POST /properties
# POST /properties.json
def create
#property = Property.new(property_params)
respond_to do |format|
if #property.save
format.html { redirect_to #property, notice: 'Property was successfully created.' }
format.json { render :show, status: :created, location: #property }
else
format.html { render :new }
format.json { render json: #property.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /properties/1
# PATCH/PUT /properties/1.json
def update
respond_to do |format|
if #property.update(property_params)
format.html { redirect_to #property, notice: 'Property was successfully updated.' }
format.json { render :show, status: :ok, location: #property }
else
format.html { render :edit }
format.json { render json: #property.errors, status: :unprocessable_entity }
end
end
end
# DELETE /properties/1
# DELETE /properties/1.json
def destroy
#property.destroy
respond_to do |format|
format.html { redirect_to properties_url, notice: 'Property was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_property
#property = Property.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def property_params
params.require(:property).permit(:name, :price, :bed, :bath, :car, :inspect)
end
end
The link I press to get the message:
<%= link_to 'New Property', new_property_path %>
New property page:
<h1>New Property</h1>
<%= render 'form', property: #property %>
<%= link_to 'Back', properties_path %>
and the form that this page renders:
<%= form_for(property) do |f| %>
<% if property.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(property.errors.count, "error") %> prohibited this property from being saved:</h2>
<ul>
<% property.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 :price %>
<%= f.number_field :price %>
</div>
<div class="field">
<%= f.label :bed %>
<%= f.number_field :bed %>
</div>
<div class="field">
<%= f.label :bath %>
<%= f.number_field :bath %>
</div>
<div class="field">
<%= f.label :car %>
<%= f.number_field :car %>
</div>
<div class="field">
<%= f.label :inspect %>
<%= f.text_field :inspect %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Remove :new from before_action :set_property:
before_action :set_property, only: [:show, :edit, :update, :destroy]
set_property searches for an id attribute in the params hash and then sets the #property with the property (record from the db) that matches that id, but with new you don't want to search for an existing property, you are creating a new one. So thats why new method sets #property with Property.new:
# GET /properties/new
def new
#property = Property.new
end
It creates the object, says that it was successfully created, but all fields are saved in the database with nil values. Only created_at and updated_at are saved normally.
Some methods of my controllers/admin/categories_controller.rb
def new
#admin_category = Category.new
end
# GET /admin/categories/1/edit
def edit
end
# POST /admin/categories
# POST /admin/categories.json
def create
#admin_category = Category.new(params[:category])
respond_to do |format|
if #admin_category.save
format.html { redirect_to admin_category_path(#admin_category), notice: 'Category was successfully created.' }
format.json { render :show, status: :created, location: admin_category_path(#admin_category) }
else
format.html { render :new }
format.json { render json: #admin_category.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /admin/categories/1
# PATCH/PUT /admin/categories/1.json
def update
respond_to do |format|
if #admin_category.update(admin_category_params)
format.html { redirect_to #admin_category, notice: 'Category was successfully updated.' }
format.json { render :show, status: :ok, location: #admin_category }
else
format.html { render :edit }
format.json { render json: #admin_category.errors, status: :unprocessable_entity }
end
end
end
This is my models/category model:
class Category < ActiveRecord::Base
belongs_to :category
end
This is my routes.br file
namespace :admin do
resources :categories
end
My views/admin/categories/_form.html.erb
<%= form_for(#admin_category, url: admin_categories_path) do |f| %>
<% if #admin_category.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#admin_category.errors.count, "error") %> prohibited this admin_category from being saved:</h2>
<ul>
<% #admin_category.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>
<div class="field">
<%= f.label :is_active %><br>
<%= f.check_box :is_active %>
</div>
<div class="field">
<%= f.label :main_menu %><br>
<%= f.check_box :main_menu %>
</div>
<div class="field">
<%= f.label :category_id %><br>
<%= f.number_field :category_id %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
And when I try to edit, I get this error:
No route matches [PATCH] "/admin/categories"
I'm very newbie to Ruby on Rails, so I would apreciate any help!
Thanks!
You are only passing :category when creating a new Category:
def create
#admin_category = Category.new(params[:category])
Change it to Category.new(user_params) and try again. This will pass on all parameters you're creating and feed it to the database.
Also, permit the parameters you are trying to pass:
def user_params
params.require(:admin_category).permit(:name, :is_active, :main_menu, :category_id)
end
Strong Params:
#app/controllers/categories_controller.rb
class CategoriesController < ApplicationController
def create
#admin_category = Category.new category_params
end
private
def category_params
params.require(:category).permit(:name, :is_active, :main_menu, :category_id)
end
end
--
As a tip, if you're using nested objects with forms, you can pass both objects in an array to create the nested path:
#app/views/admin/categories/new.html.erb
<%= form_for [:admin, #admin_category] do |f| %>
I'm trying to link movies with a specific genre via a form in rails. I have seeded several genre instances in the db and have created a select tag that should, in theory, give a movie a genre_id based on the genres seeded.
Here is my Movie Migration:
class CreateMovies < ActiveRecord::Migration
def change
create_table :movies do |t|
t.string :name
t.integer :year
t.string :director
t.string :lead_actor
t.references :genre, index: true, foreign_key: true
t.timestamps null: false
end
end
end
Here is the form:
<%= form_for(#movie) do |f| %>
<% if #movie.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#movie.errors.count, "error") %> prohibited this movie from being saved:</h2>
<ul>
<% #movie.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :genre_id %><br>
<%= f.select(:genre_id, #genres.map {|p| [ p.name, p.id ] }) %>
</div>
<div class="field">
<%= f.label :name %><br>
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :year %><br>
<%= f.number_field :year %>
</div>
<div class="field">
<%= f.label :director %><br>
<%= f.text_field :director %>
</div>
<div class="field">
<%= f.label :lead_actor %><br>
<%= f.text_field :lead_actor %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
All of my dropdown boxes are being displayed properly, but when I go into the database and check the movies genre_id, it equals 'nil'.
Full controller:
class MoviesController < ApplicationController
before_action :set_movie, only: [:show, :edit, :update, :destroy]
# GET /movies
# GET /movies.json
def index
#movies = Movie.all
end
# GET /movies/1
# GET /movies/1.json
def show
end
# GET /movies/new
def new
#movie = Movie.new
#genres = Genre.all
end
# GET /movies/1/edit
def edit
end
# POST /movies
# POST /movies.json
def create
#movie = Movie.new(movie_params)
respond_to do |format|
if #movie.save
format.html { redirect_to #movie, notice: 'Movie was successfully created.' }
format.json { render :show, status: :created, location: #movie }
else
format.html { render :new }
format.json { render json: #movie.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /movies/1
# PATCH/PUT /movies/1.json
def update
respond_to do |format|
if #movie.update(movie_params)
format.html { redirect_to #movie, notice: 'Movie was successfully updated.' }
format.json { render :show, status: :ok, location: #movie }
else
format.html { render :edit }
format.json { render json: #movie.errors, status: :unprocessable_entity }
end
end
end
# DELETE /movies/1
# DELETE /movies/1.json
def destroy
#movie.destroy
respond_to do |format|
format.html { redirect_to movies_url, notice: 'Movie was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_movie
#movie = Movie.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def movie_params
params.require(:movie).permit(:name, :year, :director, :lead_actor)
end
end
I get "3 errors prohibited this event from being saved:Title can't be blank Date can't be blank Description can't be blank. it was working perfectly but not sure whats wrong with it now?
When they are not even blank?
here is the controller.
class EventsController < ApplicationController
before_action :authenticate_user!, :only => [:create , :destroy]
before_action :set_event, only: [:show, :edit, :update, :destroy]
# GET /events
# GET /events.json
def index
#events = Event.all
end
# GET /events/1
# GET /events/1.json
def show
end
# GET /events/new
def new
#event = Event.new
end
# GET /events/1/edit
def edit
end
# POST /events
# POST /events.json
def create
#event = Event.new(event_params)
respond_to do |format|
if #event.save
format.html { redirect_to #event, notice: 'Event was successfully created.' }
format.json { render :show, status: :created, location: #event }
else
format.html { render :new }
format.json { render json: #event.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /events/1
# PATCH/PUT /events/1.json
def update
respond_to do |format|
if #event.update(event_params)
format.html { redirect_to #event, notice: 'Event was successfully updated.' }
format.json { render :show, status: :ok, location: #event }
else
format.html { render :edit }
format.json { render json: #event.errors, status: :unprocessable_entity }
end
end
end
# DELETE /events/1
# DELETE /events/1.json
def destroy
#event.destroy
respond_to do |format|
format.html { redirect_to events_url, notice: 'Event was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_event
#event = Event.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def event_params
params.require(:event).permit(:title, :date, :description)
end
end
Here is the form:
<%= form_for(#event) do |f| %>
<% if #event.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#event.errors.count, "error") %> prohibited this event from being saved:</h2>
<ul>
<% #event.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 :date %><br>
<%= f.date_select :date %>
</div>
<div class="field">
<%= f.label :description %><br>
<%= f.text_area :description %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
model code as per request :
class Event < ActiveRecord::Base
validates_presence_of :title , :date, :description
validates_uniqueness_of :title
end
Problem was with one of the gems I have installed which I have now removed. working now.