ActionController::UnknownFormat respond_to do |format| - ruby-on-rails

My product_controller
class ProductController < ApplicationController
def index
#product = Product.all
#categories = Category.all
end
def from_category
#product = Product.joins(:category).where(category: { id: params[:cat_id] })
respond_to do |format|
format.js
end
end
end
My form_category.js.erb
$("#products_grid").html("<%= escape_javascript(render partial: 'product/products_list', locals: { product: #selected } ) %>");
I want to filter products by categories and found this way, but I get an error on this part

Related

(RoR) json and nested objects: get attribute in object of object

My goal is an output like this (for each attachment):
url:
"/uploads/attachment/picture/15/5ee306c9-e263-466b-b56d-1c7c9d2ae17b.jpg"
What I have at the moment:
attachments_controller.rb
class AttachmentsController < ApplicationController
before_action :logged_in_user
def index
#attachments = current_user.attachments.all
respond_to do |format|
format.json do
render :json => #attachments.each{ |o| o.picture.url }
end
end
end
...
Try
respond_to do |format|
format.json do
render :json => #attachments.map { |o| { url: o.picture.url } }
end
end

Receiving the error "Couldn't find Product with id=5" when I click on view cart link in my app

I have a "view cart" link which returns the following error when clicked:
Couldn't find Product with id=5
My products_controller.rb file looks like this:
class ProductsController < ApplicationController
# GET /products
# GET /products.json
def index
#products = Product.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: #products }
end
end
# GET /products/1
# GET /products/1.json
def show
#product = Product.find(params[:id])
logger.debug("Event code is: #{params[:id]}")
respond_to do |format|
format.html # show.html.erb
format.json { render json: #product }
end
end
# GET /products/new
# GET /products/new.json
def new
#product = Product.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #product }
end
end
# GET /products/1/edit
def edit
#product = Product.find(params[:id])
end
# POST /products
# POST /products.json
def create
#product = Product.new(params[:product])
respond_to do |format|
if #product.save
format.html { redirect_to #product, notice: 'Product was successfully created.' }
format.json { render json: #product, status: :created, location: #product }
else
format.html { render action: "new" }
format.json { render json: #product.errors, status: :unprocessable_entity }
end
end
end
# PUT /products/1
# PUT /products/1.json
def update
#product = Product.find(params[:id])
respond_to do |format|
if #product.update_attributes(params[:product])
format.html { redirect_to #product, notice: 'Product was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #product.errors, status: :unprocessable_entity }
end
end
end
# DELETE /products/1
# DELETE /products/1.json
def destroy
#product = Product.find(params[:id])
#product.destroy
respond_to do |format|
format.html { redirect_to products_url }
format.json { head :no_content }
end
end
def add_to_cart
#products = cookies[:products]
if #products.blank?
#products = cookies[:products] = params[:id]
else
unless #products.include? params[:id]
cookies[:products] = #products + '&&' + params[:id]
end
end
redirect_to products_url
end
def remove_from_cart
#current_products = cookies[:products]
if #current_products.blank?
redirect_to products_url
else
#current_products = #current_products.split("&&")
#current_products.delete(params[:id])
#current_products = #current_products.join("&&")
cookies[:products] = #current_products
redirect_to products_url
end
end
def view_cart
#products = cookies[:products].split("&&").map { |s| s.to_i }
end
end
My view_cart.html.erb file looks like this:
<h1>Your Cart</h1>
<table>
<tr>
<th>Name</th>
<th>Price</th>
<th></th>
<th></th>
<th></th>
</tr>
<% total = 0 %>
<% #products.each do |product| %>
<tr>
<td><%= Product.find(product).name %></td>
<td><%= Product.find(product).price %></td>
<% total += Product.find(product).price %>
</tr>
<% end %>
</table>
Total: <%= total %>
I am a Rails novice and would appreciate some help with this.
You don't need to use find since you already have all #products. You iterate over that collection with each and you can access each element attributes like that:
<% #products.each do |product| %>
<tr>
<td><%= product.name %></td>
<td><%= product.price %></td>
<% total += product.price %>
</tr>
<% end %>
i.e. product in the block is already "found" :)
We've done a cart implementation before (based on this Railscast):
(more explained below)...
Fix
Your error stems from the fact you're trying to find a product which doesn't exist.
There are a lot of problems with your code (for example, using cart methods inside your products controller). The simple fix is as follows:
#app/controllers/products_controller.rb
class ProductsController < ApplicationController
def cart_view
#products = cart_contents
end
private
def cart_contents
##Cart product ID's
products = cookies[:products].split("&&").map { |s| s.to_i }
##Only proceed if user has products in cart
if (products && products != {})
#Determine Quantities (if ID appears 2 times etc)
quantities = Hash[products.uniq.map {|i| [i, products.count(i)]}]
#Get products from DB
products_array = Product.find(products.uniq)
#Create Qty Array with "qty" attached
products_new = {}
products_array.each{
|a| products_new[a] = {"qty" => quantities[a.id.to_s]}
}
#Output appended
return products_new
end
end
end
This is code we use (explained further down page) and will basically give you an ActiveRecord collection for your view.
So you'll be able to use the following:
#app/views/products/view_cart.html.erb
<% #products.each do |product| %>
<%= product.name %>
<% end %>
Structure
As mentioned, we've implemented this before:
#config/routes.rb
resources :cart, only: [:index, :create, :destroy]
#app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
def cart_session
#cart_session ||= CartSession.new(session)
end
helper_method :cart_session
end
#app/controllers/cart_controller.rb
class CartController < ApplicationController
include ApplicationHelper
#Index
def index
#items = cart_session.cart_contents
end
#Add
def create
session[:cart] ||={}
products = session[:cart][:products]
#If exists, add new, else create new variable
if (products && products != {})
session[:cart][:products] << params[:id]
else
session[:cart][:products] = Array(params[:id])
end
#Handle the request
respond_to do |format|
format.json { render json: cart_session.build_json }
format.html { redirect_to cart_index_path }
end
end
#Delete
def destroy
session[:cart] ||={}
products = session[:cart][:products]
id = params[:id]
all = params[:all]
#Is ID present?
unless id.blank?
unless all.blank?
products.delete(params['id'])
else
products.delete_at(products.index(id) || products.length)
end
else
products.delete
end
#Handle the request
respond_to do |format|
format.json { render json: cart_session.build_json }
format.html { redirect_to cart_index_path }
end
end
end
The above gives you a cart_session method, which creates or invokes the CartSession model. This is just a class which puts all the user's "cart items" in a session.
The important thing to note is that because the cart controller is separate to the products controller, it allows you to split your code into a resourceful structure.
It also means you keep your code extremely lean - the only overhead will be a small array of product IDs kept in a session variable. No ActiveRecord or anything...
#app/models/cart_session.rb
class CartSession
#Initalize Cart Session
def initialize(session)
#session = session
#session[:cart] ||= {}
end
#Cart Count
def cart_count
if (#session[:cart][:products] && #session[:cart][:products] != {})
#session[:cart][:products].count
else
0
end
end
#Cart Contents
def cart_contents
products = #session[:cart][:products]
if (products && products != {})
#Determine Quantities
quantities = Hash[products.uniq.map {|i| [i, products.count(i)]}]
#Get products from DB
products_array = Product.find(products.uniq)
#Create Qty Array
products_new = {}
products_array.each{
|a| products_new[a] = {"qty" => quantities[a.id.to_s]}
}
#Output appended
return products_new
end
end
#Qty & Price Count
def subtotal
products = cart_contents
#Get subtotal of the cart items
subtotal = 0
unless products.blank?
products.each do |a|
subtotal += (a[0]["price"].to_f * a[1]["qty"].to_f)
end
end
return subtotal
end
#Build Hash For ActiveMerchant
def build_order
#Take cart objects & add them to items hash
products = cart_contents
#order = []
products.each do |product|
#order << {name: product[0].name, quantity: product[1]["qty"], amount: (product[0].price * 100).to_i }
end
return #order
end
#Build JSON Requests
def build_json
session = #session[:cart][:products]
json = {:subtotal => self.subtotal.to_f.round(2), :qty => self.cart_count, :items => Hash[session.uniq.map {|i| [i, session.count(i)]}]}
return json
end
end
This allows you to use the following:
#app/views/cart/index.html.erb
<% #items.each do |item| %>
<%= item.name %> #=> this will be the ActiveRecord "Product" record
<% end %>
You'll also be able to do the following:
#app/views/products/show.html.erb
<%= link_to "Add To Cart", cart_path(#product.id), method: :post %> #-> adds product to cart
The best thing about this method is that the cart functionality is split into its own controller & model. At the moment, you've broken the resourceful convention by including non-rest methods in your products controller.
You need to keep your cart functionality in its own controller, and products functionality in its own controller. The above achieves this.

Link to Order Index Rails 4

I am using Rails 4 with the Impressionist gem to get view count of my Articles.
On my index page I have a link labeled "Most Popular"
I also have access to a method that will order articles by the view count:
#articles = Article.order('impressions_count ASC')
What is the best way to order the index by impression_count when a user clicks the "most popular button?" I am having trouble finding documentation on this.
Here is my articles_controller.rb
class ArticlesController < ApplicationController
load_and_authorize_resource
before_action :set_article, only: [:show, :edit, :update, :destroy]
def index
if params[:q].present?
#articles = Article.search(params[:q], misspellings: {edit_distance: 1}, page: params[:page], per_page: 12)
#search = current_or_guest_user.searches.create!(query: params[:q], searched_at: Time.now)
else
#articles = Article.order('impressions_count ASC').page(params[:page]).per(12)
#search = current_or_guest_user.searches.create!(query: params[:q], searched_at: Time.now)
end
if #articles.blank?
return redirect_to request_path
#search = current_or_guest_user.searches.create!(query: params[:q], searched_at: Time.now)
end
get_query
end
def autocomplete
#articles = Article.search params[:term], autocomplete: true
render json: #articles
end
def search
#articles = Article.search params[:q], suggest: true, page: params[:page], per_page: 5
#search = current_or_guest_user.searches.create!(query: params[:q], searched_at: Time.now)
render 'index'
end
def show
impressionist(#article, nil, { unique: [:session_hash] })
#skip_error = true
#subarticles = #article.subarticles.approved.order(:cached_votes_score => :desc)
if request.path != article_path(#article)
redirect_to #article, status: :moved_permanently
else
respond_to do |format|
format.html # show.html.erb
format.json { render json: #article }
end
end
end
def new
end
def edit
end
def create
respond_to do |format|
if #article.save
format.html { redirect_to #article, notice: 'Article was successfully created.' }
format.json { render :show, status: :created, location: #article }
else
format.html { render :new }
format.json { render json: #article.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #article.update(article_params)
format.html { redirect_to #article, notice: 'Article was successfully updated.' }
format.json { render :show, status: :ok, location: #article }
else
format.html { render :edit }
format.json { render json: #article.errors, status: :unprocessable_entity }
end
end
end
def destroy
#article.destroy
respond_to do |format|
format.html { redirect_to articles_url, notice: 'Article was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_article
#article = Article.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def article_params
params.require(:article).permit(:title, :specific, :category, :aka, :image1, :image2, :video1, :video2)
end
def get_query
#userquery = params[:q]
end
end
The first else clause in your index is this:
else
#articles = Article.order('impressions_count ASC').page(params[:page]).per(12)
That is why you are getting them sorted by impressions_count. Just get rid of it to return them sorted by most recent.
else
#articles = Article.order(created_at: :desc).page(params[:page]).per(12)
You then need to set your "most popular" link to return the #articles variable sorted by impressions_count as you did in your old code.
You will need to make your action in the controller to return the results you want, something like:
Add a variable to your whitelist:
def article_params
params.require(:article).permit(:title, :specific, :category, :aka, :image1, :image2, :video1, :video2, :imp_sort)
end
Then in your index action you can add it in:
def index
if params[:q].present?
#articles = Article.search(params[:q], misspellings: {edit_distance: 1}, page: params[:page], per_page: 12)
#search = current_or_guest_user.searches.create!(query: params[:q], searched_at: Time.now)
else
if article_params[:imp_sort]
#articles = Article.order('impressions_count ASC').page(params[:page]).per(12)
else
#articles = Article.order(created_at: :desc).page(params[:page]).per(12)
end
#search = current_or_guest_user.searches.create!(query: params[:q], searched_at: Time.now)
end
if #articles.blank?
return redirect_to request_path
#search = current_or_guest_user.searches.create!(query: params[:q], searched_at: Time.now)
end
get_query
end
in your index.html.erb you will need to have your link do something like:
<%= link_to "Sort by Impressions", articles_path(:imp_sort => true) %>

NoMethodError show issue

I have a model that looks like:
class Product < ActiveRecord::Base
before_create :generate_token
def to_param
token
end
private
def generate_token
self.token = loop do
random_token = SecureRandom.urlsafe_base64(10, false)
break random_token unless Product.exists?(token: random_token)
end
end
end
My controller looks like:
def set_product
#product = Product.find_by(token: params[:token])
end
When I create a new product, I get the error:
NoMethodError in ProductsController#show
undefined method `name' for nil:NilClass
and my show in my controller looks like:
def show
#title = #product.name
end
my create looks like:
def create
#product = Product.new(product_params)
##product.user_id = current_user.id
respond_to do |format|
if #product.save
format.html { redirect_to #product, notice: 'Product was successfully created.' }
format.json { render action: 'show', status: :created, location: #product }
else
format.html { render action: 'new' }
format.json { render json: #product.errors, status: :unprocessable_entity }
end
end
end
Also, in my controller I have a callback that looks like:
before_action :set_product, only: [:show, :edit, :update, :destroy]
But in the rails console insert, it shows the name being inserted. the name column is being set.
Can you show me your url that goes to that page
if you are passing the token by product_path(token)
then try
def set_product
#product = Product.find_by(token: params[:id]) # id instead of token
end
if it is a form then
def set_product
#product = Product.find_by(token: params[:product][:token])
end
I am prettry sure your current params[:token] is not right that is why you cannot find the product.

Unknown Action: The action 'create' could not be found for CommentsController

I'm working on an app that allows users to comment on a single "work" (think blog post). The associations in the models are as follows:
class User < ActiveRecord::Base
has_many :works
has_many :comments
class Work < ActiveRecord::Base
belongs_to :user
has_many :comments
class Comment < ActiveRecord::Base
belongs_to :user
belongs_to :post
belongs_to :work
There's a form on the Works show page that allows users to post a comment:
<%= form_for(#comment) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<div class="field">
<%= f.text_area :content, placeholder: "Post a comment!" %>
</div>
<%= f.submit "Post", class: "btn btn-small btn-primary" %>
<% end %>
The Works controller is as follows. Note that I'm adding the build comment functionality here so that the form on the Works page functions:
class WorksController < ApplicationController
#before_filter :current_user, only: [:edit, :update]
def index
#works = Work.all
#comment = #work.comments.build(params[:comment])
#comment.user = current_user
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => #works }
end
end
def create
#work = current_user.works.create(params[:work])
redirect_to current_user
end
def edit
#work = current_user.works.find(params[:id])
end
def new
#work = current_user.works.new
end
def destroy
#work = current_user.works.find(params[:id]).destroy
flash[:success] = "Work deleted"
redirect_to current_user
end
def update
#work = current_user.works.find(params[:id])
if #work.update_attributes(params[:work])
flash[:success] = "Profile updated"
redirect_to #work
else
render 'edit'
end
end
def show
#work = Work.find(params[:id])
#comment = #work.comments.build
#comment.user = current_user
#activities = PublicActivity::Activity.order("created_at DESC").where(trackable_type: "Work", trackable_id: #work).all
#comments = #work.comments.order("created_at DESC").where(work_id: #work ).all
respond_to do |format|
format.html # show.html.erb
format.xml { render :xml => #work }
end
end
end
And lastly, here is the Comments controller:
class CommentsController < ApplicationController
before_filter :authenticate_user!
def index
#comments = Comment.all
end
def show
#comment = Comment.find(params[:id])
#activities = PublicActivity::Activity.order("created_at DESC").where(trackable_type: "Comment", trackable_id: #comment).all
respond_to do |format|
format.html # show.html.erb
format.xml { render :xml => #comment }
end
def update
#comment = current_user.comments.find(params[:id])
if #comment.update_attributes(params[:comment])
flash[:success] = "Comment updated"
redirect_to #comment
end
end
def create
#work = Work.find(params[:id])
#comment = #work.comments.build(params[:comment])
#comment.user = current_user
if #comment.save
#flash[:success] = "Post created!"
redirect_to #work
else
render 'home#index'
end
end
end
end
When I attempt to submit a comment using the comment form on the works show view page, I get the following error:
Unknown action
The action 'create' could not be found for CommentsController
Why can't it find the create action on the Comments controller? Any help would be greatly appreciated.
Thanks!
Your comments controller show action is missing an end, i.e. this:
def show
#comment = Comment.find(params[:id])
#activities = PublicActivity::Activity.order("created_at DESC").where(trackable_type: "Comment", trackable_id: #comment).all
respond_to do |format|
format.html # show.html.erb
format.xml { render :xml => #comment }
end
should be this:
def show
#comment = Comment.find(params[:id])
#activities = PublicActivity::Activity.order("created_at DESC").where(trackable_type: "Comment", trackable_id: #comment).all
respond_to do |format|
format.html # show.html.erb
format.xml { render :xml => #comment }
end
end
(right now it is 'falling' into the create action so the create action never gets set up).
You will then probably need to change the final:
end
end
end
end
to be
end
end
end
as this was probably 'compensating' for the mismatch and allowing the page to precompile in Ruby.

Resources