Im trying to edit a field so that it goes in the database as the owner boolean being set to true when the user creates the account. I get the error undefined method `owner
= form_for #school do |f|
= f.label :school_name, "School Name"
= f.text_field :school_name, :class => 'form-control'
= f.label :latitude, "Latitude"
= f.text_field :latitude, :class => 'form-control'
= f.label :longitude, "Longitude"
= f.text_field :longitude, :class => 'form-control'
= f.label :radius, "Radius"
= f.text_field :radius, :class => 'form-control'
= f.fields_for :admins do |ff|
= ff.label :email
= ff.text_field :email, :class => 'form-control'
= ff.label :password
= ff.password_field :password, :class => 'form-control'
= ff.label :password_confirmation
= ff.password_field :password_confirmation, :class => 'form-control'
= f.submit :class => 'submit-button'
def new
#school = School.new
#school.admins.build
#school.admins.owner = true
end
def create
#school = School.new(school_params)
if #school.save
redirect_to :action => 'show', :id => #school
else
render 'new'
end
Because #school.admins is a collection of multiple admins, so it doesn't have the owner method, that exists on the individual admin objects within that collection.
When you call #school.admins.build it returns a new instance of Admin, but you're not doing anything with that instance. You need to put it in a variable, and then assign a value to its owner attribute. That will look like this:
#school = School.new
#admin = #school.admins.build
#admin.owner = true
But the build method takes an attributes argument, so you can shorten that to this:
#school = School.new
#admin = #school.admins.build(owner: true)
Don't forget that you'll also need to save this object at some point.
Related
I have been struggeling with a nested form for a while and I dont know why it is not working.
The form updates/creates the venue without complaint, but not the associated venue_image.
Problem: I want to create/update a model and one of its associated models at the same time. Please note that the controllers are namespaced under "admin"
_form.haml
.col-md-12
= form_for([:admin, venue], html: { class: 'form-horizontal', multipart: true }) do |f|
- if venue.errors.any?
.col-md-12.alert.alert-danger{role: "alert"}
%h2
= pluralize(venue.errors.count, "Error")
%ul
- venue.errors.full_messages.each do |message|
%li= message
.form-group
= f.label :name, class: 'col-md-2 control-label'
.col-md-10
= f.text_field :name, class: 'form-control'
.form-group
= f.label :category, class: 'col-md-2 control-label'
.col-md-10
= f.text_field :category, class: 'form-control'
.form-group
= f.label :description, class: 'col-md-2 control-label'
.col-md-10
= f.text_area :description, rows: 5, class: 'form-control'
.form-group
= f.label :street, class: 'col-md-2 control-label'
.col-md-10
= f.text_field :street, class: 'form-control'
.form-group
= f.label :zip, class: 'col-md-2 control-label'
.col-md-10
= f.text_field :zip, class: 'form-control'
.form-group
= f.label :city, class: 'col-md-2 control-label'
.col-md-10
= f.text_field :city, class: 'form-control'
.form-group
= f.label :homepage, class: 'col-md-2 control-label'
.col-md-10
= f.url_field :homepage, class: 'form-control'
%h3 Add images
= f.fields_for(:venue_image, html: { class: 'form-horizontal', multipart: true }) do |vi|
.form-group
= vi.label :name, class: 'col-md-2 control-label'
.col-md-10
= vi.input :name, label: false, class: 'form-control'
.form-group
= vi.label :venue_id, class: 'col-md-2 control-label'
.col-md-10
= vi.input :venue_id, label: false, class: 'form-control'
.form-group
= vi.label :default, class: 'col-md-2 control-label'
.col-md-10
= vi.input :default, as: :radio_buttons, label: false, class: 'form-control radio radio-inline'
.form-group
= vi.label :image_file, class: 'col-md-2 control-label'
.col-md-10
= vi.file_field :image_file, label: false, class: 'form-control'
.actions
= f.submit 'Save', class: 'btn btn-primary pull-right'
= link_to 'Cancel', :back, class: 'btn btn-default'
venues_controller
class Admin::VenuesController < Admin::BaseController
before_action :set_venue, only: [:show, :edit, :update, :destroy]
def index
#venues = Venue.all
end
def show
end
def new
#venue = Venue.new
#venue.venue_images.build
end
def edit
end
def create
#venue = Venue.new(venue_params)
if #venue.save
redirect_to admin_venue_path(#venue), notice: 'Venue was successfully created.'
else
render :new
end
end
def update
if #venue.update(venue_params)
redirect_to admin_venue_path(#venue), notice: 'Venue was successfully updated.'
else
render edit_admin_venue
end
end
def destroy
#venue.destroy
redirect_to admin_venues_url, notice: 'Venue was successfully destroyed.'
end
private
def set_venue
#venue = Venue.find(params[:id])
end
def venue_params
params.require(:venue).permit(:name, :category, :description, :street, :zip, :city, :homepage,
venue_image_attributes: [:name, :default, :image_file])
end
end
venue_images_controller
class Admin::VenueImagesController < Admin::BaseController
def new
image = VenueImage.new
render locals: { image: image }
end
def create
# TODO: Remove # if possible
#image = VenueImage.new(venue_images_params)
if #image.save
redirect_to admin_venue_path(#image.venue.id), notice: 'Image was successfully created.'
else
render admin_new_venue_path
end
end
private
def venue_images_params
params.require(:venue_image).permit(:name, :default, :image_file, :venue_id)
end
end
routes
namespace :admin do
resources :venues do
resources :venue_images
end
resources :users
end
Thanks in advance for any help! Please let me know if you need more of the code.
Seems like you have a has_many relation with the Venue(i.e, has_many :venue_images), then this line
= f.fields_for(:venue_image, html: { class: 'form-horizontal', multipart: true }) do |vi|
should be
= f.fields_for(:venue_images, html: { class: 'form-horizontal', multipart: true }) do |vi|
And your venue_params method should be like below
def venue_params
params.require(:venue).permit(:id, :name, :category, :description, :street, :zip, :city, :homepage, venue_images_attributes: [:id, :name, :default, :image_file])
end
Notice the plural venue_images and also I added :id to venue_params for Update to work correctly.
Im trying to submit a nested form when you create a school, you can also create a admin with it. When I try to save the form with the default value of owner set to true and status set to active, it saves the form but doesnt save those values in the database
class SchoolsController < ApplicationController
before_filter :authenticate_admin!, except: [:index, :new, :create]
def show
#school = School.friendly.find(params[:id])
end
def new
#school = School.new
#admin = #school.admins.build(:owner => true, :status => "active")
end
def create
#school = School.new(school_params)
if #school.save
redirect_to new_admin_session_path
else
render 'new'
end
end
def edit
#school = School.find_by_slug(params[:id])
end
def update
#school = School.find_by_slug(params[:id])
if #school.update_attributes(school_params)
redirect_to :action => 'show', :id => #school
else
render :action => 'edit'
end
end
def team
#teams = Admin.all
end
private
def school_params
params.require(:school).permit(:school_name, :latitude, :longitude, :radius, admins_attributes: [ :first_name, :last_name, :email, :password, :password_confirmation, :image ])
end
end
class School < ActiveRecord::Base
has_many :admins
accepts_nested_attributes_for :admins
extend FriendlyId
friendly_id :school_name, use: :slugged
def should_generate_new_friendly_id?
school_name?
end
# Validation
validates :school_name, presence: true, uniqueness: true
validates :latitude, presence: true
validates :longitude, presence: true
validates :radius, presence: true, numericality: { only_integer: true }
end
%nav.navbar.navbar-default.navbar-fixed-top{role:"navigation"}
%div.container
%div.navbar-header
%button.navbar-toggle.collapsed{"data-toggle" => "collapse", "data-target" => "#navbar", "aria-expanded" => "false", "aria-controls" => "navbar"}
%span.sr-only Toggle Navigation
%span.icon-bar
%span.icon-bar
%span.icon-bar
%a.navbar-brand{"href" => "/", "id"=> "brand"} QuickAlert
%div#navbar.collapse.navbar-collapse
%ul.nav.navbar-nav.main-menu
%li.active
%a{"href" => "#"} Home
%li
%a{"href" => "#about"} About
%li
%a{"href" => "#contact"} Contact
%div.container-fluid
%div.row
%div.school-create
- if #school.errors.any?
%ul
- #school.errors.full_messages.each do |msg|
%li
= msg
%div#map-check
%h2.header School Info
= form_for #school do |f|
= f.label :school_name, "School Name"
= f.text_field :school_name, :class => 'form-control'
= f.label :latitude, "Latitude"
= f.text_field :latitude, :class => 'form-control', :id => "latitude"
= f.label :longitude, "Longitude"
= f.text_field :longitude, :class => 'form-control', :id => "longitude"
= f.label :radius, "Radius"
= f.text_field :radius, :class => 'form-control', :id => "radius"
%div.admin-fields
%h2.header Admin Info
= f.fields_for :admins do |ff|
= ff.label :first_name
= ff.text_field :first_name, :class => 'form-control'
= ff.label :last_name
= ff.text_field :last_name, :class => 'form-control'
= ff.label :email
= ff.text_field :email, :class => 'form-control'
= ff.label :password
= ff.password_field :password, :class => 'form-control'
= ff.label :password_confirmation
= ff.password_field :password_confirmation, :class => 'form-control'
= ff.file_field :image
= f.submit :class => 'submit-button btn btn-primary'
I am using devise, and is having an issue if you try to signup with an existing email.
When you signup you do it from this url:
http://localhost:3000/accounts/new
So I have an account, where I add a user (devise). If I try to signup as a user which already exists I get the correct error:
"Users email has already been taken"
But it redirects to http://localhost:3000/accounts
The controller looks a bit like this:
def create
name = account_params[:name]
first_name = Modules::NameHelpers.get_first_name(name)
last_name = Modules::NameHelpers.get_last_name(name)
#account = Account.new(account_params_wo_user_name)
#account.users.first.first_name = first_name
#account.users.first.last_name = last_name
respond_to do |format|
if #account.save
sign_in #account.users.first
format.html { redirect_to root_path, notice: "Thanks for signing up." }
format.json { render action: 'show', status: :created, location: #account }
else
format.html { render action: 'new' }
format.json { render json: #account.errors, status: :unprocessable_entity }
end
end
end
I can't seem to find what redirects to the index page.
Update:
Here is the form:
<%= form_for(#account) do |f| %>
<%= render 'shared/error_messages', :object => f.object %>
<div>
<%= f.label :name, 'Account Name' %> <br />
<%= f.text_field :name, :required => true, :placeholder => 'Your account name' %>
</div>
<%= f.fields_for :users do |user_form| %>
<div><%= user_form.label :name %><br />
<%= user_form.text_field :name, :autofocus => true, :required => true, :placeholder => 'Your name' %></div>
<div><%= user_form.label :email %><br />
<%= user_form.email_field :email, :required => true, :placeholder => 'Your email' %></div>
<div><%= user_form.label :password, :required => true %><br />
<%= user_form.password_field :password, :required => true, :placeholder => 'Enter a 8 character password'%></div>
<div><%= user_form.label :password_confirmation, :required => true %><br />
<%= user_form.password_field :password_confirmation, :required => true, :placeholder => 'Confirm password' %></div>
<% end %>
<div><%= f.submit "Sign up" %></div>
<% end %>
I am new to Rails. Getting the error below. I understand what the issue is, but not sure how to fix it?
Error - param is missing or the value is empty: customer
def customer_params
params.require(:customer).permit(
:first_name,
:last_name,
:email,
:password,
:password_confirmation)
end
end
DetailsController.rb
class My::Account::DetailsController < MyController
def show
#customer = current_user
end
def update
#customer = current_user
#customer.update_attributes(customer_params)
if #customer.errors.any?
render :action => :show
else
redirect_to my_account_details_path, :notice => 'Account details updated'
end
end
private
def customer_params
params.require(:customer).permit(
:first_name,
:last_name,
:email,
:password,
:password_confirmation)
end
end
View
.account.container
.row
= render :partial => '/my/account/sidebar'
.section
%h2 Your account details
= simple_form_for #customer, :url => my_account_details_path, :method => :put, :html => { :class => 'form-horizontal'} do |form|
.field
= form.input :first_name
.field
= form.input :last_name
.field
= form.input :email, :as => :email
%hr
%h4 Leave password fields blank to keep the existing password
%hr
.field
= form.input :password, :input_html => { :value => '' }
.field
= form.input :password_confirmation, :input_html => { :value => '' }
.field-actions
%button.btn.btn-primary{type: "submit"} Save
It is because it is coming through as user and not customer. Which I believe is because you are using current_user which is a User and not a Customer (guessing from the code). Change it to be params.require(:user).permit(blah)
Recently, I decided to split my User Form into an Edit & Account Form.
User Edit Form
-Name
-Username
-AboutMe
User Account Form
-Email
-Password
-Password Confirmation
The routes work fine and everything gets updated accordingly. But for some reason, when my User Model validates the Email Presence & it Fails, it renders the Edit Form with the appropriate Error Messages as oppose to the Account Form.
How can I set up my Update Method in my Controller to know which form to Render with the appropriate error messages?
Model
class User < ActiveRecord::Base
attr_accessible :name, :email, :password, :password_confirmation, :username
validates :username, :presence => true,
:length => { :maximum => 15 },
:format => { :with => VALID_UNAME_REGEX },
:uniqueness => { :case_sensitive => false }
validates :email, presence: true,
format: { with: VALID_EMAIL_REGEX },
uniqueness: { case_sensitive: false }
validates :password, presence: true, length: { minimum: 6 }, :if => :password #only validate if password changed!
validates :password_confirmation, presence: true, :if => :password
end
Views
Edit View
<%= form_for #user, :html => { :multipart => true } do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<div class="statictitle">Your Profile</div>
<%= f.text_field :username, placeholder: "Username..", :class => "form-control" %>
<%= f.text_field :name, placeholder: "Name", :class => "form-control" %>
<%= f.text_area :bio, placeholder: "About yourself in 160 characters or less...", class: "textinput" %>
<%= f.submit "Update Profile", class: "btn btn-primary" %><br>
<% end %>
Account View
<%= form_for #user, :html => { :multipart => true } do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<div class="statictitle">Your Account</div>
<%= f.text_field :email, placeholder: "Email", :class => "form-control" %>
<%= f.password_field :password, placeholder: "Password", :class => "form-control" %>
<%= f.password_field :password_confirmation, placeholder: "Password Confirmation", :class => "form-control" %>
<%= f.submit "Update Account", class: "btn btn-primary" %><br>
<% end %>
Controller
class UsersController < ApplicationController
def edit
#user = User.find_by_username(params[:id])
end
def account
#title = "Account"
#user = User.find_by_username(params[:id])
end
def update
#user = User.find(current_user.id)
if #user.update_attributes(params[:user])
flash[:success] = "Profile updated"
sign_in #user
redirect_to user_url
else
render 'edit' ###I can't seem to figure out how to render the correct form
end
end
end
Routes
resources :users do
member do
get :account
end
end
You can check the HTTP Referer in this case which will tell you where the request came from and accordingly render your view.
for eg:
if URI(request.referer).path == edit_user_path
render :edit
else
render :account
end