Showing errors in the modal rails - ruby-on-rails

I'm very frustrated because I've been working on it for days and I haven't found a solution yet.
I have a Visit.rb model and, beyond the common validations, I have two more validations through two methods of mine (visit's start date cannot be prior to end one and there's no possibility to have two visits having the same start date, end date and visitor_id).
I need to show these errors set by me in the modal I'm giving to register a visit, but until now I've never had success.
In fact every time this error occurs: ArgumentError in VisitsController#create - First argument in form cannot contain nil or be empty
Here what I've done until now is...
Visit.rb
class Visit < ActiveRecord::Base
belongs_to :employee
belongs_to :visitor
default_scope -> { order(:created_at) }
validates :from, presence: true, uniqueness: { scope: [:to, :visitor_id] }
validates :to, presence: true
validates :visitor_id, presence: true
validates :employee_id, presence: true
validate :valid_date_range_required
validate :visit_uniqueness
def valid_date_range_required
if (from && to) && (to < from)
errors[:base] << "Visit's end date cannot be prior to the start one."
end
end
def visit_uniqueness
if Visit.find_by(from: :from, to: :to, visitor_id: :visitor_id)
errors[:base] << "A visit with the same start date, end date and visitor already exists."
end
end
end
visits_controller.rb
class VisitsController < ApplicationController
before_action :logged_in_employee, only: [:create, :destroy]
before_action :correct_employee, only: [:destroy, :update ]
def create
#visit = current_employee.visits.build(visit_params)
if #visit.save
flash[:success] = "Visit added"
redirect_to employee_path(session[:employee_id], :act => 'guestsVisits')
else
#visits = current_employee.visits.all
#employee = current_employee
render 'employees/guestsVisits'
end
end
private
def visit_params
params.require(:visit).permit(:from, :to, :visitor_id, :employee_id)
end
def correct_employee
#visit = current_employee.visits.find_by(id: params[:id])
redirect_to root_url if #visit.nil?
end
end
guestsVisits.rb (my view)
<div class="jumbotron3 text-center">
<div class="row">
<h1>Guests Visits</h1>
<hr>
<%=render :partial =>"layouts/sidebar"%>
<div class="panel3">
<div class="panel-body">
<!-- Modal for Visit -->
<% if logged_in? %>
<%=render :partial =>"shared/error_messages"%>
<a class="btn icon-btn btn-success pos" data-toggle="modal" data-target="#visitModal">
<span class="glyphicon btn-glyphicon glyphicon-plus img-circle text-success"></span>
Add a visit
</a>
<div id="visitModal" class="modal fade" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title">Add Visit</h4>
</div>
<div class="modal-body">
<%= form_for(#visit) do |f| %>
<%= f.label :start_date %>
<%= f.date_field :from, class: 'form-control',:value => (f.object.from.strftime('%m/%d/%Y') if f.object.from) %>
<%= errors_for #visit, :from %><%if #visit.errors.any?%><br><%end%>
<br>
<%= f.label :end_date %>
<%= f.date_field :to, class: 'form-control',:value => (f.object.to.strftime('%m/%d/%Y') if f.object.to) %>
<%= errors_for #visit, :to %><%if #visit.errors.any?%><br><%end%>
<br>
<%= f.label :Visitor %>
<%= f.collection_select :visitor_id, Visitor.all, :id, :full_name, { :class=> "form-control", :include_blank => ''}%>
<%= errors_for #visit, :visitor_id %><%if #visit.errors.any?%><br><%end%>
<br>
<%= f.submit "Add visit", class: "btn btn-primary btn-color" %>
<% end %>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-info" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
<% end %>
</div>
</div>
</div>
</div>
I tried to use two different versions of error_messages.rb
error_messages.rb (1)
<% if #visit && #visit.errors.any? %>
<div id="error_explanation">
<div class="alert alert-danger">
×
The form contains <%= pluralize(#visit.errors.count, "error") %>.Open the modal for more details
</div>
</div>
<% end %>
error_messages.rb (2)
<% if #visit.errors.any? %>
<ul class="errors">
<% #visit.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
<% end %>
I hope someone can help me because I don't understand how to figure it out.
Thank you a lot.
EDIT:
class Employee < ActiveRecord::Base
before_save { self.email = email.downcase }
before_create :confirmation_token
VALID_EMAIL_REGEX = /\A[\w+\-.]+#[a-z\d\-.]+\.[a-z]+\z/i
has_many :macaddresss, dependent: :destroy
has_many :visits, dependent: :destroy
has_many :visitors, dependent: :destroy
#Validations
validates :name, presence: true , length: { maximum:20 , minimum: 2 }
validates :lastname, presence: true, length: { maximum:20 , minimum: 2 }
validates :gender, presence: true
validates :dateofbirth, presence: true
validates :birth_country, presence: true
validates :birth_place, presence: true, length: { maximum:60}
validates :contry_of_residence, presence: true
validates :city_of_residence, presence: true, length: { maximum:60 }
validates :address, presence: true, length: { maximum:60 , minimum: 7 }
validates :email, presence: true, length: { maximum:243 } ,format: { with: VALID_EMAIL_REGEX }, uniqueness: { case_sensitive: false }
validates :password, length: { minimum: 6 }
validates :terms_of_service, acceptance: { message: 'accept terms and conditions' }
[...]
has_secure_password
def Employee.digest(string)
cost = ActiveModel::SecurePassword.min_cost ? BCrypt::Engine::MIN_COST :
BCrypt::Engine.cost
BCrypt::Password.create(string, cost: cost)
end
end
session_helper.rb
def current_employee
#current_employee ||= Employee.find_by(id: session[:employee_id])
end
EDIT2:
employees_controller.rb
class EmployeesController < ApplicationController
def show
if logged_in?
#employee = Employee.find(params[:id])
#indirizzimac = current_employee.indirizzimacs.new
#visitor = current_employee.visitors.new
#visit = current_employee.visits.new
#visits = current_employee.visits.all
if params[:act]=='myData'
render 'myData'
elsif params[:act]=='myNetwork'
render 'myData'
elsif params[:act]=='temporaryUsers'
render 'temporaryUsers'
elsif params[:act]=='guestsVisits'
render 'guestsVisits'
elsif params[:act]=='myAccount'
render 'myAccount'
else
render 'show'
end
else
render 'static_pages/errorPage'
end
end
end

From what i can see if creating visit fails you instantiate #visits and #employee instance variables then rendering 'employees/guestsVisits' its view you use #visit which i think it doesn't exist inside empleyees controller
So add it ad
def guestsVisits
#visit = current_employee.visits.build
end

Related

Data not persisted between steps in wizard

I have followed Nicolas Blanco's tutorial to make a "goal" wizard for my app.
There are two steps in the wizard. The first consisting of the form fields "name", "description" and "plan", the second has "deadline", which is a datetimepicker, "reporting frequency" and "days missed tolerance".
It seems to work when I click continue in the first step, but on clicking finish in the second step, the object #goal_wizard doesn't seem to include the parameters from the first step.
My goal.rb:
module Wizard
module Goal
STEPS = %w(step1 step2).freeze
class Base
include ActiveModel::Model
attr_accessor :goal
delegate *::Goal.attribute_names.map { |attr| [attr, "#{attr}="] }.flatten, to: :goal
def initialize(goal_attributes)
#goal = ::Goal.new(goal)
end
end
class Step1 < Base
validates :name, presence: true, length: { maximum: 50 }
validates :description, presence: true, length: { maximum: 300 }
validates :plan, presence: true, length: { maximum: 1000 }
end
class Step2 < Step1
validates :reporting_frequency, presence: true,
numericality: { greater_than_or_equal_to: 0 }
validates :days_missed_tolerance, presence: true,
numericality: { greater_than_or_equal_to: 0}
validates :deadline, presence: true
end
end
end
wizards_controller.rb:
class WizardsController < ApplicationController
before_action :load_goal_wizard, except: :validate_step
def validate_step
current_step = params[:current_step]
#goal_wizard = wizard_goal_for_step(current_step)
#goal_wizard.goal.attributes = goal_wizard_params
session[:goal_attributes] = #goal_wizard.goal.attributes
if #goal_wizard.valid?
next_step = wizard_goal_next_step(current_step)
create and return unless next_step
redirect_to action: next_step
else
render current_step
end
end
def create
# #user = current_user
# #goal = #user.goals.new(#goal_wizard.goal)
if #goal_wizard.goal.save
session[:goal_attributes] = nil
redirect_to root_path, notice: 'Goal succesfully created!'
else
redirect_to({ action: Wizard::Goal::STEPS.first }, alert: 'There were a problem creating the goal.')
end
end
private
def load_goal_wizard
#goal_wizard = wizard_goal_for_step(action_name)
end
def wizard_goal_next_step(step)
Wizard::Goal::STEPS[Wizard::Goal::STEPS.index(step) + 1]
end
def wizard_goal_for_step(step)
raise InvalidStep unless step.in?(Wizard::Goal::STEPS)
"Wizard::Goal::#{step.camelize}".constantize.new(session[:goal_attributes])
end
def goal_wizard_params
params.require(:goal_wizard).permit(:name, :description, :plan, :deadline, :reporting_frequency, :days_missed_tolerance)
end
class InvalidStep < StandardError; end
end
step1.html.erb:
<ol class="breadcrumb">
<li class='active'>Step 1</li>
<li>Step 2</li>
</ol>
<%= form_for #goal_wizard, as: :goal_wizard, url: validate_step_wizard_path do |f| %>
<%= render "error_messages" %>
<%= hidden_field_tag :current_step, 'step1' %>
<%= f.label :name %>
<%= f.text_field :name, class: "form_control" %>
<%= f.label :description %>
<%= f.text_field :description, class: "form_control" %>
<%= f.label :plan %>
<%= f.text_field :plan, class: "form_control" %>
<%= f.submit 'Continue', class: "btn btn-primary" %>
<% end %>
step2.html.erb:
<ol class="breadcrumb">
<li><%= link_to "Step 1", step1_wizard_path %></li>
<li class="active">Step 2</li>
</ol>
<%= form_for #goal_wizard, as: :goal_wizard, url: validate_step_wizard_path do |f| %>
<%= render "error_messages" %>
<%= hidden_field_tag :current_step, 'step2' %>
<%= f.label :deadline %>
<div class='input-group date' id='datetimepicker1'>
<%= f.text_field :deadline, class: "form-control" %>
<span class="input-group-addon">
<span class="glyphicon glyphicon-calendar"></span>
</span>
</div>
<%= f.label "How often do I want to report? (1 = every day)" %>
<%= f.number_field :reporting_frequency, class: "form_control" %>
<%= f.label "How many times can I miss my report?" %>
<%= f.number_field :days_missed_tolerance, class: "form_control" %>
<script type="text/javascript">
$(function () {
$('#datetimepicker1').datetimepicker({
minDate:new Date()
});
});
</script>
<%= f.submit "Finish", class: "btn btn-primary" %>
<% end %>
Over here you're passing the goal_attributes to initialize, but you're never using them.
def initialize(goal_attributes)
#goal = ::Goal.new(goal)
end
If you look at Nicolas Blanco's code he doesn't make that mistake.

Rails has_many :through, cocoon

Player.rb
class Player < ApplicationRecord
belongs_to :user
has_many :player_games, dependent: :destroy, inverse_of: :player
has_many :games, :through => :player_games
validates :firstname, presence: true, length: { minimum: 3, maximum: 88 }
validates :lastname, presence: true, length: { minimum: 3, maximum: 88 }
validates :user_id, presence: true
accepts_nested_attributes_for :player_games, reject_if: :reject_posts, allow_destroy: true
def reject_posts(attributes)
attributes['game_id'].to_i == 0
attributes['score'].blank?
attributes['time'].blank?
end
def initialized_player_games # this is the key method
[].tap do |o|
Game.all.each do |game|
if g = player_games.find { |g| g.game_id == game.id }
o << g.tap { |g| g.enable ||= true }
else
o << PlayerGame.new(game: game)
end
end
end
end
end
players_controller.rb
class PlayersController < ApplicationController
before_action :set_player, only: [:edit, :update, :show, :destroy]
before_action :require_user, except: [:index, :show]
before_action :require_same_user, only: [:edit, :update, :destroy]
before_filter :process_player_games_attrs, only: [:create, :update]
def process_player_games_attrs
params[:player][:player_games_attributes].values.each do |game_attr|
game_attr[:_destroy] = true if game_attr[:enable] != '1'
end
end
.......
private
# Use callbacks to share common setup or constraints between actions.
def set_player
#player = Player.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def player_params
params.require(:player).permit(:id, :firstname, :lastname, player_games_attributes: [:id, :game_id, :score, :time, :enable, :_destroy] )
end
def require_same_user
if current_user != #player.user and !current_user.admin?
flash[:danger] = "You can edit or delete only your own player"
redirect_to root_path
end
end
end
_form of 'PLAYER'
<%= form_for(#player, :html => {class: "az-form", role: "form"}) do |player_form| %>
<%= player_form.label :firstname, class: "az-form__label" %> <br/>
<%= player_form.text_field :firstname, class: "az-form__input", placeholder: "Firstname of player", autofocus: true %>
<%= player_form.label :lastname, class: "az-form__label" %> </br>
<%= player_form.text_field :lastname, class: "az-form__input", placeholder: "Lastname of player" %>
<%= player_form.fields_for :player_games, #player.initialized_player_games do |builder| %>
<% #game = builder.object.game %>
<%= render 'result_fields', f: builder %>
<div class="links">
<%= link_to_add_association 'add result', player_form, :player_games, :partial => 'players/result_fields' %>
</div>
<hr>
<% end %>
<div class="text-center">
<%= button_tag(type: "submit", class: "az-form__submit") do %>
<%= player_form.object.new_record? ? "Create player" : "Update player" %>
<% end %>
</div>
<% end %>
_result_fields.html.erb
<div class="nested-fields">
<%= f.hidden_field :game_id, :value => #game.id%>
<div class="row">
<div class="col-md-12">
<label class="az-form__label az-form__label--unable js-az-form__checkbox" data-check="<%= #game.id %>">
<%= f.check_box :enable %>
<%= #game.title %>
</label>
</div>
</div>
<div class="row">
<div class="col-md-6">
<%= f.label :score,
class: "az-form__label", :data => {:check => #game.id } %> </br>
<%= f.number_field :score, step: :any, :data => {:check => #game.id },
class: "az-form__input az-form__input--disabled",
placeholder: "Score for '#{#game.title}'", disabled: true %>
</div>
<div class="col-md-6">
<%= f.label :time,
class: "az-form__label", :data => {:check => #game.id } %> </br>
<%= f.number_field :time, step: :any, :data => {:check => #game.id },
class: "az-form__input az-form__input--disabled",
placeholder: "Time for '#{#game.title}'", disabled: true %>
</div>
</div>
<div class="row">
<div class="col-md-12">
<%= link_to_remove_association "remove result", f %>
</div>
</div>
</div>
Question:
When edit 'player' have access to only one result per game, can not change others, conflict with 'initialized_player_games' method, but if i remove this method from form work well, but cannot create another game if dont create in new action, how can i change this method properly?
If I understand correctly, you want to add an entry for all games (which works), but adding a new Result does not. The problem is the #game which is probable either undefined or set to the last game.
I also do not really like the approach (giving the fields_for a specific set). Instead I would adapt the approach slightly. Instead of using initialized_player_games I would use a method, to be called in the controller, e.g. add_default_player_games, something like
def add_default_player_games
Game.all.each do |game|
if g = player_games.find { |g| g.game_id == game.id }
g.enable ||= true
else
player_games.build(game: game)
end
end
end
effectively adding new instances to the collection, without saving them.
So in your controller you would write
#player = Player.new
#player.add_default_player_games
or in edit
#player = Player.find(params[:id])
#player.add_default_player_games
Your view would then just iterate over player_games
<%= player_form.fields_for :player_games do |builder| %>
<%= render 'result_fields', f: builder %>
<% end %>
And then, if you would use simple-form it would be very easy to select a game if not yet selected, and there is no need for the ugly #game.
So do something like in _result_fields (in haml because I am a lazy typist)
.nested-fields
- game_id = f.object.game_id
- if game_id.present?
= f.hidden_field :game_id
- else
= f.collection_select :game_id, Game.all, :id, :name
...
So in short: if there is a game_id, do not allow to change it (would be useful to show the title of the game or something), but if not use a dropdown-select to choose the game.
And the rest stays the same (only use game_id instead of #game.id).

ActiveRecord::RecordNotFound Couldn't find ServiceProvider with 'id'=

I've got a problem with the creation of an object. The New-function ist working, but when i pass the object to the Create, the following error is thrown.
I want to add a Service when a ServiceProvider exists. Every User can create one ServiceProvider for himself. A ServiceProvider could have a few services.
I've also set the foreign-keys for the services-table in a MIgration-file via
"add_foreign_key :services, :service_provider"
I don't have an idea why the service_provider_id isn't transfered.
Error Output
ActiveRecord::RecordNotFound in ServicesController#create
Couldn't find ServiceProvider with 'id'=
Extracted source (around line #55):
private
def current_service_provider
Line 55: #current_service_provider = ServiceProvider.find(params[:id])
end
Parameters:
{"utf8"=>"✓",
"authenticity_token"=>"Z4s/ZzbbMmcXA1jAyFnEZZ/8RhS2ZO/UdI6xN5QkKQwXmJJOOo/PVsSdOUcuJvVpFJdaUi/rMtNJq5sAEdz89g==",
"service"=>{"name"=>"dsfg", "address"=>"asdf", "radius"=>"64655", "price"=>"45", "descr"=>"sdfagasrfsdgh"},
"commit"=>"Speichern"}
Models
class ServiceProvider < ApplicationRecord
belongs_to :user
has_many :services
validates :name, presence: true
validates :street, presence: true
validates :plz, presence: true
validates :location, presence: true
validates :user_id, presence: true
end
class Service < ApplicationRecord
belongs_to :service_provider
has_many :service_photos
validates :name, presence: true, length: {maximum: 50}
validates :address, presence: true
validates :price, presence: true
end
ServicesController
class ServicesController < ApplicationController
before_action :set_service, only: [:show, :edit, :update]
before_action :authenticate_user!, except: [:show]
def index
#service = current_user.services
end
def show
#service_photos = #service.service_photos
end
def new
#service = Service.new
end
def create
#service = current_service_provider.services.build(service_params)
if #service.save
if params[:images]
params[:images].each do |image|
service.service_photos.create(image: image)
end
end
#service_photos = #service.service_photos
redirect_to edit_service_path(#service), notice: "Gespeichert"
else
render :new
end
end
def edit
end
def update
end
private
def current_service_provider
#current_service_provider = ServiceProvider.find(params[:id])
end
def set_service
#service = Service.find(params[:id])
end
def service_params
params.require(:service).permit(:name, :address, :radius, :price, :descr)
end
end
Form
<div class="panel panel-default">
<div class="panel-heading">
Erstelle deinen Service
</div>
<div class="panel-body">
<div class="container">
<%= form_for #service, html: {multipart: true} do |f| %>
<div class="row">
<div class="form-group">
<label>Service Name</label>
<%= f.text_field :name, placeholder: "Servicename", class: "form-control" %>
</div>
</div>
<div class="row">
<div class="form-group">
<label>Adresse</label>
<%= f.text_field :address, placeholder: "Adresse", class: "form-control" %>
</div>
</div>
<div class="row">
<div class="form-group">
<label>Radius</label>
<%= f.text_field :radius, placeholder: "Radius", class: "form-control" %>
</div>
</div>
<div class="row">
<div class="form-group">
<label>Preis</label>
<%= f.text_field :price, placeholder: "Preis", class: "form-control" %>
</div>
</div>
<div class="row">
<div class="form-group">
<label>Beschreibung</label>
<%= f.text_area :descr, rows: 5, placeholder: "Beschreibung", class: "form-control" %>
</div>
</div>
<div class="rows">
<div class="col-md-4">
<div-form-group>
<span class="btn btn-default btn-file">
<i class="fa fa-cloud-upload fa-lg"></i>Fotos hochladen
<%= file_field_tag "images[]", type: :file, multiple: true %>
</span>
</div-form-group>
</div>
</div>
<div id="photos"><%= render 'service_photos/list' %></div>
<div class="actions">
<%= f.submit "Speichern", class: "btn btn-primary" %>
</div>
<% end %>
</div>
</div>
</div>
In "create" action you try to find non-existing object. You can find object by 'id' after save that.
In your case params[:id] is not exist when "current_service_provider" method is calling.

Save successful on nested attributes on has many through but doesn't add to database

I and order and item system with Rails 4 with a has many through association. When I select create order the webpage says that the order was created successfully however the link is not made in the OrderItems linking tables meaning that the items relating to that order do not appear on the show page or edit page for an order.
The order is also linked to an employee. The current employee ID is linked to that order. I have just not been able to figure out how to add each item to the database.
p.s. I am using a gem called nested_form to handle all of the jQuery on the front end of dynamically adding and removing new items on the _form.html.erb for Orders.
orders_controller.rb
class OrdersController < ApplicationController
before_action :logged_in_employee, only:[:new, :show, :create, :edit, :update, :index]
before_action :admin_employee, only:[:destroy]
before_action :set_order, only: [:show, :edit, :update, :destroy]
def new
#order = Order.new
#items = Item.all
end
def edit
#items = Item.all
end
def create
#order = current_employee.orders.build(order_params)
if #order.save
flash[:success] = "Order successfully created"
redirect_to #order
else
render 'new'
end
end
def update
if #order.update_attributes(order_params)
flash[:success] = "Order updated!"
redirect_to current_employee
else
render 'edit'
end
end
....
private
def set_order
#order = Order.find(params[:id])
end
def order_params
params.require(:order).permit(:table_number, :number_of_customers, :status, :comment, order_items_attributes: [:id, :order_id, :item_id, :_destroy])
end
end
order.rb
class Order < ActiveRecord::Base
belongs_to :employee
has_many :order_items
has_many :items, :through => :order_items
default_scope { order('status DESC') }
validates :employee_id, presence: true
validates :table_number, numericality: { only_integer: true, greater_than: 0, less_than_or_equal_to: 20 }, presence: true
validates :number_of_customers, numericality: { only_integer: true, greater_than: 0, less_than_or_equal_to: 50 }, presence: true
validates :status, inclusion: { in: %w(Waiting Ready Closed), message: "%{value} is not a status" }
accepts_nested_attributes_for :order_items, :reject_if => lambda { |a| a[:item_id].blank? }
end
item.rb
class Item < ActiveRecord::Base
belongs_to :menu
has_many :order_items
has_many :orders, :through => :order_items
before_save { name.capitalize! }
VALID_PRICE_REGEX = /\A\d+(?:\.\d{0,2})?\z/
validates :name, presence: true, length: { maximum: 100 }
validates :price, format: { with: VALID_PRICE_REGEX }, numericality: { greater_than: 0, less_than_or_equal_to: 100}, presence: true
validates :course, inclusion: { in: %w(Starter Main Dessert Drink), message: "%{value} is not a course" }
validates :menu_id, presence: true
end
order_item.rb
class OrderItem < ActiveRecord::Base
belongs_to :item
belongs_to :order
validates :order_id, presence: true
validates :item_id, presence: true
end
orders/_form.html.erb
<% provide(:title, "#{header(#order)} #{#order.new_record? ? "order" : #order.id}") %>
<%= link_to "<< Back", :back, data: { confirm: back_message } %>
<h1><%= header(#order) %> <%= #order.new_record? ? "order" : #order.id %></h1>
<div class="row">
<div class="col-md-6 col-md-offset-3">
<%= nested_form_for #order do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<div class="row">
<div class="col-xs-6">
<%= f.label :table_number %>
<%= f.number_field :table_number, class: 'form-control' %>
</div>
<div class="col-xs-6">
<%= f.label :number_of_customers %>
<%= f.number_field :number_of_customers, class: 'form-control' %>
</div>
</div>
<%= f.fields_for :order_items do |oi| %>
<%= oi.grouped_collection_select :item_id, Menu.where(active: true).order(:name), :items, :name, :id, :name, { include_blank: 'Select Item' }, class: 'items_dropdown' %>
<%= oi.hidden_field :item_id %>
<%= oi.hidden_field :order_id %>
<%= oi.link_to_remove "Remove item" %>
<% end %>
<p><%= f.link_to_add "Add an item", :order_items %></p>
<br>
<% if !#order.new_record? %>
<%= f.label "Status" %>
<%= f.select(:status, options_for_select([['Waiting', 'Waiting'], ['Ready', 'Ready'], ['Closed', 'Closed']], #order.status), class: 'form-control') %>
<% end %>
<%= f.label "Comments - how would you like your steak cooked? Or feedback" %>
<%= f.text_area :comment, size: "20x5", class: 'form-control' %>
<%= f.submit submit_label(#order), class: "btn btn-success col-md-6" %>
<% end %>
<% if !#order.new_record? && current_employee.try(:admin?) %>
<%= link_to "Cancel", :back, data: { confirm: back_message }, class: "btn btn-warning col-md-offset-1 col-md-2" %>
<%= link_to "Delete", #order, method: :delete, data: { confirm: "Are you sure? The employee will be deleted! "}, class: "btn btn-danger col-md-offset-1 col-md-2" %>
<% else %>
<%= link_to "Cancel", :back, data: { confirm: back_message }, class: "btn btn-warning col-md-offset-1 col-md-5" %>
<% end %>
</div>
</div>
Issue: Let's say your order has got many items and you want the items to be saved just when the order is created.
order = Order.new(order_params)
item = Item.new(name: 'item-name', product_info: 'etc etc')
if order.save
item.create
order.items << item
end
You need to follow similar approach in your case. just get the item_params properly and apply above rule.
Try below approach, hope that helps. :)
def create
#order = current_employee.orders.build(order_params)
if #order.save
item = params["order"]["order_items_attributes"]
#please debug above one and try to get your items from params.
order_item = Item.create(item)
#makes sure above item hold all item attributes then create them first
#order.items << item
redirect_to #order
end
end

Why do I get "NameError in Discussions"?

I'm currently working on a Ruby on Rails application that involves users creating discussions and commenting with microposts. It's a pretty simple concept but I'm new and have run into some trouble.
When trying to look at the discussions page (index of discussion) I get the error "NameError in Discussions#index":
undefined local variable or method `discussion' for #<#<Class:0x00000100c6e020>:0x0000010380edd8>
This is my Discussion controller:
class DiscussionsController < ApplicationController
before_filter :signed_in_user, only: [:index, :edit, :update]
def show
#user = User.find(params[:id])
#discussions = #user.discussion.paginate(page: params[:page])
#microposts = #user.micropost.paginate(page: params[:page])
end
def index
#discussions = Discussion.all
end
def create
#discussion = current_user.discussions.build(params[:discussion])
if #discussion.save
flash[:success] = "Discussion Started!"
redirect_to root_url
else
render 'static_pages/home'
end
end
def destroy
end
def edit
end
def update
end
def new
end
end
This is my Micropost form:
<% #micropost = Micropost.new %>
<% #micropost.discussion_id = discussion.id %>
<%= form_for(#micropost) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<div class="field">
<%= f.text_area :content, placeholder: "Compose new micropost..." %>
</div>
<%= f.hidden_field :discussion_id, discussion.id%>
<%= f.submit "Post", class: "btn btn-large btn-primary" %>
<% end %>
This is my Discussion partial:
<% content_for :script do %>
<%= javascript_include_tag 'hover_content' %>
<% end %>
<li>
<div class = "intro-bar"><span class = "intro"><%=discussion.intro %></span></div>
<div class = "content-bar">
<span class = "content"><%= discussion.content %></span>
<div class = "buttons">
<div class = "vote-neg"><%= link_to "Break Up", signup_path,class: "btn btn-large btn-breakup" %></div>
<div class = "vote-plus"><%= link_to "Stay Together", signup_path,class: "btn btn-large btn-staytogether" %></div>
</div>
</div>
</li>
<span class = "timestamp">
Posted <%= time_ago_in_words(discussion.created_at) %> ago.
</span>
<div class = "comments">
<% discussion.microposts.each do |micropost| %>
<li>
<div class = "post-comment"><%= micropost.content%></div>
</li>
<% end %>
</div>
<% if signed_in? %>
<div class = "row">
<aside class = "span4">
<section>
<%= render 'shared/micropost_form', :locals => {:discussion => discussion }%>
</section>
</aside>
</div>
<% end %>
This is my Micropost controller:
class MicropostsController < ApplicationController
before_filter :signed_in_user, only: [:create, :destroy]
def index
end
def create
#discussion = current_user.discussions.new
#micropost = current_user.microposts.build(params[:micropost])
if #micropost.save
flash[:success] = "Posted!"
redirect_to root_url
else
render 'static_pages/home'
end
end
def destroy
end
end
This is my Discussion model:
class Discussion < ActiveRecord::Base
attr_accessible :content, :intro
has_many :microposts, dependent: :destroy
belongs_to :user
validates :content, presence: true, length: { maximum: 600 }
validates :intro, presence: true
default_scope order: 'discussions.created_at DESC'
end
This is my User model:
class User < ActiveRecord::Base
attr_accessible :email, :username, :age, :sex, :points, :password, :password_confirmation
has_secure_password
has_many :microposts, dependent: :destroy
has_many :discussions, dependent: :destroy
before_save {|user| user.email = email.downcase}
before_save :create_remember_token
validates :username, presence: true, length: {maximum: 15}
VALID_EMAIL_REGEX = /\A[\w+\-.]+#[a-z\d\-.]+\.[a-z]+\z/i
validates :email, presence: true, format: { with: VALID_EMAIL_REGEX }, uniqueness: {case_sensitive: false}
validates :age, presence: true
validates :sex, presence: true
validates :password, presence: true, length: { minimum: 6 }
validates :password_confirmation, presence: true
private
def create_remember_token
self.remember_token = SecureRandom.urlsafe_base64
end
end
This is my Discussion index:
<% provide(:title, "Discussions") %>
<h1>Discussions</h1>
<ul class = "discussions">
<% #discussions.each do |discussion| %>
<li>
<%= render :partial =>"discussions/discussion", :locals=>{:discussion=>discussion} %>
</li>
<% end %>
</ul>
Try rewriting this line:
<%= render 'shared/micropost_form', :locals => {:discussion => discussion }%>
as:
<%= render 'shared/micropost_form', :discussion => discussion %>

Resources