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 ...
Related
I need to extract a parameter from my url and insert it into my database for a referral system.
Let's say this user, which is id = 1 has shared his link with another user, the url would be:
https://www.example.com/signup?referredBy=1
When the new user creates his account, I want the field referredBy to be assigned with the value from the referredBy parameter, which should be an Integer.
I've tried to do
#user.referredBy = [:referredBy]
But it didn't worked out.
Any help is appreciated.
Thank you so much.
EDIT
My index.html.erb is:
<% if current_user %>
Logged in as <%= current_user.nomeUsuario %>
<%= link_to "Log out", logout_path %>
<% end %>
<p id=”notice”><%= notice %></p>
<% else %>
<%= link_to "Sign up", signup_path %>
<%= link_to "Log in", login_path %>
<% end %>
My new.html.erb is:
<h1>New User</h1>
<% if current_user %>
<% controller.redirect_to root_url %>
<% else %>
<%= render 'form', user: #user %>
<%= link_to 'Back', login_url %>
<% end %>
My _form.html.erb is:
<%= form_with(model: user) do |form| %>
<% if user.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(user.errors.count, "error") %> prohibited this user from being saved:</h2>
<ul>
<% user.errors.each do |error| %>
<li><%= error.full_message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= form.label :name, "Full Name" %>
<%= form.text_field :nomeUsuario %>
</div>
<div class="field">
<%= form.label :name, "E-mail" %>
<%= form.text_field :email %>
</div>
<div class="field">
<%= form.label :name, "Password" %>
<%= form.password_field :password %>
</div>
<div class="field">
<%= form.label :name, "Password Confirmation" %>
<%= form.password_field :password_confirmation %>
</div>
<div class="field">
<%= form.label :name, "Tipo do Plano" %>
<%= form.select :tipoPlano, ["Gratuito", "Mensal", "Anual"], selected: "Gratuito" %>
</div>
<%= form.hidden_field :indicadoPor, params[:indicadoPor] %>
<div class="actions">
<%= form.submit %>
</div>
<% end %>
My user_controller.rb is:
class UsersController < ApplicationController
before_action :set_user, only: %i[ show edit update destroy ]
# GET /users/new
def new
#user = User.new
end
# GET /users/1/edit
def edit
end
# POST /users or /users.json
def create
#user = User.new(user_params)
set_tipoPlano
#user.indicadoPor = params[:indicadoPor]
respond_to do |format|
if #user.save
format.html { redirect_to root_url, notice: "User was successfully created." }
format.json { render root_url, status: :created, location: #user }
else
format.html { render :new, status: :unprocessable_entity }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /users/1 or /users/1.json
def update
respond_to do |format|
if #user.update(user_params)
set_tipoPlano
format.html { redirect_to root_url, notice: "User was successfully updated." }
format.json { render :show, status: :ok, location: #user }
else
format.html { render :edit, status: :unprocessable_entity }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_user
#user = User.find(params[:id])
end
# Only allow a list of trusted parameters through.
def user_params
params.require(:user).permit(:email, :password, :password_confirmation, :nomeUsuario, :tipoPlano, :valorPlano, :indicadoPor, :comissaoAcumuladaAtual, :comissaoASerRetirada)
end
def set_tipoPlano
if(#user.tipoPlano == "Gratuito")
#user.valorPlano = 0.0
elsif(#user.tipoPlano == "Mensal")
#user.valorPlano = 49.90
elsif(#user.tipoPlano == "Anual")
#user.valorPlano = 39.90
end
end
end
If you need something else, please let me know! Thank you so much for the help.
ANSWER BELOW
I've fixed it.
I just had to change my form to:
<%= form.hidden_field :indicadoPor, value: params[:indicadoPor] %>
I forgot the =, so the form wasn't being rendered. Also, I've removed the #user.referredBy = params[:referredBy] from my controller. Everything is fine now.
Thank you guys, gals and non-binaries for the help so far!
[:referral]
This is an array with a single value. That value is a symbol :referral.
I'm not sure what type your referredBy column is but it's almost certainly going to complain about being given an array of symbols.
You want
params[:referral]
params is a hash like object containing the params in the url/(and sometimes body). So params[:referral] looks up the :referral symbol in the params hash and returns whatever the user provided.
I have two models: Question and Options. Question has has_many relation with Options. I need to add options to question whenever I create a new question. I have written the code but I am not able to send data to the options of Question model. Whenever I create the question and add options in the form, the options to that question are empty. Where is the mistake?
Models
class Question < ApplicationRecord
belongs_to :user
has_many :options
accepts_nested_attributes_for :options
end
class Option < ApplicationRecord
belongs_to :question
end
questions_controller.rb
# GET /questions/new
def new
#question = Question.new
#question.options.build(params[:options])
end
# GET /questions/1/edit
def edit
end
# POST /questions
# POST /questions.json
def create
#question = Question.new(question_params)
puts("---------------------Question options: --------------------------------------------")
puts(#question.options)
#question.user = current_user
respond_to do |format|
if #question.save
format.html { redirect_to #question, notice: 'Question was successfully created.' }
format.json { render :show, status: :created, location: #question }
else
format.html { render :new }
format.json { render json: #question.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /questions/1
# PATCH/PUT /questions/1.json
def update
respond_to do |format|
if #question.update(question_params)
format.html { redirect_to #question, notice: 'Question was successfully updated.' }
format.json { render :show, status: :ok, location: #question }
else
format.html { render :edit }
format.json { render json: #question.errors, status: :unprocessable_entity }
end
end
_form.html.erb
<%= form_with(model: question, local: true) do |form| %>
<% 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 |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= form.label :body %>
<%= form.text_area :body %>
</div>
<%= form.fields_for :address do |a| %>
<div class="field">
<%= a.label :option1 %>
<%= a.text_area :body %>
</div>
<div class="field">
<%= a.label :option2 %>
<%= a.text_area :body %>
</div>
<% end %>
<div class="actions">
<%= form.submit %>
</div>
<% end %>
For this case, I strongly recommend using a FormObject in place of accepts_nested_attributes_for. Here is a quick video on how to implement a FormObject. https://thoughtbot.com/upcase/videos/form_objects
Also, there is a related discussion here on why accepts_nested_attributes_for is not a great option.
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 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
I know that there are many questions a but every solution that i've tried did not work.
I am trying to create a sign in form, but I am getting the following error
First argument in form cannot contain nil or be empty
replacing #user with User.new will solve the error , but than I can't check for #user.errors.any..
any suggestions?
<h1>Sign up</h1>
<div class="row">
<div class="span6 offset7">
<%= form_for #user do |f| %>
<% if #user.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#user.errors.count, "error") %> prohibited this user from being saved:</h2>
<ul>
<% #user.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<%= f.label :name %>
<%= f.text_field :name %>
<%= f.label :email %>
<%= f.text_field :email %>
<%= f.label :password %>
<%= f.password_field :password %>
<%= f.label :password_confirmation, "Confirmation" %>
<%= f.password_field :password_confirmation %>
<br>
<%= f.submit "Create my account", class: "btn btn-large btn-primary" %>
<% end %>
</div>
</div>
and my controller code is
class UsersController < ApplicationController
before_action :set_user, only: [:show]
def new
#user = User.new
end
# POST /user
# POST /user.json
def create
#user = User.new(user_params)
respond_to do |format|
if #user.save
format.html { redirect_to #user, notice: 'User was successfully created.' }
format.json { render action: 'show', status: :created, location: #user }
else
format.html { render action: 'new' }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /user/1
# PATCH/PUT /user/1.json
def update
respond_to do |format|
if #user.update(user_params)
format.html { redirect_to #user, notice: 'User was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
def edit
end
# DELETE /user/1
# DELETE /user/1.json
def destroy
#user.destroy
respond_to do |format|
format.html { redirect_to users_url }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_user
#user = User.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def user_params
params.require(:user).permit(:name, :email, :password)
end
end
In your edit, update and delete actions, you do not set #user.
You should maybe change your before filter:
before_action :set_user, only: [:show, :edit, :update, :destroy]
or
before_action :set_user, except: [:index, :new]