Hi I have a rails App where Users can have a timetable with a one to many relationship.
When i add this
<%= link_to "delete", user, method: :delete,
data: { confirm: "You sure?" } %>
to _user.html it renders a delete link which deletes a user no problem
but when i add this
<%= link_to "delete", timetable, method: :delete,
data: { confirm: "You sure?" } %>
to _timetable.html.erb it throws an error
ActionController::RoutingError (No route matches [DELETE] "/timetable.4"):
My Routes.rb
get 'password_resets/new'
get 'password_resets/edit'
root 'static_pages#home'
get 'help' => 'static_pages#help'
get 'about' => 'static_pages#about'
get 'contact' => 'static_pages#contact'
get 'timetable' => 'timetables#new'
get 'signup' => 'users#new'
get 'mobile' => 'users#mobile'
get 'login' => 'sessions#new'
post 'login' => 'sessions#create'
delete 'logout' => 'sessions#destroy'
resources :account_activations, only: [:edit]
resources :password_resets, only: [:new, :create, :edit, :update]
resources :timetables
resources :users
resources :projects
Timetable Controller
class TimetablesController < ApplicationController
before_action :logged_in_user, only: [:create, :destroy]
before_action :correct_user, only: :destroy
def index
#timetables = current_user.timetables.find(current_user)
end
def new
#user = User.find(current_user)
#timetable = Timetable.new
#timetables = #user.timetables.paginate(page: params[:page], per_page: 1)
end
def feed
Timetable.where("user_id = ?", id)
end
def show
#feed_items3 = current_user.feed.paginate(page: params[:page])
#timetable = current_user.timetables.find(params[:id])
end
def create
#timetable = Timetable.new(timetable_params)
#user = User.find(current_user)
if current_user.timetables.create(timetable_params)
flash[:success] = "Timetable created!"
redirect_to timetable_path
else
flash[:success] = "Timetable not created!"
redirect_to timetable_path
end
end
def destroy
#timetable = Timetable.find(params[:id])
#timetable.destroy
redirect_to timetables_path, notice: "The timetable #{#timetable.name} has been deleted."
end
private
def timetable_params
params.require(:timetable).permit(:name, :attachment, :id)
end
def correct_user
#project = current_user.projects.find_by(id: params[:id])
redirect_to root_url if #project.nil?
end
end
Without seeing your Controllers it is hard to be sure, but I would look at a few areas:
Specifying the path & the timetable object to be deleted:
<%= link_to "Delete Timetable", timetable_path(timetable), :method => :delete %>
Ensure that the destroy action for the timetable sits within the timetable_controller
Regarding your routes.rb file I am not sure why you need:
get 'timetable' => 'timetables#new'
and then also
resources :timetables
This is duplication - why not try use 'only' (edit to your preference):
resources :timetables, only: [:index, :new, :create, :destroy]
Related
I got problem in validation with modal popup. This is my index.html.haml:
.container-index
%h1 All Posts Here
%button.btn.btn-info(type="button" data-toggle="modal" data-target="#myModal") New Post
= render 'form'
- #posts.each do |post|
.col-md-4
%h3= link_to post.title,post
%p= post.content
= "#{time_ago_in_words post.created_at} ago "
_form.html.haml:
.container
= simple_form_for current_user.posts.build do |f|
%div.modal.fade#myModal(tabindex="-1" role="dialog" aria-labelledby="myModalLabel")
%div.modal-dialog(role="document")
%div.modal-content
%div.modal-header
%button.close(type="button" data-dismiss="modal" aria-label="Close")
%span(aria-hidden="true") ×
%h3.modal-title#myModalLabel New Post
%div.modal-body
= f.input :title, label:"Title",class:'form-group',name: 'title'
= f.input :content, label:'Content',class:'form-group',name:'content'
%div.modal-footer
%button.btn.btn-danger#mynewpostclose(type="button" data-dismiss="modal") Close
= f.submit 'Create', class:"btn btn-primary"
post.rb:
validates :title, presence: true
validates :content, presence: true
posts_controller.rb:
before_action :find_post, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!, except: [:index, :show]
def index
#posts = Post.all.order("created_at DESC")
end
def new
#post = current_user.posts.build
end
def create
#post = current_user.posts.build(post_params)
if #post.save
redirect_to #post, notice: 'Created Successfully'
else
render 'new'
end
end
def show
end
def edit
end
def update
if #post.update(post_params)
redirect_to #post, notice: 'Updated Successfully'
else
render 'edit'
end
end
def destroy
#post.destroy
redirect_to posts_path(#post), notice: 'Deleted Successfully'
end
private
def find_post
#post = Post.find(params[:id])
end
def post_params
params.require(:post).permit(:title, :content)
end
I do not know how to show up the warningWhen I create a new post without any title or contentit'll link to a blank page and don't create any new postI just wanna call warning inside modal when submit, anyone can help me,plzz?
In your form you need to replace this line
= simple_form_for current_user.posts.build do |f|
with this;
= simple_form_for #post do |f|
This way, when your create action renders the new template, the form will be given the instance of Post which failed to save allowing simple form to display the error messages.
I'm creating a new Purchase from the create method of the ChargesContoller.
I can successfully create the new Purchase and pass the information related to the charge.
My questions is: How can I get the order id to the Purchase?
Here' how the checkout process works:
Event > Option > Reservation > Order "has many reservations" >
in the Order show view, I have the Stripe button which creates a new charge > redirect to Purchase.
The Purchase is basically a receipt for the order. That's why I would like to show the order id and the reservations associated with the order. I know is not passing the order id because I can see it in the rails console
Should I use a different kind of association like has_many_and_belongs_to_many?
Maybe a joinTable?
I was reading at this part of the rails guides but I'm not sure if I'm looking in the right place: http://guides.rubyonrails.org/association_basics.html
or maybe is the way I'm trying to pass the order id "in the charges create" to the purchase:
purchase = Purchase.create(customer_email: params[:stripeEmail], amount: params[:amount],
customer_card: params[:stripeToken], order_id: params[:order_id], customer_id: customer.id)
Order Model:
class Order < ActiveRecord::Base
belongs_to :order_status
belongs_to :purchase
has_many :reservations
before_create :set_order_status
before_create :create_unique_identifier
before_save :total_for_no_price
before_save :update_subtotal
def to_param
uuid
end
def subtotal
reservations.collect{ |r| r.price }.sum
end
def total_for_no_price
if self.subtotal.nil?
self[:subtotal] = 0
end
end
def create_unique_identifier
self.uuid = SecureRandom.uuid
end
private
def set_order_status
self.order_status_id = 1
end
def update_subtotal
self[:subtotal] = subtotal
end
end
Purchase model:
class Purchase < ActiveRecord::Base
has_many :orders
has_many :reservations, through: :orders
end
Charges Controller:
class ChargesController < ApplicationController
def new
end
def create
# Amount in cents
#order = Order.find_by_uuid(session[:order_id])
#reservations = #order.reservations
#amount = #order.subtotal.to_i * 100
customer = Stripe::Customer.create(
:email => params[:stripeEmail],
:source => params[:stripeToken]
)
charge = Stripe::Charge.create(
:customer => customer.id,
:amount => #amount,
:description => #order.id,
:currency => 'usd'
)
purchase = Purchase.create(customer_email: params[:stripeEmail], amount: params[:amount],
customer_card: params[:stripeToken], order_id: params[:order_id], customer_id: customer.id)
if charge.save
#order_id = #order.update_attributes(order_status_id: 2)
#redirect_to #order
redirect_to purchase
reset_session
end
rescue Stripe::CardError => e
flash[:error] = e.message
redirect_to new_charge_path
end
end
Orders Controller:
class OrdersController < ApplicationController
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
#order = Order.find_by_uuid(params[:id])
#reservations = #order.reservations
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)
respond_to do |format|
if #order.save
format.html { redirect_to #order, notice: 'Order was successfully created.' }
format.json { render :show, status: :created, location: #order }
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_by_uuid(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def order_params
params.require(:order).permit(:subtotal, :tax, :total, :order_status_id, :uuid)
end
end
Order Show page with the charge button:
<div class="container-fluid events-container">
<div class="row">
<div class="col-sm-12">
<h4>Your Registrations:</h4>
<% #order.reservations.each do |reservation| %>
<h4><%= reservation.name %> <%= reservation.lastname %> | <%= reservation.email %> | <%= reservation.phone %></h4>
<h4><%= reservation.gender %> <%= reservation.shirt %> </h4>
<% unless reservation.team === 'N/A' %>
<h4>Team: <%= reservation.team %></h4>
<% end %>
<% unless reservation.redeemcode === 'N/A' %>
<h4>Redeem Code: <%= reservation.redeemcode %></h4>
<% end %>
<hr>
<% end %>
<h1>Order Total: <%= number_to_currency(#order.subtotal)%></h1>
<% if #order.order_status_id === 1 %>
<%= form_tag charges_path(#order) do %>
<article>
<% if flash[:error].present? %>
<div id="error_explanation">
<p><%= flash[:error] %></p>
</div>
<% end %>
</article>
<script src="https://checkout.stripe.com/checkout.js" class="stripe-button"
data-key="<%= Rails.configuration.stripe[:publishable_key] %>"
data-description= "Event Registration(s)"
data-amount="<%= #order.subtotal.to_i * 100%>"
data-locale="auto">
</script>
<% end %>
<% end %>
<h3>Need to Modify you order? <%= link_to 'Back to Cart', cart_path %> </h3>
</div>
</div>
</div>
I solve this by changing:
order_id: params[:order_id] to order_id: (#order.id)
in the Charges Controller
Updated Charges Controller:
class ChargesController < ApplicationController
def new
end
def create
# Amount in cents
#order = Order.find_by_uuid(session[:order_id])
#reservations = #order.reservations
#amount = #order.subtotal.to_i * 100
customer = Stripe::Customer.create(
:email => params[:stripeEmail],
:source => params[:stripeToken]
)
charge = Stripe::Charge.create(
:customer => customer.id,
:amount => #amount,
:description => #order.id,
:currency => 'usd'
)
purchase = Purchase.create(customer_email: params[:stripeEmail], amount: params[:amount],
customer_card: params[:stripeToken], order_id: (#order.id), customer_id: customer.id)
if charge.save
#order_id = #order.update_attributes(order_status_id: 2)
#redirect_to #order
redirect_to purchase
reset_session
end
rescue Stripe::CardError => e
flash[:error] = e.message
redirect_to new_charge_path
end
end
I am trying to create a page within my application that shows all listings from a specific user. I am using Devise gem for my users. i do not need/want authentication, therefore the page should be open the the general public. I have already created a "Seller" page where a seller can manage their own listings. so how can I create a link on each listing on my homepage that connects the
<p><%= "Sold by #{listing.user.name}" %></p>
the new show page for that user? thanks!
my listings_controller:
class ListingsController < ApplicationController
before_action :set_listing, only: [:show, :edit, :update, :destroy]
before_filter :authenticate_user!, only: [:seller, :new, :create, :edit, :update, :destroy]
before_filter :check_user, only: [:edit, :update, :destroy]
def seller
#listings = Listing.where(user: current_user).order("created_at DESC")
end
# GET /listings
# GET /listings.json
def index
if params[:category].blank?
#listings = Listing.all.order("created_at DESC").paginate(:page => params[:page], :per_page => 16)
else
#category_id = Category.find_by(name: params[:category]).id
#listings = Listing.where(category_id: #category_id).order("created_at DESC").paginate(:page => params[:page], :per_page => 16)
end
end
# GET /listings/1
# GET /listings/1.json
def show
end
# GET /listings/new
def new
#listing = Listing.new
end
# GET /listings/1/edit
def edit
end
# POST /listings
# POST /listings.json
def create
#listing = Listing.new(listing_params)
#listing.user_id = current_user.id
if current_user.recipient.blank?
Stripe.api_key = ENV["STRIPE_API_KEY"]
token = params[:stripeToken]
recipient = Stripe::Recipient.create(
:name => current_user.name,
:type => "individual",
:bank_account => token
)
current_user.recipient = recipient.id
current_user.save
end
respond_to do |format|
if #listing.save
format.html { redirect_to #listing, notice: 'Listing was successfully created.' }
format.json { render :show, status: :created, location: #listing }
else
format.html { render :new }
format.json { render json: #listing.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /listings/1
# PATCH/PUT /listings/1.json
def update
respond_to do |format|
if #listing.update(listing_params)
format.html { redirect_to #listing, notice: 'Listing was successfully updated.' }
format.json { render :show, status: :ok, location: #listing }
else
format.html { render :edit }
format.json { render json: #listing.errors, status: :unprocessable_entity }
end
end
end
# DELETE /listings/1
# DELETE /listings/1.json
def destroy
#listing.destroy
respond_to do |format|
format.html { redirect_to listings_url, notice: 'Listing was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_listing
#listing = Listing.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def listing_params
params.require(:listing).permit(:name, :category_id, :description, :price, :image)
end
def check_user
if current_user != #listing.user
redirect_to root_url, alert: "Sorry, this listing belongs to someone else"
end
end
end
my current routes:
Rails.application.routes.draw do
mount RailsAdmin::Engine => '/admin', as: 'rails_admin'
resources :categories
devise_for :users
resources :listings do
resources :orders, only: [:new, :create]
end
get 'pages/about'
get 'pages/contact'
get 'seller' => "listings#seller"
get 'sales' => "orders#sales"
get 'purchases' => "orders#purchases"
# or
root 'listings#index'
end
and finally, my listing model:
class Listing < ActiveRecord::Base
if Rails.env.development?
has_attached_file :image, :styles => { :medium => "200x", :thumb => "100x100>" }, :default_url => "404.jpg"
else
has_attached_file :image, :styles => { :medium => "200x", :thumb => "100x100>" }, :default_url => "404.jpg",
:storage => :dropbox,
:dropbox_credentials => Rails.root.join("config/dropbox.yml"),
:path => ":style/:id_:filename"
end
validates_attachment_content_type :image, :content_type => /\Aimage\/.*\Z/
validates :name, :category_id, :description, :price, presence: true
validates :price, numericality: { greater_than: 0}
validates_attachment_presence :image
belongs_to :user
belongs_to :category
has_many :orders
end
my index page where I want to link to the seller specific page
<div class="center">
<div class="row">
<% #listings.each do |listing| %>
<div class="col-md-3">
<div class="thumbnail">
<%= link_to image_tag(listing.image.url), listing %>
<div class="caption">
<h3><%= listing.name %></h3>
<p><%= number_to_currency(listing.price) %></p>
<p><%= "Sold by #{listing.user.name}" %></p>
</div>
</div>
</div>
<% end %>
</div>
</div>
<br>
<div class="center">
<%= will_paginate #posts, renderer: BootstrapPagination::Rails %>
</div>
<% if user_signed_in? %>
<div class="right">
<%= link_to new_listing_path, class: "btn btn-primary", data: { no_turbolink: true } do %>
<i class="glyphicon glyphicon-plus"></i> New Listing
<% end %>
</div>
<% end %>
<br>
'User' is a model that you have created: devise only manages sessions, registrations, passwords, unlocks, and confirmations (the gem provides a controller for each one of these).
You should create your own UsersController, in which you can define the show action that you need. You should also declare a different path in your routes, or you'd have a conflict as '/users' is already used by devise. Something like
resources :users, only: [:show], path: 'sellers'
Then you can use
<p><%= "Sold by #{link_to listing.user.name, user_path(listing.user)}" %></p>
I have Comment, User and Product models. The user can leave a comment in the Product's show view.
So, I tried to implement the commenting functionality, but when I submit the form with the comment, I get the following error:
ActionController::UrlGenerationError at /comments
No route matches {:action=>"show", :controller=>"products", :id=>nil} missing required
keys: [:id]
The comments table in db looks like this:
id :integer not null, primary key
body :text
created_at :datetime not null
updated_at :datetime not null
user_id :integer
product_id :integer
Here' my views/comments/_form.html.erb:
<%= simple_form_for(#comment) do |f| %>
<%= f.error_notification %>
<%= f.input :body, required: true, placeholder: 'Type in a new comment...', input_html: { class: 'form-control'}, label: false %>
<%= f.button :submit, class: 'btn btn-primary btn-block' %>
<% end %>
My CommentsController.rb:
class CommentsController < ApplicationController
before_action :set_comment, only: [:edit, :update, :destroy]
def create
# #comment = Comment.new(user: current_user, product: params[:id])
#comment = Comment.new(comment_params)
if #comment.save
respond_to do |format|
format.html do
redirect_to product_path(#comment.product_id), notice: 'Comment Created!'
end
end
else
redirect_to product_path(#comment.product_id), notice: 'Something went wrong'
end
end
def edit
end
def update
if #comment.update(comment_params)
respond_to do |format|
format.html do
redirect_to product_path(#comment.product_id), notice: 'Comment Updated'
end
end
else
redirect_to comment_path(#comment_id), notice: 'Something went wrong'
end
end
def destroy
#comment.destroy!
respond_to do
redirect_to product_path(#comment.product_id), notice: 'Comment Deleted'
end
end
private
def set_comment
#comment = Comment.find(params[:id])
end
def comment_params
params.require(:comment).permit(:body)
end
end
The error is thrown at line 15 in the create method in else condition: redirect_to product_path(#comment.product_id), notice: 'Something went wrong', which means that not only it is giving me the no routes matches error, but it also doesn't save the comment.
In my views/products/show.html.erb there's this line:
<%= render 'comments/form' %>
And in my ProductsController.rb I have this:
def show
#product = Product.find(params[:id])
#comment = Comment.new
#comments = Comment.where(product_id: product.id).order('created_at DESC')
end
In my routes file I have this:
resources :products, only: [:show]
resources :comments, only: [:create, :edit, :update, :destroy]
I've been trying to figure out how to resolve that issue, but didn't succeed. Could you please help me with that?
Everytime I click the "Sign in with Github" button, I get a Page not found. When I try http://127.0.0.1:3000/auth/github/callback
I get an error called OmniAuth::Strategies::OAuth2::CallbackError which says "csrf_detected | CSRF detected" . Here is my code:
initializers/omniauth.rb:
OmniAuth.config.logger = Rails.logger
Rails.application.config.middleware.use OmniAuth::Builder do
provider :github, ENV['GITHUB_ID'], ENV['GITHUB_SECRET'],
:scope => 'user,public_repo',
:redirect_uri => ENV['http://127.0.0.1:3000']
end
routes.rb:
root 'users#new'
get '/auth/:provider/callback' => 'sessions#create'
get '/signout' => 'sessions#destroy', as: :signout
end
views/users/new.html.erb:
<% if current_user %>
<h1> Welcome: </h1>
<h2><%= link_to 'Sign out', signout_path %></h2>
<% else %>
<h2><%= link_to 'Sign in with Github', "/auth/github" %></h2>
<% end %>
sessions_controller.rb:
class SessionsController < ApplicationController
def new
end
def create
auth = request.env["omniauth.auth"]
user = User.where(:provider => auth['provider'], :uid => auth['uid'].to_s).first || User.from_omniauth(auth)
reset_session
session[:user_id] = user.id
redirect_to root_url, :notice => "Signed in!"
end
def destroy
session[:user_id] = nil
redirect_to root_url, :notice => 'Signed out!'
end
def failure
redirect_to root_url, :alert => "Authentication error: #{params[:message].humanize}"
end
end
user.rb:
class User < ActiveRecord::Base
def self.from_omniauth(auth)
# where(auth.slice(:provider, :uid)).first_or_initialize.tap
create! do |user|
user.provider = auth.provider
user.uid = auth.uid
user.name = auth.info.name
user.oauth_token = auth.credentials.token
user.oauth_expires_at = Time.at(auth.credentials.expires_at)
user.save!
end
end
end
application_controller.rb:
class ApplicationController < ActionController::Base
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
protect_from_forgery with: :exception
helper_method :current_user
private
def current_user
#current_user ||= User.find(session[:user_id]) if session[:user_id]
end
end
Please help!
I managed to fix this error by adding scope: 'user:email' to the end of the provider statement in the OmniAuth initializer file.
Rails.application.config.middleware.use OmniAuth::Builder do
provider :github, ENV['GITHUB_KEY'], ENV['GITHUB_SECRET'], scope: 'user:email'
end
Error 404 means "File or Directory not found". In other words, the server received and understood your request, and would have been quite willing to fulfil the request, but the data that you asked for doesn't exist.