How to download search results of index page using axlsx? - ruby

First, I am really sorry if this question is too trivial. I am new with rails and couldn't figure out where i am doing it wrong.
I have a model named Costing and in it's index page i have a search form. I am trying to use 'axlsx' gem to download only the search results but I always get all the rows. I am also using 'will_paginate' gem.
Here is my code.
//costings_controller.rb
def index
#costings = Costing.search(params[:search] , params[:page])
respond_to do |format|
format.html # index.html.erb
format.json { render json: #costings }
format.xlsx {
send_data #costings.to_xlsx.to_stream.read, :filename => 'costings.xlsx', :type => "application/vnd.openxmlformates-officedocument.spreadsheetml.sheet"
}
end
end
// index.html.erb
<%= link_to 'Download Costings', url_for(:format=>"xlsx") %>
Please help me here.
Thanks a lot in advance.

Here is the code that I made for a demo of axlsx gem. Browse through it and implement your requirement in the controller. Here is the output of this demo.

//costings_controller.rb
def download
#costings = Costing.search(params[:search] , params[:page])
respond_to do |format|
format.html # index.html.erb
format.json { render json: #costings }
format.xlsx {
send_data #costings.to_xlsx.to_stream.read, :filename => 'costings.xlsx', :type => "application/vnd.openxmlformates-officedocument.spreadsheetml.sheet"
}
end
end
// index.html.erb
<%= form_for :costing, url: download_costing_index_path do %>
...
<% end %>
//routes
resources :costing do
collection do
post :download, :defaults => { :format => 'xlsx' }
end
end

Related

Rails 4: comment partial not rendering

Trying to display comments for photo, photo belongs to profile. html does not render.
The pertinent code:
routes.rb
resources :profiles do
resources :photos do
resources :comments do
resources :comments
end
end
end
comments/_comment.html.haml
= comments.each do |comment|
%li
= comment.body
\-
%small Submitted
= #{time_ago_in_words(comment.created_at)}
= semantic_form_for [#profile, #photo, comment, Comment.new] do |f|
= f.inputs do
= f.input :body, placeholder: "Add a Reply"
%br/
= f.actions do
= f.action :submit, :as => :input, label: "Reply"
%ul
- render partial: 'comments/comment', locals: {comments: comment.comments}
models/photo.rb
class Photo < ActiveRecord::Base
belongs_to :profile
has_many :comments, as: :commentable, :dependent => :destroy
end
models/comment.rb
class Comment < ActiveRecord::Base
belongs_to :profile
belongs_to :commentable, polymorphic: true
has_many :comments, as: :commentable, :dependent => :destroy
end
models/profile.rb
class Profile < ActiveRecord::Base
belongs_to :user
has_many :photos, :dependent => :destroy
has_many :comments, :dependent => :destroy
end
app/controllers/phtos_controller.rb
class PhotosController < ApplicationController
before_action :set_photo, only: [:show, :edit, :update, :destroy]
before_action :set_profile
load_and_authorize_resource
def index
#photos = Photo.where(:profile => #profile)
end
def show
end
def new
#photo = Photo.new(:profile => #profile)
end
def edit
end
def create
#photo = Photo.new(photo_params.merge(:profile_id => #profile.id))
respond_to do |format|
if #photo.save
format.html { redirect_to [#profile, #photo], notice: 'Photo was successfully created.' }
format.json { render :show, status: :created, location: #photo }
else
format.html { render :new }
format.json { render json: #photo.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #photo.update(photo_params)
format.html { redirect_to [#profile, #photo], notice: 'Photo was successfully updated.' }
format.json { render :show, status: :ok, location: #photo }
else
format.html { render :edit }
format.json { render json: #photo.errors, status: :unprocessable_entity }
end
end
end
def destroy
#photo.destroy
respond_to do |format|
format.html { redirect_to profile_photos_url, notice: 'Photo was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_photo
#photo = Photo.find(params[:id])
end
def set_profile
#profile = Profile.find(params[:profile_id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def photo_params
params.require(:photo).permit(:description, :attachment)
end
end
/app/views/photos/show.html.haml
= render partial: "layouts/sub_header", locals: {heading: #photo.profile.name + "'s", sub_heading: "photo", current_bread_crumb: #photo.profile.name + "'s photo", include_crumbs: true}
/ Intro Content
.row
.col-md-6
= image_tag #photo.attachment.url(:large), :class => "img-responsive"
.col-md-6
%p
%h2 About this photo...
= simple_format(#photo.description)
,
/ /.row
%h3 Comments
= semantic_form_for [#profile, #photo, Comment.new] do |f|
= f.inputs do
= f.input :body, :as => :text
= f.actions do
= f.action :submit, :as => :input
%ul
- render partial: 'comments/comment', locals: {comments: #photo.comments}
- if current_user == #profile.user
= link_to 'Edit', edit_profile_photo_path(#profile, #photo)
|
= link_to 'Back', :back
Data is being inserted into the database (except the profile_id, but I will save that for another post). I manually updated the profile_id in the db to make see if it was just a data integrity issue, still nothing.
I have tried moving the resources around in the routes.rb, I have tried refactoring the views to load the collection directly without the partial, nothing seems to work.
Additionally, if I comment out the partial and use this code I do see comment bodies on the page, so it is definitely something I am doing wrong in the call to the partial or inside the partial itself.
%ul
- #photo.comments.each do |comment|
= comment.body
I cannot seem to crack this one and I know it isn't magic, but I clearly not seeing something.
Thanks for any help!
Change show.html.haml to:
%ul
- render 'comments/comment', locals: {comments: #photo.comments}
Reason being, is that you can't render a view within a view, so the above will assume you are looking for a partial named _comment.html.haml within the comments folder.
Thanks Marc and Jarvis for all your help, I still don't know why that wasn't working, but looking at the ActionView::PartialRender at api.rubyonrails.org I found that this does work...
- #photo.comments.each do |comment|
= render partial: 'comments/comment', locals: { comment: comment }
I basically have to do the iterating myself even though clearly in the guide Marc referenced it said I should be able to do what I had written.
Oh well, on to the next problem.
Thanks again!

Dynamic Dropdown SelectBox in Rails Issue

I'm working on a project in rails 4 where I am creating some dynamic drop downs. Below is all the code i have done for this dropdown. The drop downs are appearing, however not saving to the table and wont show up in the Show (and yes I have the proper ruby ie. <%= #reports.site_id %>.
I am not sure what to do from here and I am a bit of a rails noob, but have worked through tutorials and classes on the language.
My Form Select Box Looks Like this:
`<%= collection_select( :site, :site_id, Site.all, :id, :site_call_sign, {}, { :multiple => false %>`
The above select box dose get data from the site table but wont save that data to the reports table??`
My Controller looks like this:
class ReportsController < ApplicationController
before_action :set_report, only: [:show, :edit, :update, :destroy]
# GET /reports
# GET /reports.json
def index
#search = ReportDateSearch.new(params[:search])
#reports = #search.scope
#reports = Report.all
# Adds CSV Downloader to Residents
respond_to do |format|
format.html
format.csv { render text: #reports.to_csv }
end
end
# GET /reports/1
# GET /reports/1.json
def show
end
# GET /reports/new
def new
#report = Report.new
end
# GET /reports/1/edit
def edit
end
# POST /reports
# POST /reports.json
def create
#report = Report.new(report_params)
respond_to do |format|
if #report.save
format.html { redirect_to #report, notice: 'Report was successfully created.' }
format.json { render :show, status: :created, location: #report }
else
format.html { render :new }
format.json { render json: #report.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /reports/1
# PATCH/PUT /reports/1.json
def update
respond_to do |format|
if #report.update(report_params)
format.html { redirect_to #report, notice: 'Report was successfully updated.' }
format.json { render :show, status: :ok, location: #report }
else
format.html { render :edit }
format.json { render json: #report.errors, status: :unprocessable_entity }
end
end
end
# DELETE /reports/1
# DELETE /reports/1.json
def destroy
#report.destroy
respond_to do |format|
format.html { redirect_to reports_url, notice: 'Report was successfully destroyed.' }
format.json { head :no_content }
end
end
# Adds CSV Uploader Method to Application
def import
Report.import(params[:file])
redirect_to reports_path, notice: "Report(s) Added Successfully"
end
private
# Use callbacks to share common setup or constraints between actions.
def set_report
#report = Report.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def report_params
params.require(:report).permit(:date, :site_id, :user_id, :type_of_report, :type_of_incident, :report)
end
end
my model looks like this:
class Report < ActiveRecord::Base
belongs_to :user
belongs_to :site
def self.import(file)
CSV.foreach(file.path, headers: true) do |row|
Report.create! row.to_hash
end
end
def self.to_csv
CSV.generate do |csv|
csv << column_names
all.each do |report|
csv << report.attributes.values_at(*column_names)
end
end
end
end
My Show Page Looks Like:
<p id="notice"><%= notice %></p>
<p>
<strong>Date:</strong>
<%= #report.date %>
</p>
<p>
<strong>Site:</strong>
<%= #report.site_id %>
</p>
<p>
<strong>Created By:</strong>
<%= #report.user_id %>
</p>
<p>
<strong>Type of report:</strong>
<%= #report.type_of_report %>
</p>
<p>
<strong>Type of incident:</strong>
<%= #report.type_of_incident %>
</p>
<p>
<strong>Report:</strong>
<%= #report.report %>
</p>
<%= link_to 'Edit', edit_report_path(#report) %> |
<%= link_to 'Back', reports_path %>
not too sure where I'm going wrong here.Any help would be greatly appreciated
Try changing the first parameter if your collection_select call from :site to :report:
<%= collection_select( :report, :site_id, Site.all, :id, :site_call_sign, {}, { :multiple => false } %>
My initial guess is that your form is passing up site_id as params[:site_id] instead of params[:report][:site_id], which is the format you'd need based on your strong parameters method in your controller:
def report_params
params.require(:report).permit(:date, :site_id, :user_id, :type_of_report, :type_of_incident, :report)
end
If it doesn't work, one thing you can do to help debug the issue is look at your rails console and see exactly the format that your form parameters are being sent from your view to the controller. Putting a couple puts statements in your action can help you better compare params versus report_params:
def create
puts "Params: #{params.inspect}"
puts "Report Params: #{report_params.inspect}"
#report = Report.new(report_params)
respond_to do |format|
if #report.save
format.html { redirect_to #report, notice: 'Report was successfully created.' }
format.json { render :show, status: :created, location: #report }
else
format.html { render :new }
format.json { render json: #report.errors, status: :unprocessable_entity }
end
end
end
Look in your server console for the output of those 2 puts statements. If you see site_id in params and not in report_params, you'll know your strong parameters method has filtered it out.

Rails 4 nested forms link_to edit not working in loop

I have a nested routes/models/forms in rails. On my index page I am listing the todo_lists with the todo_items underneath. I want to be able to click on my todo list title and then it takes me to the edit page. I research polymorphic routes and nested routes.
UPDATE
This was my fix to stop it from creating the dummy todo list.
<% #current_todo_lists.each do |list| %>
<% if list.id %>
<div class="panel">
<p><strong><%= link_to list.title ,edit_todo_list_path(list)%></strong></p>
<% list.todo_items.each do |todo_item| %>
<p><%= todo_item.description %></p>
<% end %>
</div>
<% end %>
<% end %>
github link
Link_to rails nested form edit
polymorphic_path not generating correct path
I have done a lot quite a bit of research looking to cocoon, rails guides on polymorphic routes and several other stackoverflow links.
I have not been successful in making any of these work.
Here is the index page where all my todo_lists with todo_items are listed. It goes through a loop to list each todo list with the corresponding items created with it
Update:
I already tried <%= link_to list.title, edit_todo_list_path(list) %>and <%= link_to list.title, edit_todo_list_path(#list) %>.
The error message I get is :
ActionController::UrlGenerationError at /todo_lists
No route matches {:action=>"edit", :controller=>"todo_lists", :id=>nil} missing required keys: [:id]
This same configuration with #todo_list gives the same error.
Basically it can't find the Todo List with an id.
In the console does give me a result. So I am missing something.
>> t = TodoList.find(1)
=> #<TodoList id: 1, title: "First todo List with a modal", created_at: "2014-09-09 23:02:27", updated_at: "2014-09-09 23:02:27", user_id: 1>
>>
Update 2: This is where the error is happening in my todo list controller. It can't find without id.
def set_todo_list
#todo_list = TodoList.find(params[:id])
end
<% #todo_lists.each do |list| %>
<p><strong><%= link_to list.title, edit_polymorphic_path(#todo_list) %></strong></p>
<% list.todo_items.each do |todo_item| %>
<p><%= todo_item.description %></p>
<% end %>
<% end %>
So far <p><strong><%= link_to list.title, edit_polymorphic_path(#todo_list) % parameters have been #todo_list(s), # todo_lists(s), todo_items and so on.
Models:
class TodoList < ActiveRecord::Base
has_many :todo_items, dependent: :destroy
accepts_nested_attributes_for :todo_items, allow_destroy: true
validates_presence_of :title
end
class TodoItem < ActiveRecord::Base
belongs_to :todo_list
end
Controllers:
Class TodoListsController < ApplicationController
before_filter :authenticate_user!
before_filter except: [:index]
before_action :set_todo_list, only: [:show, :edit, :update, :destroy]
# GET /todo_lists
# GET /todo_lists.json
def index
##todo_lists = TodoList.all
#find current user todo lists/items
#todo_lists = current_user.todo_lists
#todo_items = current_user.todo_items
#create a new user todo list
#todo_list = current_user.todo_lists.new
# builder for todo list _form
3.times{ #todo_list.todo_items.build }
end
# GET /todo_lists/1
# GET /todo_lists/1.json
def show
end
# # GET /todo_lists/new
def new
#todo_list = current_user.todo_lists.new
3.times{ #todo_list.todo_items.build }
end
# GET /todo_lists/1/edit
def edit
##todo_list = TodoList.find(todo_list_params)
#todo_list = TodoList.find(params[:id])
end
# POST /todo_lists
# POST /todo_lists.json
def create
##todo_list = TodoList.new(todo_list_params)
#todo_list = current_user.todo_lists.new(todo_list_params)
respond_to do |format|
if #todo_list.save
format.html { redirect_to #todo_list, notice: 'Todo list was successfully created.' }
format.json { render :show, status: :created, location: #todo_list }
else
format.html { render :new }
format.json { render json: #todo_list.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /todo_lists/1
# PATCH/PUT /todo_lists/1.json
def update
#todo_list = TodoList.find(params[:id])
respond_to do |format|
if #todo_list.update(todo_list_params)
format.html { redirect_to #todo_list, notice: 'Todo list was successfully updated.' }
format.json { render :show, status: :ok, location: #todo_list }
else
format.html { render :edit }
format.json { render json: #todo_list.errors, status: :unprocessable_entity }
end
end
end
# DELETE /todo_lists/1
# DELETE /todo_lists/1.json
def destroy
##todo_list.TodoList.find(params[:id])
#todo_list.destroy
respond_to do |format|
format.html { redirect_to todo_lists_url, notice: 'Todo list was successfully destroyed.' }
format.json { head :no_content }
end
end
private
def owns_todolist
if current_user != TodoList.find(params[:id]).user
redirect_to todo_lists_path, error: "You can't do that!"
end
end
# Use callbacks to share common setup or constraints between actions.
def set_todo_list
#todo_list = TodoList.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def todo_list_params
params.require(:todo_list).permit(:title, todo_items_attributes: [:description, :_destroy])
end
end
class TodoItemsController < ApplicationController
before_action :set_todo_item, only: [:show, :edit, :update, :destroy]
before_action :set_todo_list
# GET /todo_items
# GET /todo_items.json
def index
#todo_items = TodoItem.all
end
# GET /todo_items/1
# GET /todo_items/1.json
def show
#todo_item = TodoItem.find(params[:id])
end
# GET /todo_items/new
def new
#todo_item = #todo_list.todo_items.build
end
# GET /todo_items/1/edit
def edit
#todo_item = TodoItem.find(params[:id])
end
# POST /todo_items
# POST /todo_items.json
def create
#todo_item = #todo_list.todo_items.build(todo_item_params)
respond_to do |format|
if #todo_item.save
format.html { redirect_to [#todo_list,#todo_item], notice: 'Todo item was successfully created.' }
format.json { render :show, status: :created, location: #todo_item }
else
format.html { render :new }
format.json { render json: #todo_item.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /todo_items/1
# PATCH/PUT /todo_items/1.json
def update
#todo_item = TodoItem.find(params[:id])
respond_to do |format|
if #todo_item.update(todo_item_params)
format.html { redirect_to #todo_item, notice: 'Todo item was successfully updated.' }
format.json { render :show, status: :ok, location: #todo_item }
else
format.html { render :edit }
format.json { render json: #todo_item.errors, status: :unprocessable_entity }
end
end
end
# DELETE /todo_items/1
# DELETE /todo_items/1.json
def destroy
#todo_item = TodoItem.find(params[:id])
#todo_item.destroy
respond_to do |format|
format.html { redirect_to todo_list_todo_items_url, notice: 'Todo item was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_todo_item
#todo_item = TodoItem.find(params[:id])
end
def set_todo_list
#todo_list = TodoList.find(params[:todo_list_id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def todo_item_params
params.require(:todo_item).permit(:description, :text, :todo_list_id)
end
end
and finally the form. Right now it allows for adding a todo_list and a few todo_items just as practice. I plan on using some Ajax to allow for dynamic creation later on. And having a different form for editing.
<%= form_for(#todo_list) do |f| %>
<% if #todo_list.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#todo_list.errors.count, "error") %> prohibited this todo_list from being saved:</h2>
<ul>
<% #todo_list.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :title %><br>
<%= f.text_field :title %>
</div>
<div>
<%= f.fields_for :todo_items do |builder| %>
<%= builder.label :description, "Items" %>
<%= builder.text_field :description %>
<%= builder.check_box '_destroy' %>
<% end %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
I think the issue's actually a little trickier, because edit_todo_list_path(list) seems to throw the same error.
What's going on is that the #todo_lists variable (first an array of persisted lists) is altered when you run #todo_list = current_user.todo_lists.new. That command actually adds a new (unpersisted) list to the end of the #todo_lists array (seems like buggy behavior to me, but it's happened to me before), so that when your view is looping through them, the last one has no id, and a path cannot be created for it.
The solution is (I think) to make that variable after you've used the #todo_lists variable.
Take #todo_list out of the controller, and where you use it in the view, instead do current_user.todo_lists.build. That should instantiate a new list without changing the #todo_lists variable.
You are trying to create a link to a resource that has not been persisted yet:
#create a new user todo list
#todo_list = current_user.todo_lists.new
Since you never call #todo_list.save the record does not have a ID and cannot be routed to.
I think what you are trying to do is:
<% #todo_lists.each do |list| %>
<p><strong><%= link_to list.title, edit_polymorphic_path(id: list.to_param) #not #todo_list! %></strong></p>
<% list.todo_items.each do |todo_item| %>
<p><%= todo_item.description %></p>
<% end %>
<% end %>
And I would seriously consider renaming #todo_list -> #new_todo_list since it´s pretty confusing as is.
Update
"I can even click a button to open a modal which will create a new todo list all from the same page."
What you should do then is have the user create a new a resource by posting the form with an AJAX POST request to /todo_list and then update the page with the new list (and an edit link).
What you are doing now is creating a new todo_list which only exists in the servers memory before rails finishes processing the request.

Element.update rjs error while using link_to_remote in rails

I am using rails 2.3.2
I have a link_to_remote functions
<%= link_to_remote "Comments ", {
:url => {:controller => "blogs",:action => "fetchcomments",:id => blog.id}} %> |
and the rails action as
def fetchcomments
unless params[:id].nil?
#blog = Blog.find(params[:id])
respond_to do |format|
format.js do
render :update do |page|
page.replace_html("comm", 'hi')
end
end
end
end
The above code throws me the error as
try {
Element.update("comm", "hi");
} catch (e) { alert('RJS error:\n\n' + e.toString());
alert('Element.update(\"comm\", \"hi\");'); throw e }
Please give me suggestions
Remove unless params[:id].nil? and it will work if you have an element with the id 'comm' on the page that makes the request. Of course it will replace whatever is inside with the word 'hi'.

Rails 3: update method redirection problem

Trying to build a CMS for a blog using rails 3.
In my routes.rb...
namespace :admin do
resources :posts
root :to => "home#index"
end
In Admin::PostsController...
def update
#post = Post.find(params[:id])
respond_to do |format|
if #post.update_attributes(params[:post])
format.html { redirect_to(#post,
:notice => 'Post was successfully updated.')}
format.xml { head :ok }
else
format.html { render :action => "edit" }
format.xml { render :xml => #post.errors,
:status => :unprocessable_entity }
end
end
end
I had to change the first line of admin/_form.html.erb due to a previous 'undefined method' error that was driving me crazy. Was trying to point the browser to a nonexistent "post_path".
<%= form_for(#post, :url => admin_posts_path(#post)) do |f| %>
All other methods for posts are working as expected. Upon form submission (update) - the rails server...
Started POST "/admin/posts.1"
ActionController::RoutingError (No route matches "/admin/posts.1"):
First, curious as to why it is using POST instead of PUT for the update.
Second, I can't figure out why the URL is being interpreted as "/admin/posts.1" and how to fix it.
Has anyone else run into this problem? (and yes, I am following the rubyonrails.org guides closely to help me). Any help would be greatly appreciated.
EDIT:
Changed admin_posts_path(#post) to admin_post_path(#post) per theIV.
the rails server...
NoMethodError (undefined method 'post_url' for #<Admin::PostsController:0x00000102b26ff8>):
app/controllers/admin/posts_controller.rb:55:in 'block (2 levels) in update'
app/controllers/admin/posts_controller.rb:53:in 'update'
I believe you should be hitting admin_post_path(#post), not admin_posts_path(#post).
Look at the table that lists all of the helpers created for your routes on guides.rubyonrails.org.
EDIT: Also, have you tried the array style of urls? It's pretty convenient.
<%= form_for([:admin, #post]) do |f| %>
EDIT 2: My guess as to "undefined method post_url" is from your update action here:
format.html { redirect_to(#post,
:notice => 'Post was successfully updated.')}
It needs to be namespaced as well:
format.html { redirect_to([:admin, #post],
:notice => 'Post was successfully updated.')}

Resources