I am new to spree and ruby on rails. while creating a custom controller in my spree app, I can successfully add link to it in spree admin panel using deface. but when I go to that link, it gives me following error
NoMethodError in Spree::Admin::Societies#new
Showing app/views/spree/admin/societies/_form.html.erb where line #1 raised:
undefined method `societies_path' for #<#<Class:0x007f19cb636898>:0x007f19c5ecacf8>
I don't know from where it is looking for 'societies_path' as I already have updated app/views/spree/admin/societies/new.html.erb to look for 'admin_societies_path', here it is
<%= render 'form' %>
<%= link_to 'Back', admin_societies_path %>
and app/views/spree/admin/societies/_form.html.erb contains
<%= form_for(#society) do |f| %>
<% if #society.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#society.errors.count, "error") %> prohibited this society from being saved:</h2>
<ul>
<% #society.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 :address %><br>
<%= f.text_field :address %>
</div>
<div class="field">
<%= f.label :area %><br>
<%= f.text_field :area %>
</div>
<div class="field">
<%= f.label :postcode %><br>
<%= f.number_field :postcode %>
</div>
<div class="field">
<%= f.label :city %><br>
<%= f.text_field :city %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
I tried removing link to back also, but it's again giving same error.
config/routes.rb is
mount Spree::Core::Engine, :at => '/'
Spree::Core::Engine.add_routes do
namespace :admin do
resource :societies
end
end
and my app/controllers/spree/admin/societies_controller.rb is
module Spree
module Admin
class SocietiesController < Spree::Admin::BaseController
before_action :set_society, only: [:show, :edit, :update, :destroy]
def index
#societies = Society.all
end
def show
end
def new
#society = Society.new
end
def edit
end
def create
#society = Society.new(society_params)
respond_to do |format|
if #society.save
format.html { redirect_to #society, notice: 'Society was successfully created.' }
format.json { render :show, status: :created, location: #society }
else
format.html { render :new }
format.json { render json: #society.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #society.update(society_params)
format.html { redirect_to #society, notice: 'Society was successfully updated.' }
format.json { render :show, status: :ok, location: #society }
else
format.html { render :edit }
format.json { render json: #society.errors, status: :unprocessable_entity }
end
end
end
def destroy
#society.destroy
respond_to do |format|
format.html { redirect_to societies_url, notice: 'Society was successfully destroyed.' }
format.json { head :no_content }
end
end
private
def set_society
#society = Society.find(params[:id])
end
def society_params
params.require(:society).permit(:name, :url, :building_number, :address, :area, :postcode, :city, :active, :IsDelete)
end
end
end
end
Any help would be greatly appreciated.
I would suspect that it is this line in _form partial
<%= form_for(#society) do |f| %>
You need to reference the namespace here, so maybe somthing like
<%= form_for([:admin, #society]) do |f| %>
or add your own url
<%= form_for(#society, url: admin_societies_path) do |f| %>
Related
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| %>
Hi I know this has been asked many times but none of those could help me.
I'm building an online clinic website based on ruby on rails.
When a user wants to sign up it chooses either Doctor or Patient. After that a sign-in form appears.
In DB, there's a general table for users for common attributes like name, gender etc. In that table the user type in set. For Doctor and Patient there are two separate tables for their specific attributes.
Here's the problem!
When signing up I get the error: raise ParameterMissing.new(key)
Here's thee code for doctor_controller.rb:
class DoctorsController < ApplicationController
before_action :set_doctor, only: [:show, :edit, :update, :destroy]
#before_save :set_type
# GET /doctors
# GET /doctors.json
def index
#doctors = Doctor.all
end
# GET /doctors/1
# GET /doctors/1.json
def show
end
# GET /doctors/new
def new
#doctor = Doctor.new
#user=User.new
#user.user_type='2'
end
# GET /doctors/1/edit
def edit
end
# POST /doctors
# POST /doctors.json
def create
#user=User.new(user_params)
respond_to do |format|
if #user.save
format.html { redirect_to #user, notice: 'Doctor was successfully created.' }
format.json { render :show, status: :created, location: #doctor }
else
format.html { render :new }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
#doctor = Doctor.new(doctor_params)
respond_to do |format|
if #doctor.save
format.html { redirect_to #doctor, notice: 'Doctor was successfully created.' }
format.json { render :show, status: :created, location: #doctor }
else
format.html { render :new }
format.json { render json: #doctor.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /doctors/1
# PATCH/PUT /doctors/1.json
def update
respond_to do |format|
if #doctor.update(doctor_params)
format.html { redirect_to #doctor, notice: 'Doctor was successfully updated.' }
format.json { render :show, status: :ok, location: #doctor }
else
format.html { render :edit }
format.json { render json: #doctor.errors, status: :unprocessable_entity }
end
end
end
# DELETE /doctors/1
# DELETE /doctors/1.json
def destroy
#doctor.destroy
respond_to do |format|
format.html { redirect_to doctors_url, notice: 'Doctor was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_doctor
#doctor = Doctor.find(params[:id])
#user = User.find(params[:id])
end
def set_type
#user.user_type="2"
end
# Never trust parameters from the scary internet, only allow the white list through.
def doctor_params
params.require(:doctor).permit(:user_id, :doctroNum, :adderess, :sepciality, :records)
end
def user_params
params.require(:user).permit(:user_type, :username, :password, :name, :family, :gender, :phone, :city, :profilepicture)
end
end
and here is the code for signup form:
<%= 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 |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :username, "Email" %><br>
<%= f.email_field :username %>
</div>
<div class="field">
<%= f.label :password %><br>
<%= f.password_field :password %>
</div>
<div class="field">
<%= f.label :name %><br>
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :family %><br>
<%= f.text_field :family %>
</div>
<div class="field">
<%= f.label :gender %><br>
<%= f.text_field :gender %>
</div>
<div class="field">
<%= f.label :phone %><br>
<%= f.text_field :phone %>
</div>
<div class="field">
<%= f.label :city %><br>
<%= f.text_field :city %>
</div>
<% end %>
<%= form_for(#doctor) do |f| %>
<% if #doctor.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#doctor.errors.count, "error") %> prohibited this doctor from being saved:</h2>
<ul>
<% #doctor.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :doctroNum %><br>
<%= f.text_field :doctroNum %>
</div>
<div class="field">
<%= f.label :adderess %><br>
<%= f.text_field :adderess %>
</div>
<div class="field">
<%= f.label :sepciality %><br>
<%= f.text_field :sepciality %>
</div>
<div class="field">
<%= f.label :records %><br>
<%= f.text_field :records %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
I know it's too much. I'd be really thankful
There is no f.submit button for form_for(#user), so whenever you press the submit button, the form_for(#doctor)'s submit button gets called. Hence, the params that are sent forward, always include doctor, and never include user. But the code in your create method expects params to have user in it: #user = User.new(user_params) - therefore, it is generating param is missing or the value is empty: user.
Apart from it, you are not following the good practices. You controller name is DoctorsController, but you are mixing it with the user's code. You should have two separate controllers: DoctorsController, UsersController, and accordingly two different views.
I have a User model, which has_one prestataire and has_one employeur. Previously on stackoverflow, someone advised me to declare singular resources, like:
resources :users do
resource: employeur
resource: prestataire
end
Instead of:
resources :users do
resources: employeurs
resources: prestataires
end
Thanks to rails, I didn't had to singularize all my controllers and views name files. Yet, when I create a user and am redirected to the employeur form, I get undefined method `user_employeurs_path', which is right since I only have a user_employeur_path. But I didn't ask for the plural in my user controller. Rails indicates that this NoMethodError happens in the first line of my employeur form <%= form_for [#user, #employeur] do |f| %>, where one is redirected when a user is saved.
class UsersController < ApplicationController
#TODO index user doit être suprimé quand inutile pour dev
def index
#users = User.all
end
def show
#user = User.find(params[:id])
end
def new
#user = User.new
end
# GET /users/1/edit
def edit
#user = User.find(params[:id])
end
# POST /users
# POST /users.json
def create
#user = User.new(user_params)
respond_to do |format|
if #user.save
if params[:commit] == 'Prestataire'
format.html { redirect_to new_user_prestataire_path(user_id: #user), notice: "Renseignez vos informations d'employeur" }
format.json { render action: 'show', status: :created, location: #user }
else
format.html { redirect_to new_user_employeur_path(user_id: #user), notice: "Renseignez vos informations de prestataire" }
format.json { render action: 'show', status: :created, location: #user }
end
else
format.html { render action: 'new' }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /users/1
# PATCH/PUT /users/1.json
def update
#user = User.find(params[:id])
respond_to do |format|
if #user.update(user_params)
if params[:commit] == 'Prestataire'
format.html { redirect_to new_user_prestataire_path(user_id: #user), notice: 'User was successfully updated.' }
format.json { head :no_content }
else
format.html { redirect_to new_user_employeur_path(user_id: #user), notice: "User was successfully updated." }
format.json { head :no_content }
end
else
format.html { render action: 'edit' }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
# DELETE /users/1
# DELETE /users/1.json
def destroy
#user = User.find(params[:id])
#user.destroy
respond_to do |format|
format.html { redirect_to users_url }
format.json { head :no_content }
end
end
private
def user_params
params.require(:user).permit(:email, :password, :password_confirmation, :surname, :forename, :civility, :phone)
end
end
User form:
<%= 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 %>
<div class="field">
<%= f.label :civility, 'Titre de civilité: ' %><br>
<%= f.text_field :civility %>
</div>
<div class="field">
<%= f.label :forename, 'Prénom: ' %><br>
<%= f.text_field :forename %>
</div>
<div class="field">
<%= f.label :surname, 'Nom de famille: ' %><br>
<%= f.text_field :surname %>
</div>
<div class="field">
<%= f.label :email, 'Email: ' %><br>
<%= f.text_field :email %>
</div>
<div class="field">
<%= f.label :password, 'Mot de passe: ' %><br>
<%= f.password_field :password, size: 40 %>
</div>
<div class="field">
<%= f.label :password_confirmation, 'Confirmation de mot de passe: ' %><br>
<%= f.password_field :password_confirmation, size: 40 %>
</div>
<div class="field">
<%= f.label :phone, 'Numéro de téléphone: ' %><br>
<%= f.text_field :phone %>
</div>
<div class="actions">
<%= f.submit "Employeur" %>
<%= f.submit "Prestataire" %>
</div>
<% end %>
Employeur form:
<%= form_for [#user, #employeur] do |f| %>
<% if #employeur.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#employeur.errors.count, "error") %> prohibited this employeur from being saved:</h2>
<ul>
<% #employeur.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :siren, 'Siren: ' %><br>
<%= f.text_field :siren %>
</div>
<div class="field">
<%= f.label :societe, 'Société: ' %><br>
<%= f.text_field :societe %>
</div>
<div class="field">
<%= f.label :code_postal, 'Code Postal: ' %><br>
<%= f.text_field :code_postal %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
As for my new.html document for employeur:
<h1>New employeur</h1>
<%= render 'form' %>
Here is what's happening:
when you pass <%= form_for [#user, #employeur] do |f| %>, Rails will connect the objects (#user & #employeur) in the order you passed and the then append path to it. So this becomes user_employeurs_path. by convention it will pluralize your the last object (employeur) to infer your controller's name. that's how it gets: user_employeurs_path
so you would either have to pluralize your controller's resources to follow the convention. Or pass url to your path:
<%= form_for [#user, #employeur], url: user_employeur_path do |f| %>
I believe you can use url parameter in this case. Try something like:
<%= form_for [#user, #employeur], url: user_employeur_path do |f| %>
...
Below are my models:
class Ticket < ActiveRecord::Base
attr_accessible :issue, :logs_attributes
has_many :logs
accepts_nested_attributes_for :logs
end
class Log < ActiveRecord::Base
attr_accessible :detail, :ticket_id
belongs_to :ticket
end
I'm trying to figure out how to create new log via the ticket view, but I can't get the detail field in the log model to show.
My attempt on the views:
tickets_form
<%= form_for(#ticket) do |f| %>
<% if ... end %>
<div class="field">
<%= f.label :issue %><br />
<%= f.text_area :issue %>
</div>
<% f.fields_for :logs do |builder| %>
<p>
<%= builder.label :detail %><br />
<%= builder.text_area :detail %>
</p>
<% end %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
tickets\show
<p id="notice"><%= notice %></p>
<p>
<b>Issue:</b>
<%= #ticket.issue %>
</p>
<ol>
<% for log in #ticket.logs %>
<p>
<%=log.detail %> *Note:squiggly line under detail said "Cannot find 'detail'"*
</p>
<% end %>
</ol>
<%= link_to 'Edit', edit_ticket_path(#ticket) %> |
<%= link_to 'Back', tickets_path %>
My Controller:
def new
#ticket = Ticket.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #ticket }
end
end
def create
#ticket = Ticket.new(params[:ticket])
respond_to do |format|
if #ticket.save
format.html { redirect_to #ticket, notice: 'Ticket was successfully created.' }
format.json { render json: #ticket, status: :created, location: #ticket }
else
format.html { render action: "new" }
format.json { render json: #ticket.errors, status: :unprocessable_entity }
end
end
end
Ticket\show
<h1>New ticket</h1>
<%= render 'form' %>
<%= link_to 'Back', tickets_path %>
Your attr_accessible line in Ticket class should be attr_accessible :issue, :logs_attributes.
Otherwise you should get(if you are using rails version < 4):
Can't mass-assign protected attributes: logs_attributes
If you don't get it there must be a problem with your controller create action(can you update your question with a controller code?)
It should look something like this:
def new
#ticket = Ticket.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #ticket }
end
end
def create
#ticket = Ticket.new(params[:ticket])
respond_to do |format|
if #ticket.save
format.html { redirect_to #ticket, notice: 'Ticket was successfully created.' }
format.json { render json: #ticket, status: :created, location: #ticket }
else
format.html { render action: "new" }
format.json { render json: #ticket.errors, status: :unprocessable_entity }
end
end
end
This simple create action together with fields_for call in your tickets_form and accepts_nested_attributes_for :logs in Ticket class will crate both parent and association object in a one go.
tickets/new.html.erb should look something like this:
<h1>New ticket</h1>
<%= render 'form' %>
<%= link_to 'Back', tickets_path %>
And the form partial tickets/_form.html.erb should be:
<%= form_for(#ticket) do |f| %>
<% if ... end %>
<div class="field">
<%= f.label :issue %><br />
<%= f.text_area :issue %>
</div>
<% f.fields_for :logs do |builder| %>
<p>
<%= builder.label :detail %><br />
<%= builder.text_area :detail %>
</p>
<% end %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Off topic:
A bit more Rails way to do this(just a suggestion):
<% for log in #ticket.logs %>
<p>
<%=log.detail %>
</p>
<% end %>
Would be:
<% #ticket.logs.each |log| %>
<%= content_tag(:p, log.detail) %>
<% end %>
I have a admin section and inside the admin i have, Finalist and Images.
Im using, ruby 1.8.7-p249 and Rails 3.1.2
# model image.rb
class Admin::Image < ActiveRecord::Base
belongs_to :finalist
...
end
# model finalist.rb
class Admin::Image < ActiveRecord::Base
has_many :images
...
end
My ImagesController:
def new
#admin_finalist = Admin::Finalist.find(params[:finalist_id])
#admin_image = #admin_finalist.images.build
respond_to do |format|
format.html # new.html.erb
format.json { render :json => #admin_image }
end
end
def edit
#admin_finalist = Admin::Finalist.find(params[:finalist_id])
#admin_image = #admin_finalist.images.find(params[:id])
end
def create
#admin_finalist = Admin::Finalist.find(params[:finalist_id])
#admin_image = #admin_finalist.images.new(params[:admin_image])
respond_to do |format|
if #admin_image.save
format.html { redirect_to admin_finalist_images_path(#admin_finalist) }
format.json { render :json => #admin_image, :status => :created, :location => #admin_image }
else
format.html { render :action => "new" }
format.json { render :json => #admin_image.errors, :status => :unprocessable_entity }
end
end
end
def update
#admin_finalist = Admin::Finalist.find(params[:finalist_id])
#admin_image = #admin_finalist.images.find(params[:id])
respond_to do |format|
if #admin_image.update_attributes(params[:admin_image])
format.html { redirect_to admin_finalist_images_path(#admin_finalist) }
format.json { head :ok }
else
format.html { render :action => "edit" }
format.json { render :json => #admin_image.errors, :status => :unprocessable_entity }
end
end
end
And my Images _form.html.erb:
<%= form_for([#admin_finalist, #admin_image]) do |f| %>
<% if #admin_image.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#admin_image.errors.count, "error") %> prohibited this admin_image from being saved:</h2>
<ul>
<% #admin_image.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :file %>
<%= f.file_field :file %>
</div>
<%- unless #admin_image.new_record? || !#admin_image.file? -%>
<div class="field">
<%= f.label :remove_file, "Remover?" %>
<%= f.check_box :remove_file %>
</div>
<%- end -%>
<div class="field">
<%= f.label :url %>
<%= f.text_field :url, :placeholder => "http://" %>
</div>
<div class="field">
<%= f.label :title %>
<%= f.text_field :title %>
</div>
<div class="actions">
<%= image_submit_tag("button/save.png") %>
<%= link_to image_tag("button/back.png"), admin_finalist_images_path %>
</div>
<% end %>
Everything seems perfect, but im getting this error when im trying to add an image to finalist at admin/finalists/1/images/new.
Showing .../app/views/admin/images/_form.html.erb where line #5 raised:
undefined method `admin_finalist_admin_images_path' for #<#<Class:0x102da0068>:0x102d9a870>
So, i tryed to tell rails to use a particular url:
<%= form_for([#admin_finalist, #admin_image], :url => admin_finalist_image_path(#admin_finalist.id, #admin_image)) do |f| %>
Saddly, this work only for editing. When i try to edit i get this error message:
No route matches {:controller=>"admin/images", :finalist_id=>1, :id=>nil, :action=>"show"}
And if i wanna create i need to do:
<%= form_for([#admin_finalist, #admin_image], :url => admin_finalist_images_path) do |f| %>
And if i try to edit i get this message:
No route matches [PUT] "/admin/finalists/1/images"
I dont know what to do... I tried everything without success, if anyone can help me would be much appreciated.
EDIT
The problem was that my models was namespaced. So, i rewrite all the app to fix this, and thats running normally.
[]`s