Routing to show action instead of custom action - ruby-on-rails

news_controller.rb
class NewsController < ApplicationController
before_action :set_news, only: [:show]
before_action :authenticate_user!, except: [:show, :index ]
def index
#news = News.where( state: true ).paginate(:page => params[:page], :per_page => 12).order('id DESC')
end
def new
#news = News.new
end
def show
#news_photos = #news.news_photos
end
def create
#news = News.new(news_params)
if #news.save
if params[:images]
params[:images].each do |image|
#news.news_photos.create(image: image)
end
end
#news_photos = #news.news_photos
redirect_to edit_news_path(#news), notice: "Saved..."
else
render :new
end
end
def destroy
#news = News.find(params[:id])
#news.destroy
respond_to do |format|
format.html { redirect_to news_index_path }
# format.json { head :no_content }
end
end
def search
#news = News.search(params[:search])
end
private
def set_news
#news = News.find(params[:id])
end
def news_params
params.require(:news).permit( :title, :description, :category, :keywords, :user_id, :email, :user_name)
end
end
news.rb
class News < ApplicationRecord
extend FriendlyId
friendly_id :slug_candidates, use: [:slugged, :finders, :history]
def slug_candidates
[ :title,
[:title, :id]
]
end
def self.search(search)
pg_search_scope :search_full_text,
:against => :full_text,
:using => { :tsearch => { :prefix => true } }
end
end
index.html.erb
<div class="fh5co-box">
<h3 class="heading">Search</h3>
<%= form_tag(look_path, :method => "get") do %>
<%= text_field_tag :search, params[:search], placeholder: "Search news" %>
<%= submit_tag "Search" %>
<% end %>
</div>
</div>
</div>
routes.rb
resources :news, :except => [ :search]
get 'news/search' => 'news#search', :as => 'look'
As I submit the data inside the search field, it is routing to the show action instead of search action.
the routes are
ews_index GET /news(.:format) news#index
POST /news(.:format) news#create
new_news GET /news/new(.:format) news#new
edit_news GET /news/:id/edit(.:format) news#edit
news GET /news/:id(.:format) news#show
PATCH /news/:id(.:format) news#update
PUT /news/:id(.:format) news#update
DELETE /news/:id(.:format) news#destroy
look GET /news/search(.:format) news#search
log:
Started GET "/news/search?utf8=%E2%9C%93&search=tax&commit=Search" for 183.83.117.57 at 2017-04-10 07:36:13 -0500
Processing by NewsController#show as HTML
Parameters: {"utf8"=>"▒~\~S", "search"=>"tax", "commit"=>"Search", "id"=>"search"}
^[[1m^[[36mNews Load (0.5ms)^[[0m ^[[1m^[[34mSELECT "news".* FROM "news" WHERE "news"."slug" = $1 ORDER BY "news"."id" ASC LIMIT $2^[[0m [["slug", "search"], ["LIMIT", 1]]
^[[1m^[[36mNews Load (0.7ms)^[[0m ^[[1m^[[34mSELECT "news".* FROM "news" INNER JOIN "friendly_id_slugs" ON "friendly_id_slugs"."sluggable_id" = "news"."id" AND "friendly_id_slugs"."sluggable_type" = $1 WHERE ("friendly_id_slugs"."sluggable_type" = 'News' AND "friendly_id_slugs"."slug" = 'search') ORDER BY "friendly_id_slugs"."id" DESC LIMIT $2^[[0m [["sluggable_type", "News"], ["LIMIT", 1]]
Completed 404 Not Found in 5ms (ActiveRecord: 1.2ms)
ActiveRecord::RecordNotFound (can't find record with friendly id: "search"):
app/controllers/news_controller.rb:111:in `set_news'
Don't know where I have gone wrong.Is there anything to do with the slugs???
Any Help is highly Appreciated.Thanks in Advance!!!

Routes are search for in order.
So in other words you show action matches the get request for /news/(:id) and your system processes SHOW. Move the line:
get 'news/search' => 'news#search', :as => 'look'
higher up in the routes file and it should work fine, keep in mind though that this will block search from being used as a id/slug. A cleaner route would be
get '/search/news' => 'news#search', :as => 'look'
as it'd get outside the news scope and you wouldn't have conflicts with the news model.

Related

How to download an uploaded stored file from the database in rails?

Im trying to implement a download functionality to an uploaded pdf file in my app. For some reason the record can not be found? If I check the GET Request I see that it tries to use the url ending "/resumes/download.5". 5 is the record id from the stored file. What am I missing? How can I debug issues like that in the future? Byebug did not work this time for some reason.
views/resumes/show.html.erb
<%= link_to "Download", resume_download_path(#resume) %>
resumes_controller.rb
class ResumesController < ApplicationController
around_filter :catch_not_found
before_action :find_resume, only: [ :show, :edit, :update, :destroy, :download ]
before_action :authenticate_user!
def show
end
def new
if #resume = current_user.resume
redirect_to #resume
else
#resume = Resume.new
end
end
def create
#resume = current_user.build_resume(resume_params)
if #resume.save
redirect_to #resume
else
render :new
end
end
def edit
end
def update
if #resume.update resume_params
redirect_to #resume, notice: "Your resume was successfully saved!"
else
render 'edit'
end
end
def destroy
#resume.destroy
redirect_to new_resume_path, notice: "Your resume was successfully deleted!"
end
def download
send_data #resume, type: "application/pdf", disposition: "attachment"
end
private
def resume_params
params.require(:resume).permit( :user_id, :download_file, :remove_download_file)
end
def find_resume
#resume = Resume.find(params[:id])
end
def catch_not_found
yield
rescue ActiveRecord::RecordNotFound
redirect_to(root_url, :notice => 'Record not found')
end
end
routes.rb
Rails.application.routes.draw do
devise_for :users
root 'welcomes#index'
resources :resumes
get "resumes/download", as: "resume_download"
get '*path' => redirect('/')
end
When clicking on the download link:
Started GET "/resumes/download.5" for 77.8.13.5 at 2017-08-23 21:22:14 +0000
Cannot render console from 77.8.13.5! Allowed networks: 127.0.0.1, ::1, 127.0.0.0/127.255.255.255
Processing by ResumesController#show as
Parameters: {"id"=>"download"}
Resume Load (0.2ms) SELECT "resumes".* FROM "resumes" WHERE "resumes"."id" = ? LIMIT 1 [["id", 0]]
Redirected to https://rails-tutorial-martinbortowski.c9.io/
Completed 302 Found in 3ms (ActiveRecord: 0.2ms)
Started GET "/" for 77.8.13.5 at 2017-08-23 21:22:15 +0000
Cannot render console from 77.8.13.5! Allowed networks: 127.0.0.1, ::1, 127.0.0.0/127.255.255.255
Processing by WelcomesController#index as HTML
Rendered welcomes/index.html.erb within layouts/application (0.2ms)
Completed 200 OK in 39ms (Views: 38.4ms | ActiveRecord: 0.0ms)
resources :resumes do
get :download, on: :member
end
Will give you an idiomatically correct REST route:
resumes/:id/download
Change your link to:
<%= link_to "Download", download_resume_path(#resume), "data-turbolinks" => false %>
See Rails Routing from the Outside In - Adding More RESTful Actions.
You download link seems to be wrong.
change in your routes.rb
get "resumes/download", as: "resume_download"
to
controller :resumes do
get "resumes/download/:id" => :show, as: :resume_download
end
views/resumes/show.html.erb
change your link
<%= link_to "Download", resume_download_path(#resume) %>
to
<%= link_to "Download", resume_download_path(id: #resume) %>

Rails button_to No route matches {:action=>"complete", :controller=>"dashboard", :name=>"Order"}

Please help i have tried my best. I really need your help.
So im trying to make a mark order as complete. Now it all works up to the button to mark order as complete. I ran a migration to add.
class AddCompleteToOrder < ActiveRecord::Migration
def change
add_column :orders, :complete, :boolean, default: false
end
end
Then i added a method the order.rb of
def complete!
update(complete: true)
end
Then routes.rb
resources :orders do
post "complete", to: "orders#complete", on: :member
end
Then this is the button
= button_to "Mark as complete", { action: "complete", id: #order.id }
But i dont have a #order.id
but a order does have a #order.name so i changed it to
= button_to "Mark as complete", { action: "complete", name: #order.name }
But then i get the error:
ActionController::UrlGenerationError in Dashboard#dadmin
Showing /Users/jacksharville/Desktop/dancer/app/views/dashboard/dadmin.html.haml where line #87 raised:
No route matches {:action=>"complete", :controller=>"dashboard", :name=>"Order"}
Extracted source (around line #87):
85
86
87
= link_to "Back to Dashboard", :back, :class => 'btn-danger btn'
= button_to "Mark as complete", { action: "complete", name: #order.name }
So clearly im doing the routes.rb wrong but i cant fix it. Please help. Any help greatly appreciated.
routes.rb (full file)
Rails.application.routes.draw do
mount RailsAdmin::Engine => '/admin', as: 'rails_admin'
get 'home/index'
root 'home#index'
#pages
get '/why' => 'pages#why'
get '/trak' => 'pages#trak'
get '/contact' => 'pages#contact'
get '/mydms' => 'pages#mydms'
get '/air' => 'pages#air'
get '/ocean' => 'pages#ocean'
get '/road' => 'pages#road'
get '/courier' => 'pages#courier'
get 'fulfilment' => 'pages#fulfilment'
get 'express' => 'pages#express'
resources :dashboard
get 'dadmin' => 'dashboard#dadmin'
get 'myorders' => 'dashboard#myorders'
get 'label' => 'dashboard#label'
resources "contacts", only: [:new, :create]
devise_for :users
as :user do
get 'users/edit' => 'devise/registrations#edit', :as => 'edit_user_registration'
put 'users' => 'devise/registrations#update', :as => 'user_registration'
end
resources "orders"
get "/confirm" => "confirmations#show"
get 'dconfirmation' => 'orders#confirmation'
resources :orders do
post "complete", to: "orders#complete", on: :member
end
end
orders_controller.rb
class OrdersController < ApplicationController
before_filter :authenticate_user!
def new
#order = Order.new
end
def create
#order = current_user.orders.new(order_params)
#order.email = current_user.email
#order.name = current_user.name
#order.address_line_1 = current_user.address_line_1
#order.address_line_2 = current_user.address_line_2
#order.postcode = current_user.postcode
#order.city = current_user.city
#order.country = current_user.country
if #order.save
redirect_to dconfirmation_path
end
end
def order_params
params.require(:order).
permit(
:email,
:delivery_name,
:company_name,
:delivery_address1,
:delivery_address2,
:delivery_address3,
:delivery_city,
:delivery_postcode,
:delivery_country,
:phone,
:package_contents,
:description_content,
:restricted_items,
:terms_conditions,
:insurance,
:contents_value,
:cf_reference,
:reference_number
)
end
def show
#user = User.find(params[:id])
end
def confirmation
end
def complete!
order = Order.find(params[:id])
order.complete!
# handle response
end
end
dashboard_controller.rb
class DashboardController < ApplicationController
before_filter :authenticate_user!
def index
end
def admindashboard
(current_user.nil?) ? redirect_to(root_path) : (redirect_to(root_path) unless current_user.admin?)
end
def adminuser
(current_user.nil?) ? redirect_to(root_path) : (redirect_to(root_path) unless current_user.admin?)
end
def dadmin
(current_user.nil?) ? redirect_to(root_path) : (redirect_to(root_path) unless current_user.admin?)
# #order = Order.all
#order = Order.order("name").page(params[:page]).per(1)
end
def myorders
#order = current_user.orders.order("name").page(params[:page]).per(1)
end
def show
#user = User.find(params[:id])
end
def label
#order = current_user.orders.order("name").page(params[:page]).per(1)
end
def complete!
order = Order.find(params[:id])
order.complete!
# handle response
end
end
You can specify this additional option in the button_to tag :controller => "order", but the proper way to use button_to tag is to not create a separate hash for options. Instead use it as a button_to("Mark as complete", controller: "order", action: "complete", name: #order.name)
try this
button_to "Mark as complete", { controller: "orders", action: "complete", name: #order.name }, {method: :post}
This link can help: Routing Error - No route matches when using button_to with custom action
rake routes give me:
complete_order POST /order/:id/complete(.:format) orders#complete
You need to move the complete action from DashboardsController to OrdersController, which is where it is defined in the routes file.
Also, you can probably use:
= button_to "Mark as complete", complete_order_path(#order)
The controller action is looking for params[:order_id] so it can find the right order. I am not sure how orders are defined in your view, but you will need to pass an order object to the path.
If by any chance you defined a to_param method in Order class, which defines order's name rather than id as params, you will need to update the complete action to look for an order by name.
But my guess is that it is the default id. So passing the order object to the path should work.

Multiple check box not working Rails 4

I am using Rails 4.1.6
I am trying to create ability to select at least 3 services and then save with advertisement.
Model structure is like this:
class Service < ActiveRecord::Base
belongs_to :advertisement
end
class Advertisement < ActiveRecord::Base
has_many :services
end
My form:
<% #services.each do |service| %>
<li>
<%= check_box_tag 'service_ids[]', service.id -%>
<%= h service.name -%>
</li>
<% end %>
Controller:
class AdvertisementsController < ApplicationController
before_action :authenticate_user!
before_action :set_advertisement, only: [:show, :edit, :update, :destroy]
respond_to :html, :xml, :json
def index
#advertisements = Advertisement.all
respond_with(#advertisements)
end
def show
#advertisement = Advertisement.find(params[:id])
respond_with(#advertisement)
end
def new
#advertisement = Advertisement.new
#services = Service.all
respond_with(#advertisement)
end
def edit
end
def create
#advertisement = Advertisement.new(advertisement_params)
if #advertisement.save
if params[:images]
params[:images].each { |image|
#advertisement.pictures.create(image: image)
}
respond_with(#advertisement)
end
else
format.html { render 'new'} ## Specify the format in which you are rendering "new" page
format.json { render json: #advertisement.errors } ## You might want to specify a json format as well
end
end
def update
#advertisement.update(advertisement_params)
respond_with(#advertisement)
end
def destroy
#advertisement.destroy
respond_with(#advertisement)
end
private
def set_advertisement
#advertisement = Advertisement.find(params[:id])
end
def advertisement_params
params.require(:advertisement).permit(:name, :user_id, :advertisement_id, :image,:terms_of_service,:region, :age, :height, :phone_number,:description)
end
end
When I check multpile services and click save there is no error. When I checked log files i got this message "
Parameters: ... "service_ids"=>["1", "2", "3"] ...
But then in console I check:
2.1.3 :008 >t = Advertisement.last (ALL OK)
....
2.1.3 :008 > t.services
=> #<ActiveRecord::Associations::CollectionProxy []>
And this is error. Problem in associations, but everyrhing seems ok to me.
What could be the problem?
Thanks
There are no service_ids in advertisement_params. Add them:
#advertisement = Advertisement.new(advertisement_params.merge(service_ids: params[:service_ids]))
# or
#advertisement = Advertisement.new(advertisement_params)
#advertisement.service_ids = service_ids

Listing all tags for an acts_as_taggable

I have an app that has factoids that have tags using the acts_as_taggable gem. I currently have it setup so that when on the index page for the factoids, clicking on any of the tags filters the factoids by that tag. What I am attempting to do now is create an index page that lists all of the tags in the app. This seemed rather straight forward...
create a tag.rb
create a tags_controller.rb
add a view in tags/index.html.erb
The problem is that this causes my previously implemented search to break. If there are any additional things that are needed, please let me know.
FactoidsController (the index part of it)
class FactoidsController < ApplicationController
helper_method :sort_column, :sort_direction
before_filter :authenticate_user!
# GET /factoids
# GET /factoids.json
def index
if params[:tag]
#factoids = Factoid.tagged_with(params[:tag]).order(sort_column + ' ' + sort_direction).paginate(:per_page => 15, :page => params[:page])
else
#factoids = Factoid.search(params[:search]).order(sort_column + ' ' + sort_direction).paginate(:per_page => 15, :page => params[:page])
end
respond_to do |format|
format.html # index.html.erb
format.json { render json: #factoids }
end
end
def tagged
if params[:tag].present?
#factoids = Factoid.tagged_with(params[:tag])
else
#factoids = Factoid.postall
end
end
private
def sort_column
params[:sort] || "created_at"
end
def sort_direction
params[:direction] || "desc"
end
end
Tags Controller
class TagsController < ApplicationController
helper_method :sort_column, :sort_direction
before_filter :authenticate_user!
# GET /factoids
# GET /factoids.json
def index
#tags = Tag.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: #tags }
end
end
private
def sort_column
params[:sort] || "created_at"
end
def sort_direction
params[:direction] || "desc"
end
end
Routes
QaApp::Application.routes.draw do
devise_for :users
resources :factoids
resources :tags
get "home/index"
match 'tagged' => 'factoids#tagged', :as => 'tagged'
get 'tags/:tag', to: 'factoids#index', as: :tag
root :to => 'home#index'
end
You dont need to go through all the trouble of creating a tag model and controller. `acts-as-taggable-on provides a method to find a list of all tags for the model.
2.0.0-p451 :008 > Factoid.tag_counts
ActsAsTaggableOn::Tag Load (2.0ms) SELECT tags.*, taggings.tags_count AS count FROM "tags" JOIN (SELECT taggings.tag_id, COUNT(taggings.tag_id) AS tags_count FROM "taggings" INNER JOIN factoids ON factoids.id = taggings.taggable_id WHERE (taggings.taggable_type = 'Factoid' AND taggings.context = 'tags') AND (taggings.taggable_id IN(SELECT factoids.id FROM "factoids")) GROUP BY taggings.tag_id HAVING COUNT(taggings.tag_id) > 0) AS taggings ON taggings.tag_id = tags.id
=> #<ActiveRecord::Relation [#<ActsAsTaggableOn::Tag id: 1, name: "tag">]>
This will return a ActiveRecord::Relation of all the tag objects. You can run map on it to get a array of tags
Factoid.tag_counts.map(&:name)
=> ["tag"]

No method error issue rails

I'm a new rails developer who has a basic scaffolded crud application that I modified a bit.
I'm getting this error:
undefined method description for #<ActiveRecord::Relation:0x00000102df26d8>
when I visit john/recipes/46. Here's my view:
<h1 itemprop="name"><%= #recipe.name %></h1>
<ul>
<li><%= link_to 'Edit', edit_recipe_path(#recipe) %></li>
</ul>
<p itemprop="description"><%= #recipe.description %></p>
here's my routes:
match "/:username" => "recipes#index"
scope ':username' do
resources :recipes
end
here's my show index:
def show
#user = User.find_by_username params[:username]
#recipe = Recipe.where(:user_recipe_id => params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #recipe }
end
end
and my model:
before_save :set_next_user_recipe_id
belongs_to :users
validates :user_recipe_id, :uniqueness => {:scope => :user_id}
def to_param
self.user_recipe_id.to_s
end
def set_next_user_recipe_id
self.user_recipe_id ||= get_new_user_recipe_id
end
def get_new_user_recipe_id
user = self.user
max = user.recipes.maximum('user_recipe_id') || 0
max + 1
end
attr_accessible :description, :duration, :author, :url, :name, :yield, :ingredients_attributes, :user_recipe_id, :directions_attributes, :tag_list, :image
The reason I'm doing a Recipe.where(:user_recipe_id => params[:id]) instead of Recipe.where(:id => params[:id]) is because I'm trying to get so instead of john/recipes/46 showing the 46th recipe in the database, instead to show the 46th recipe that belongs to John.
Thanks for all help!
You're only trying to look for one recipe, but your query is searching for multiples. When you use a plain where(...) without ending it with .first, Rails interprets it as "show me all (multiple) Recipes with this user id" instead of "show me the (one) recipe with this id".
So you need to either put .first at the end of your query:
#recipe = Recipe.where(:user_recipe_id => params[:id]).first
or use an ActiveRecord finder that only returns one record:
#recipe = Recipe.find_by_user_recipe_id(params[:id])

Resources