I'm a ROR newbie and I've somehow broken the create and edit functionalities within my app. I have individual pages for each artwork I've uploaded, a _form that enables editing of those artworks (and their original creation), and two different index pages: one index page that's pretty (on the app's home page), and one that's just a big table with all the info for each artwork (for the backend).
routes.rb
Rails.application.routes.draw do
root "pages#home"
get "artworks" => "artworks#index"
# post "artworks" => "artworks#index"
resources :artworks, path: ''
get "about" => "pages#about"
end
artworks_controller.rb
class ArtworksController < ApplicationController
before_action :set_artwork, only: [:show, :edit, :update, :destroy]
# GET /artworks
# GET /artworks.json
def index
#artworks = Artwork.all
end
# GET /artworks/1
# GET /artworks/1.json
def show
#artwork = Artwork.friendly.find(params[:id])
if request.path != artwork_path(#artwork)
redirect_to #artwork, status: :moved_permanently
end
end
# GET /artworks/new
def new
#artwork = Artwork.new
end
# GET /artworks/1/edit
def edit
end
# POST /artworks
# POST /artworks.json
def create
#artwork = Artwork.new( artwork_params )
respond_to do |format|
if #artwork.save
format.html { redirect_to #artwork, notice: 'Artwork was successfully created.' }
format.json { render :show, status: :created, location: #artwork }
else
format.html { render :new }
format.json { render json: #artwork.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /artworks/1
# PATCH/PUT /artworks/1.json
def update
respond_to do |format|
if #artwork.update(artwork_params)
format.html { redirect_to #artworks, notice: 'Artwork was successfully updated.' }
format.json { render :show, status: :ok, location: #artwork }
else
format.html { render :edit }
format.json { render json: #artwork.errors, status: :unprocessable_entity }
end
end
end
# DELETE /artworks/1
# DELETE /artworks/1.json
def destroy
#artwork.destroy
respond_to do |format|
format.html { redirect_to artworks_url, notice: 'Artwork was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_artwork
#artwork = Artwork.friendly.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def artwork_params
params.require(:artwork).permit(:title, :image, :genre, :category, :medium, :slug, :availability, :date, :height, :width)
end
end
pages_controller.rb
class PagesController < ApplicationController
def home
#artworks = Artwork.all
end
def about
end
end
index.html.rb (in views/artworks)
<div class="row">
<div class="col-xs-6 col-sm-8 col-md-4">
<h1>Listing artworks</h1>
</div>
<div class="col-xs-4 col-sm-2 col-md-2 col-md-offset-6">
<%= link_to 'New Artwork', new_artwork_path, class:"btn btn-default" %>
</div>
</div>
<div class="table-responsive">
<table class="table table-striped">
<thead>
<tr>
<th>Image</th>
<th>Title</th>
<th>Genre</th>
<th>Category</th>
<th>Medium</th>
<th>Date</th>
<th>Dimensions</th>
<th>Availability</th>
<th>Edit</th>
</tr>
</thead>
<tbody>
<% #artworks.each do |artwork| %>
<tr>
<td><%= link_to image_tag(artwork.image.url(:thumb)), artwork %></td>
<td><%= artwork.title %></td>
<td><%= artwork.genre %></td>
<td><%= artwork.category %></td>
<td><%= artwork.medium %></td>
<td><%= artwork.date %></td>
<td><%= artwork.height %> x <%= artwork.width %></td>
<td><%= artwork.availability %> </td>
<td><%= link_to 'Edit', edit_artwork_path(artwork) %></td>
<td></td>
</tr>
<% end %>
</tbody>
</table>
</div>
<br>
_form.html.rb
<%= simple_form_for #artwork, :html => {:multipart => true } do |f| %>
<% if #artwork.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#artwork.errors.count, "error") %> prohibited this artwork from being saved:</h2>
<ul>
<% #artwork.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="row">
<div class="col-md-4">
<%= f.input :image %>
</div>
<div class="col-md-8">
<%= f.input :title %>
</div>
</div>
<div class="row">
<div class="col-md-4">
<%= f.input :genre, :collection => ['Landscape', 'Still life', 'Figure', 'Interior'], :include_blank => false, :as => :radio_buttons %>
</div>
<div class="col-md-4">
<%= f.input :category, :collection => ['Painting', 'Drawing', 'Sculpture', 'Print', 'Mixed media'], :include_blank => false, :as => :radio_buttons %>
</div>
<div class="col-md-4">
<%= f.input :medium, :collection => ['Oil on paper', 'Oil on canvas', 'Oil on canvas mounted on panel', 'Watercolor', 'Ink wash', 'Charcoal', 'Graphite', 'Oil pastel'] %>
</div>
</div>
<div class="row">
<div class="col-md-4">
<%= f.input :date, :include_blank => true, as: :string, start_year: Time.now.year - 100, end_year: Time.now.year, order: [ :year, :month, :day,], hint: 'Order: Year, month, date' %>
</div>
<div class="col-md-4">
<%= f.input :height %>
<%= f.input :width %>
</div>
<div class="col-md-4">
<%= f.input :availability, :collection => ['Available for purchase','Private collection','Not for sale'], :as => :radio_buttons %>
</div>
</div>
<div class="row">
<div class="col-md-8">
<%= f.input :notes %>
</div>
</div>
<div class="row">
<div class="col-md-2 col-md-offset-10">
<%= f.button :submit, class: "btn btn-primary" %>
</div>
</div>
<!--
<div class="form-group">
<%= f.label :image %><br>
<%= f.file_field :image %>
</div>
<div class="form-group">
<%= f.label :title %><br>
<%= f.text_field :title %>
</div>
<div class="form-group">
<%= f.label :genre %><br>
<%= f.select :genre, ['Landscape', 'Still life', 'Figure', 'Interior'] %>
</div>
<div class="form-group">
<%= f.label :category %><br>
<%= f.select :category, ['Painting', 'Drawing', 'Sculpture', 'Print', 'Mixed media'] %>
</div>
<div class="form-group">
<%= f.label :medium %><br>
<%= f.select :medium, ['Oil on paper', 'Oil on canvas', 'Oil on canvas mounted on panel', 'Watercolor', 'Ink wash', 'Charcoal', 'Graphite'] %>
</div>
<div class="actions">
<%= f.submit %>
</div> -->
<% end %>
and home.html.erb (in views/pages)
<div id="artworks" class="transitions-enabled">
<% #artworks.each do |artwork| %>
<div class="box">
<%= link_to image_tag(artwork.image.url(:medium)), artwork %>
</div>
<% end %>
</div>
model: artwork.rb
class Artwork < ActiveRecord::Base
has_attached_file :image, :styles => { :medium => "300x300>", :thumb => "100x100>" }, :default_url => "/images/:style/missing.png"
validates_attachment_content_type :image, :content_type => /\Aimage\/.*\Z/
extend FriendlyId
friendly_id :slug_candidates, use: [:slugged, :history]
def slug_candidates
[
:title,
[:title, :genre],
[:title, :genre, :category],
[:title, :genre, :category, :medium]
]
end
def previous
Artwork.where(["id < ?", id]).order('id').last
end
def next
Artwork.where(["id > ?", id]).first
end
end
I'm using a few gems that I like (friendly_id), but somehow I've broken the form because I get the error "ActionController::ActionControllerError in ArtworksController#update
Cannot redirect to nil!" related to line 49:
format.html { redirect_to #artworks, notice: 'Artwork was successfully updated.' }
When I create a new artwork, I see this error: "Routing Error
No route matches [POST] "/artworks""
rake routes:
Prefix Verb URI Pattern Controller#Action
artworks GET /artworks(.:format) artworks#index
root GET / pages#home
GET / artworks#index
POST / artworks#create
new_artwork GET /new(.:format) artworks#new
edit_artwork GET /:id/edit(.:format) artworks#edit
artwork GET /:id(.:format) artworks#show
PATCH /:id(.:format) artworks#update
PUT /:id(.:format) artworks#update
DELETE /:id(.:format) artworks#destroy
about GET /about(.:format) pages#about
Can anyone help me see what I've done wrong? Thanks in advance!
Replace
redirect_to #artworks
to
redirect_to artworks_url
also modify routes.rb
Rails.application.routes.draw do
root "pages#home"
resources :artworks
get "about" => "pages#about"
end
I solved this problem by doing a few things:
Created a new 'admin.html.erb' page within my artworks/ folder. I cut and pasted the code from index.html.erb into it.
Cut code out of my home.html.erb file and pasted into the index.html.erb file.
Removed the 'def home' method from the pages_controller.
Rewrote routes as follows:
root "artworks#index"
get "about" => "pages#about"
get "admin" => "artworks#admin"
This other thread I posted helped me sort out this issue. #Ajay's and #Deep's responses helped me think this through.
Related
I'm almost certain I know what the problem is, and if I'm correct, I just can't find where the problem is lying.
When triple-nesting with the cocoon gem, I'm having what seems to be an error with incorrect pluralisation. I have 3 resources, Developments > Lots > Listings, where Developments is the grandparent, Lots is the parent and Listings is the child.
The error I'm getting is unknown attribute 'development_id' for Lot. stemming from ActiveModel::UnknownAttributeError in Developments#new. I've checked my models and partials and have been playing around with them. Here is my code:
developments_controller.rb
class DevelopmentsController < ApplicationController
before_action :set_development, only: %i[ show edit update destroy ]
# GET /developments or /developments.json
def index
#developments = Development.all
end
# GET /developments/1 or /developments/1.json
def show
end
# GET /developments/new
def new
#development = Development.new
end
# GET /developments/1/edit
def edit
end
# POST /developments or /developments.json
def create
#development = Development.new(development_params)
respond_to do |format|
if #development.save
format.html { redirect_to #development, notice: "Development was successfully created." }
format.json { render :show, status: :created, location: #development }
else
format.html { render :new, status: :unprocessable_entity }
format.json { render json: #development.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /developments/1 or /developments/1.json
def update
respond_to do |format|
if #development.update(development_params)
format.html { redirect_to #development, notice: "Development was successfully updated." }
format.json { render :show, status: :ok, location: #development }
else
format.html { render :edit, status: :unprocessable_entity }
format.json { render json: #development.errors, status: :unprocessable_entity }
end
end
end
# DELETE /developments/1 or /developments/1.json
def destroy
#development.destroy
respond_to do |format|
format.html { redirect_to developments_url, notice: "Development was successfully destroyed." }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_development
#development = Development.find(params[:id])
end
# Only allow a list of trusted parameters through.
def development_params
params.require(:development).permit(:development_name, :development_type, :development_address, :description, :estimated_completion_date, :body_corp,
lots_attributes: [:id, :status, :stage, :land_size, :price, :eta, :_destroy,
listings_attributes: [:id, :lot_number, :price, :type, :bed, :bath, :car, :house_size, :rent, :_destroy]])
end
end
development.rb (model)
class Development < ApplicationRecord
has_many :lots
accepts_nested_attributes_for :lots, reject_if: :all_blank, allow_destroy: :true
end
Lot.rb (model)
class Lot < ApplicationRecord
has_many :listings
accepts_nested_attributes_for :listings, reject_if: :all_blank, allow_destroy: :true
belongs_to :development
end
Listing.rb (model)
class Listing < ApplicationRecord
belongs_to :lot
end
_form.html.erb (partial)
<%= form_for #development do |f| %>
<div class="field">
<%= f.label :development_name%>
<%= f.text_field :development_name%>
</div>
<div class="field">
<%= f.label :development_type %>
<%= f.text_field :development_type %>
</div>
<div class="field">
<%= f.label :development_address %>
<%= f.text_field :development_address %>
</div>
<div class="field">
<%= f.label :description %>
<%= f.text_area :description %>
</div>
<div class="field">
<%= f.label :estimated_completion_date %>
<%= f.date_select :estimated_completion_date %>
</div>
<div class="field">
<%= f.label :body_corp %>
<%= f.number_field :body_corp %>
</div>
<div id="listings">
<%= f.fields_for :lots do |lot| %>
<%= render 'lot_fields', f: lot %>
<% end %>
<div class="links">
<%= link_to_add_association 'add lot', f, :lots %>
</div>
</div>
<%= f.submit %>
<% end %>
_lot_fields.html.erb (partial)
<div class="nested-fields">
<h3> New Lots </h3>
<div class="field">
<%= f.label :status %>
<br/>
<%= f.text_field :status %>
</div>
<div class="field">
<%= f.label :stage %>
<br/>
<%= f.text_field :stage %>
</div>
<div class="field">
<%= f.label :land_size %>
<br/>
<%= f.text_field :land_size %>
</div>
<div class="field">
<%= f.label :price %>
<br/>
<%= f.text_field :price %>
</div>
<div class="field">
<%= f.label :eta %>
<br/>
<%= f.text_field :eta %>
</div>
<%= link_to_remove_association "remove lot", f %>
</div>
_listing_fields.html.erb (partial)
<div class="nested-fields">
<h3> New Listing </h3>
<div class="field">
<%= f.label :status %>
<br/>
<%= f.text_field :status %>
</div>
<div class="field">
<%= f.label :stage %>
<br/>
<%= f.text_field :stage %>
</div>
<div class="field">
<%= f.label :land_size %>
<br/>
<%= f.text_field :land_size %>
</div>
<div class="field">
<%= f.label :price %>
<br/>
<%= f.text_field :price %>
</div>
<div class="field">
<%= f.label :eta %>
<br/>
<%= f.text_field :eta %>
</div>
<%= link_to_remove_association "remove listing", f %>
</div>
new.html.erb
<h1>New Development</h1>
<%= render 'form', development: #development %>
<%= link_to 'Back', developments_path %>
I have a clone project of this and I noticed in the schema.rb that there is a key difference:
t.index ["developments_id"], name: "index_lots_on_developments_id"
I believe it should be development_id instead of being pluralised, but I'm not sure where/how this needs to be changed. I'm under the impression you should never alter a schema file.
Any help is greatly appreciated!
Exactly, it should be :
t.index ["development_id"], name: "index_lots_on_development_id"
You have to rewrite a migration with
def change
remove_index :lots, name: "index_lots_on_developments_id"
add_reference :lots, :development, index: true
end
I have a rails scaffold for Accounts and another scaffold for Transactions. The Accounts model as an attribute account_name which is created within the form. For each Transaction, the form then prompts a user to select the account the transaction belongs to which is retrieved from the Accounts account_name field. This displays perfectly but when the Transaction is saved, the Account name does not save in the db or display in my index. When I edit the transaction the account name field is set to blank.
Been stuck on this for so damn long - any advice would be greatly appreciated.
My Account model:
class Account < ActiveRecord::Base
has_many :transactions
end
My Account form looks like this (and saves perfectly in the DB )
<%= form_for(#account) do |f| %>
<% if #account.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#account.errors.count, "error") %> prohibited this account from being saved:</h2>
<ul>
<% #account.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="jumbotron">
<div class="container">
<div class="form-group">
<%= f.label :account_name %><br>
<%= f.text_field :account_name, class: "form-control" %>
</div>
</div>
<div class="form-group">
<%= f.label :account_number %><br>
<%= f.number_field :account_number, class: "form-control" %>
</div>
</div>
<div class="actions">
<%= f.submit %>
</form>
<% end %>
</div>
</div>
Transaction Model
class Transaction < ActiveRecord::Base
has_many :accounts
end
The Transaction form looks like (I used the Pluck method to retrieve the Accounts account_name value and it displays all the created accounts):
<div class="form-group">
<%= form_for(#transaction) do |f| %>
<% if #transaction.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#transaction.errors.count, "error") %> prohibited this transaction from being saved:</h2>
<ul>
<% #transaction.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class = "jumbotron">
<form class="needs-validation" novalidate>
<div class="col-md-4 mb-3">
<%= f.label :date %><br>
<%= f.date_select :date, class:"form-control" %>
</div>
<div class="col-md-4 mb-3">
<%= f.label :reference %><br>
<%= f.text_field :reference, class:"form-control" %>
</div>
<div class="col-md-3 mb-3">
<%= f.label :account_name %> <br>
<%= f.select :account_name, Account.pluck(:account_name), {prompt:"Choose Account"}%>
</div>
<div class="form-row">
<div class="col-md-6 mb-3">
<%= f.label :description %><br>
<%= f.text_field :description, class:"form-control" %>
</div>
</div>
<div class="col-md-3 mb-3">
<%= f.label :amount %><br>
<%= f.text_field :amount, class:"form-control" %></br>
</div>
</br></br></br></br></br></br>
<div class="form-check form-check-inline">
</br>
<%= f.label :payment %>
<%= f.check_box :payment %> |
<%= f.label :receipt %>
<%= f.check_box :receipt %>
</div>
<div class="actions">
<%= f.submit %>
<% end %>
My transaction controller is as follows:
class TransactionsController < ApplicationController
before_action :set_transaction, only: [:show, :edit, :update, :destroy]
# GET /transactions
# GET /transactions.json
def index
#transactions = Transaction.all
#balance = 0
#transactions.each do |transaction|
if transaction.payment == true
#balance += transaction.amount
else
#balance -= transaction.amount
end
end
end
# GET /transactions/1
# GET /transactions/1.json
def show
end
# GET /transactions/new
def new
#transaction = Transaction.new
end
# GET /transactions/1/edit
def edit
end
# POST /transactions
# POST /transactions.json
def create
#transaction = Transaction.new(transaction_params)
respond_to do |format|
if #transaction.save
format.html { redirect_to transactions_url, notice: 'Transaction was successfully created.' }
format.json { render :show, status: :created, location: #transaction }
else
format.html { render :new }
format.json { render json: #transaction.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /transactions/1
# PATCH/PUT /transactions/1.json
def update
respond_to do |format|
if #transaction.update(transaction_params)
format.html { redirect_to transactions_url, notice: 'Transaction was successfully updated.' }
format.json { render :show, status: :ok, location: #transaction }
else
format.html { render :edit }
format.json { render json: #transaction.errors, status: :unprocessable_entity }
end
end
end
# DELETE /transactions/1
# DELETE /transactions/1.json
def destroy
#transaction.destroy
respond_to do |format|
format.html { redirect_to transactions_url, notice: 'Transaction was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_transaction
#transaction = Transaction.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def transaction_params
params.require(:transaction).permit(:date, :description, :reference, :account, :amount, :account_id, :payment, :receipt, account_attributes: [:account_name])
end
end
The problem seems to be in the usage of select method for creating a select tag:
<%= f.select :account_name, Account.pluck(:account_name), {prompt:"Choose Account"}%>
The second parameter is expected to be an array of two-elements arrays (one for displayed value in the select tag, and another one for the value that is going to be sent as a request parameter).
Thus, the solution you're looking for is going to look something like:
<%= f.select :account_name, Account.pluck(:account_name).map { |name| [name, name] }, {prompt:"Choose Account"}%>
Or you might want to use options_from_collection_for_select method:
<%= f.select :account_name, options_from_collection_for_select(Account.all, :name, :name) %>
You are facing that issue because you need to store the id of the account as a reference in the transaction.
Currently you are saving account name, so it is not prefetching and saving the data
You can use collection_select and tell that save id into DB and display account_name in select tag.
Syntax:
collection_select(object, method, collection, value_method, text_method, options = {}, html_options = {})
The :value_method and :text_method parameters are methods to be called
on each member of collection. The return values are used as the value
attribute and contents of each <option> tag, respectively.
Here is the collection_select in your example:
<%= f.collection_select(:account_name,Account.all, :id, :account_name, :prompt => 'Choose Account') %>
Here is the documentation for the same
I'm new to Rails and I have no idea what's going on here. The app I am building is an online store. The current functionality works, but the change I am trying to implement isn't working. As a starting point, I will show the working version that I have now. Here is my carts/show.html.erb file:
<p id="notice"><%= notice %></p>
<h2>My Cart</h2>
<table class="table table-responsive table-striped">
<thead>
<tr>
<th>Item</th>
<th>Quantity</th>
<th>Total Price in Galleons</th>
<th>Total Price in Muggle Currency</th>
</tr>
<tbody>
<%= render(#cart.line_items) %>
<tr>
<td>Total</td>
<td><%= number_to_currency(#cart.total_price * 7.35) %></td>
<td></td>
<td></td>
</tr>
</tbody>
</thead>
</table>
<br>
<div class="row">
<div class="col-md-3">
<div class="row">
<div class="col-md-4">
<%= link_to 'Back', products_path, :class => 'btn btn-primary whiteText' %>
</div>
<div class="col-md-4">
<%= link_to "Checkout", new_charge_path, :class => 'btn btn-success whiteText' %>
</div>
<div class="col-md-4">
<%= link_to 'Empty Cart', #cart, method: :delete, data: {confirm: 'Are you sure you want to empty your cart?'}, :class => 'btn btn-danger whiteText' %>
</div>
</div>
</div>
<div class="col-md-9"></div>
</div>
However, I am wanting to change the workflow a bit so that it uses my Order scaffold to redirect the user to an address confirmation page (orders/new.html.erb) after clicking "Checkout" on the Cart show page. Once the address is confirmed, it should then route the customer to the payments page, which is what the new_charge_path in my current Checkout link redirects to already.
So to start with, I am replacing the Checkout link and turning it from this:
<%= link_to "Checkout", new_charge_path, :class => 'btn btn-success whiteText' %>
to this:
<%= link_to "Checkout", new_order_path, method: :get, :class => 'btn btn-success whiteText' %>
This redirect functions as expected, and takes me to orders/new.html.erb, which contains the following:
<h1>Order Information</h1>
<br>
<%= render 'form', order: #order %>
<%= link_to 'Back', products_path %>
The form it renders contains the following code:
<%= form_for(order) do |f| %>
<% if order.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(order.errors.count, "error") %> prohibited this order from being saved:</h2>
<ul>
<% order.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="row">
<div class="col-md-6">
<div class="field">
<%= f.label :first_name %>
<%= f.text_field :first_name, size: 20, :value => current_user.first_name, :class => "form-control" %>
</div>
<div class="field">
<%= f.label :last_name %>
<%= f.text_field :last_name, size: 20, :value => current_user.last_name, :class => "form-control" %>
</div>
<div class="field">
<%= f.label :address %>
<%= f.text_area :address, size: 40, :value => current_user.address, :class => "form-control" %>
</div>
<div class="field">
<%= f.label :city %>
<%= f.text_area :city, size: 20, :value => current_user.city, :class => "form-control" %>
</div>
<div class="field">
<%= f.label :state %>
<%= f.text_area :state, size: 2, :value => current_user.state, :class => "form-control" %>
</div>
<div class="field">
<%= f.label :email %>
<%= f.text_field :email, size: 40, :value => current_user.email, :class => "form-control" %>
</div>
<div class="field">
<%= f.label :pay_type %>
<%= f.select :pay_type, Order.pay_types.keys, prompt: 'Select a payment method', :class => "form-control" %>
</div>
</div>
<div class="col-md-6">
<%= form_tag(payments_path, class: "form-inline") do %>
<%= hidden_field_tag(:purchase_amount_cents, #cart.total_price) %>
<div class="form_group">
<%= label_tag(:credit_card_number, "Credit Card Number", class: "sr-only") %>
<%= text_field_tag(:credit_card_number, "", class: "form-control", placeholder: "Credit Card #") %>
</div>
<br>
<div class="form_group">
<%= label_tag(:expiration_month, "Month", class: "sr-only") %>
<%= text_field_tag(:expiration_month, "", class: "form-control", placeholder: "Month") %>
<br>
<%= label_tag(:expiration_year, "Year", class: "sr-only") %>
<%= text_field_tag(:expiration_year, "", class: "form-control", placeholder: "Year") %>
<br>
<%= label_tag(:cvc, "Year", class: "sr-only") %>
<%= text_field_tag(:cvc, "", class: "form-control", placeholder: "CVC #") %>
</div>
<br>
<div class="form_group">
<%= submit_tag("Purchase Cart", class: "btn btn-default", id: "purchase") %>
</div>
<% end %>
</div>
</div>
<hr>
<div class="actions">
<%= f.submit 'Proceed to Payment' %>
</div>
<% end %>
The payment options are credit card (Stripe) or Paypal. I will eventually add the Paypal functionality but Stripe API is all I have for now.
Here is my Order Controller:
class OrdersController < ApplicationController
include CurrentCart
before_action :set_cart, only: [:new, :create]
before_action :ensure_cart_isnt_empty, only: :new
before_action :set_order, only: [:show, :edit, :update, :destroy]
# GET /orders
# GET /orders.json
def index
#orders = Order.all
end
# GET /orders/1
# GET /orders/1.json
def show
end
# GET /orders/new
def new
#order = Order.new
end
# GET /orders/1/edit
def edit
end
# POST /orders
# POST /orders.json
def create
#order = Order.new(order_params)
#order.add_line_items_from_cart(#cart)
respond_to do |format|
if #order.save
format.html { redirect_to new_charge_path}
else
format.html { render :new }
format.json { render json: #order.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /orders/1
# PATCH/PUT /orders/1.json
def update
respond_to do |format|
if #order.update(order_params)
format.html { redirect_to #order, notice: 'Order was successfully updated.' }
format.json { render :show, status: :ok, location: #order }
else
format.html { render :edit }
format.json { render json: #order.errors, status: :unprocessable_entity }
end
end
end
# DELETE /orders/1
# DELETE /orders/1.json
def destroy
#order.destroy
respond_to do |format|
format.html { redirect_to orders_url, notice: 'Order was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_order
#order = Order.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def order_params
params.require(:order).permit(:first_name, :last_name, :address, :city, :state, :email, :pay_type)
end
def ensure_cart_isnt_empty
if #cart.line_items.empty?
redirect_to products_path, notice: 'Your cart is empty!'
end
end
end
Here is my Charge Controller:
class ChargesController < ApplicationController
include CurrentCart
before_action :set_cart, only: [:new, :create]
def new
end
def create #METHOD IS CALLED AFTER PAYMENT IS MADE
# Amount in cents
#amount = #cart.total_price
customer = Stripe::Customer.create(
:email => params[:stripeEmail],
:source => params[:stripeToken]
)
charge = Stripe::Charge.create(
:customer => customer.id,
:amount => #amount,
:description => 'Customer',
:currency => 'usd'
)
Cart.destroy(session[:cart_id])
rescue Stripe::CardError => e
flash[:error] = e.message
redirect_to new_charge_path
end
end
Here's the problem. While the redirects work as expected, the #amount in the Charge controller is set to $0.00 if the order controller is used. If, however, the Cart links directly to the Charge controller, then the correct dollar amount is used. So, I am assuming that somehow the cart object is being lost or having its value reset.
Here is my set_cart method:
def set_cart
#cart = Cart.find(params[:id])
end
And here is my CurrentCart module:
module CurrentCart
private
def set_cart
#cart = Cart.find(session[:cart_id])
rescue ActiveRecord::RecordNotFound
#cart = Cart.create
session[:cart_id] = #cart.id
end
end
My idea you need to passing forward the value #cart.total_price from cart show form to order controller here some steps to do
inside your link (you pass the value as params)
<%= link_to "Checkout", new_order_path(total_price: #cart.total_price), method: :get, :class => 'btn btn-success whiteText' %>
inside order_controller (you get the params and put in instance variabel)
# GET /orders/new
def new
#order = Order.new
#temp_total_price = params[:total_price]
end
inside order_form insert between your form_for tag, we need to put this in the form as hidden value, so it can be passing to create method for charge
<%= hidden_field_tag 'total_price', #temp_total_price %>
inside your class ChargesController create method you can get the total_price
#total_price = params[:total_price]
I know it's little bit log but probably this can help
Scenario
I have got four resources in my Rails project, viz. Drive, Drivecomment, College and Manager
resources :drives do
resources :drivecomments
end
devise_for :colleges, controllers: { sessions: "college/sessions", registrations: "college/registrations" }
devise_for :managers, controllers: { sessions: "manager/sessions", registrations: "manager/registrations" }
The association between them are as follows:
Manager => belongs_to :college
College => has_many :managers
College => has_many :drives
Drives => belongs_to :college
Drives => has_many :drivecomments
Drivecomments => belongs_to :drives
As it is clear from above association, each Drive can have multiple Drivecomments, which can be submitted by the Managers.
Also, I have created a custom Controller#View resource "m" for providing a Manager Interface (coz default manager is generated from devise and using the same resource means all post operations get redirected to "create" method, including sign_up, which eventually means i cannot sign_up at all)
resources :m, :only => [:index] do
member do
get :drive
end
end
So, inside my "m", I have created a form for posting a comment as well as a table for displaying all comments.
FOR DISPLAYING COMMENTS:
../drive.html.erb
<h2>Drive Comments</h2>
<table>
<thead>
<tr>
<th>Jobseeker</th>
<th>Comment</th>
<th colspan="3"></th>
</tr>
</thead>
<tbody>
<% #comments.each do |comment| %>
<tr>
<td><%= comment.jobseeker.first_name %></td>
<td><%= comment.title %></td>
</tr>
<% end %>
</tbody>
</table>
../m_controller.erb
def drive
#drive = #drives.find_by_id(params[:id])
#comments = #drive.drivecomments
#addcomment = Drivecomment.new
end
FOR ADDING A COMMENT:
../drive.html.erb
<%= form_for [#addcomment], as: :addcomment, url: {action: "addcomment"} do |f| %>
<div><%= f.hidden_field :drive_id, :value => #drive.id %></div>
<div><%= f.hidden_field :jobseeker_id, :value => 2 %></div>
<div><%= f.label "Comment:" %><%= f.text_field :title %></div>
<div><%= f.submit "Post Comment" %></div>
<% end %>
../m_controller.erb
def new
#addcomment = Drivecomment.new
end
def create
#drive = #drives.find_by_id(params[:id])
#addcomment = #drive.drivecomments.build
#addcomment.save
end
Problem
When I submit my form, I get an error saying
ActionController::UrlGenerationError in M#drive
Showing /home/xxx/xxx/xxx/app/views/m/drive.html.erb where line #30 raised:
No route matches {:action=>"addcomment", :controller=>"m", :id=>"5"}
Extracted source (around line #30):
</table>
<%= form_for [#addcomment], as: :addcomment, url: {action: "addcomment"} do |f| %>
<div><%= f.hidden_field :drive_id, :value => #drive.id %></div>
<div><%= f.hidden_field :jobseeker_id, :value => 2 %></div>
Alternatively, If I write my form like this
<%= form_for [#drive, #addcomment] do |f| %>
<div><%= f.hidden_field :drive_id, :value => #drive.id %></div>
<div><%= f.hidden_field :jobseeker_id, :value => 2 %></div>
<div><%= f.label "Comment:" %><%= f.text_field :title %></div>
<div><%= f.submit "Post Comment" %></div>
<% end %>
it submits the form successfully and a value gets added, but I get redirected to "http://localhost:3000/drives/5/drivecomments/8" from "http://localhost:3000/m/5/drive" which I don't want.
Please tell what might be the workaround for this problem.
Additional Info
Drivecomments _form.html.erb
<%= form_for([#drive, #drivecomment]) do |f| %>
<% if #drivecomment.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#drivecomment.errors.count, "error") %> prohibited this drivecomment from being saved:</h2>
<ul>
<% #drivecomment.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :jobseeker_id %><br>
<%= f.number_field :jobseeker_id %>
</div>
<div class="field">
<%= f.label :drive_id %><br>
<%= f.number_field :drive_id %>
</div>
<div class="field">
<%= f.label :title %><br>
<%= f.text_area :title %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Extract from drivecoments_controller.rb
before_action :set_drivecomment, only: [:show, :edit, :update, :destroy]
before_filter :load_drive
def new
#drivecomment = #drive.drivecomments.new
end
def create
#drivecomment = #drive.drivecomments.new(drivecomment_params)
respond_to do |format|
if #drivecomment.save
format.html { redirect_to [#drive, #drivecomment], notice: 'Drivecomment was successfully created.' }
format.json { render :show, status: :created, location: #drivecomment }
else
format.html { render :new }
format.json { render json: #drivecomment.errors, status: :unprocessable_entity }
end
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_drivecomment
#drivecomment = Drivecomment.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def drivecomment_params
params.require(:drivecomment).permit(:jobseeker_id, :drive_id, :title)
end
def load_drive
#drive = Drive.find(params[:drive_id])
end
If you want to user the action create from the controller m you should define your form like this:
<%= form_for #addcomment, url: url_for(controller: :m, action: :create) do |f| %>
Also, you need to define the create action on your routes, update this piece of your routes:
resources :m, :only => [:index, :create]
I am creating a customer service web app for our clients that allows them to submit new customer service tickets, once logged in. I have a login system that I created using the sorcery gem, and I have modified it to accept an additional field: client code.
We are assigning client codes to help prevent unauthorized users from creating accounts.
Upon login, it asks for the information like so:
Name:
Email:
Client Code: (we assign this)
Password:
My question is this, is there a way to only display customer service tickets to clients with the same client code? For example, The "Coca-Cola" clients would only see other "Coca-Cola" tickets and the "Pepsi" clients would only see other "Pepsi" tickets, etc.
Here is my Tickets Controller:
class TicketsController < ApplicationController
before_filter :require_login
def new
#ticket = Ticket.new
end
def create
#ticket = Ticket.new(ticket_params)
if
#ticket.save
redirect_to #ticket
flash[:notice] = "Your Ticket has been submitted. We will contact you very soon!"
else
flash[:notice] = "Something went wrong :("
render 'new'
end
end
def show
#ticket = Ticket.find(params[:id])
end
def index
#tickets = Ticket.all
end
def edit
#ticket = Ticket.find(params[:id])
end
def update
#ticket = Ticket.find(params[:id])
if #ticket.update(ticket_params)
redirect_to #ticket
else
render 'edit'
end
end
def destroy
#ticket = Ticket.find(params[:id])
#ticket.destroy
redirect_to tickets_path
end
private
def ticket_params
params.require(:ticket).permit(:name, :email, :phone, :help)
end
end
Here is the Ticket Index View:
<div class="panel panel-default">
<div class="panel-heading">Ticket Queue</div>
<div class="panel-body">
<table class="table">
<tr>
<th>Name</th>
<th>Phone</th>
<th></th>
<th></th>
</tr>
<% #tickets.each do |ticket| %>
<tr>
<td><%= ticket.name %></td>
<td><%= ticket.phone %></td>
<td><%= button_to "View or Edit", ticket_path(ticket), :class => "btn btn-primary btn-sm", :method => :get %></td>
<td><%= button_to "Delete", ticket_path(ticket), :class => "btn btn-primary btn- sm", :method => :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
</table>
</div>
Here is the New Ticket View:
<div class="panel panel-info">
<div class="panel-heading">
<div id="wrapper">
<h1 class="panel-title">New Ticket
<div id="first"><%= button_to "Back", root_path, :class => "btn btn-primary btn-sm", :method => :get %></div>
</div>
</h1>
</div>
<div class="panel-body">
<%= form_for :ticket, url: tickets_path do |f| %>
<p>
<%= f.label "Name:" %>
<%= f.text_field :name %>
</p>
<p>
<%= f.label "Email:" %>
<%= f.text_field :email %>
</p>
<p>
<%= f.label :"Phone #:" %>
<%= f.text_field :phone %>
</p>
<p>
<%= f.label :"How can we help?" %>
<p><%= f.text_area :help, :cols=> 38, :rows => 8 %></p>
</p>
<p>
<button type="submit" class="btn btn-primary btn-sm"><span class="glyphicon glyphicon-envelope"></span> Submit Ticket</button>
</p>
<% end %>
</div>
</div>
Here is the User Model:
class User < ActiveRecord::Base
authenticates_with_sorcery!
validates :password, length: { minimum: 3 }
validates :password, confirmation: true
validates :password_confirmation, presence: true
validates :code, inclusion: { in: %w(Client1, Client2), message: "Please enter a valid Client Code", :allow_nil => false}
validates :email, uniqueness: true
validates_format_of :email, :with => /\A([^#\s]+)#((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i
end
Here is the New User View:
<%= 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 :email %><br>
<%= f.text_field :email %>
</div>
<div class="field">
<%= f.label :password %><br />
<%= f.password_field :password %>
</div>
<div class="field">
<%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation %>
</div>
<div class="field">
<%= f.label "Client Code" %><br />
<%= f.text_field :code %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Here is the User Controller:
class UsersController < ApplicationController
before_action :set_user, only: [:show, :edit, :update, :destroy]
skip_before_filter :require_login, only: [:index, :new, :create]
# GET /users
def index
#users = User.all
end
# GET /users/1
def show
end
# GET /users/new
def new
#user = User.new
end
# GET /users/1/edit
def edit
end
# POST /users
def create
#user = User.new(user_params)
if #user.save
redirect_to(:users, notice: 'User was successfully created')
else
render :new
end
end
# PATCH/PUT /users/1
def update
if #user.update(user_params)
redirect_to #user, notice: 'User was successfully updated.'
else
render :edit
end
end
# DELETE /users/1
def destroy
#user.destroy
redirect_to users_url, notice: 'User was successfully destroyed.'
end
private
# Use callbacks to share common setup or constraints between actions.
def set_user
#user = User.find(params[:id])
end
# Only allow a trusted parameter "white list" through.
def user_params
params.require(:user).permit(:email, :password, :password_confirmation, :code)
end
end
Let me know if you need to see anything else, thank you!
From your example, I would think Users would have an additional database layer:
class User < ActiveRecord::Base
belongs_to :company
has_many :tickets, through: :companies
end
class Company < ActiveRecord::Base
has_many :users
has_many :tickets
end
class Ticket < ActiveRecord::Base
belongs_to :company
end
Then you can easily display tickets associated with each company