Not able to export data to an excel sheet - sql

I am using to_xls and spreadsheet gem to export data to excel sheet in rails4
However, I am not able to export the data to excel sheet even if the excel sheet fires open.
I am following this tutorial
http://code.dblock.org/2011/09/01/exporting-data-to-excel-in-ruby-on-rails-w-spreadsheet-and-toxls.html
orders_controller.rb
def index
#orders = Order.all.includes(:status,:document,:platform, payment:
[:status]).where(status_id: Orders::Status.where(name:
['INPROGRESS', 'COMPLETED']).pluck(:id)).paginate(:page =>
params[:page], :per_page => 30).order('id Desc')
#order_statuses = Orders::Status.all
#delivery_statuses = Orders::DeliveryStatus.all
respond_to do |format|
format.html
format.xls do
send_data(
Order.where(status_id:
Orders::Status.where(name:
['COMPLETED',
'INPROGRESS' ]).pluck(:id))
.includes(:status, :platform,
:payment).map{
|order|
{
id: order.id, txnid: order.txnid,
created_at: order.created_at,
product: order.product,
payment:
order.payment.status.name,
status: order.status.name,
total_amount: order.total_amount,
discount: order.discount,
platform: order.platform.name
}}.to_xls,
content_type: 'application/vnd.ms-excel',
filename: 'orders.xls' )
end
end
end
orders/index.html.erb
<table id='myOrdersTable'class="table table-bordered">
<thead>
<tr>
<th>Trans ID</th>
<th>Date(dd/mm/yy)</th>
<th>Product</th>
<th>Payment</th>
<th>Status</th>
<th>Total amount</th>
<th>Discount</th>
<th>Platform</th>
<th>Draft</th>
<th>Edit Draft</th>
<th>Upload Soft Copy</th>
<th colspan="3"></th>
</tr>
</thead>
<tbody>
<% #orders.each do |order| %>
<tr>
<td><%= order.txnid %></td>
<td><%= order.created_at.strftime('%d-%b-%Y') %></td>
<td><%= order.product %></td>
<td><%= order.payment.status.name if order.payment %></td>
<td><%= order.status.name %></td>
<td><%= order.total_amount %></td>
<td><%= order.discount %></td>
<td><%= order.platform.name %></td>
<td
:
:
:
<% end %>
</tbody>
</table>
<%= will_paginate #orders %>
:
:
<%#= link_to 'New Order', new_order_path %>
<%= link_to 'Exporting', "/admin/orders.xls", :class =>'btn btn-primary'
%>
Here in the link if call
<%= link_to 'Exporting', orders_path(request.parameters.merge({:format
=> :xls})), :class =>'btn btn-primary' %>
it gives a template missing error(Dont know why) .Hence I am not using the above link in the code to get the export button.
This helps me generate an excel sheet, but not able to export all the columns from the index.html.erb page and their values into the sheet. Just gives a blank spreadsheet. How can I export all these data in to sheet? Please help !I am a beginner so kindly elaborate and let me know if more data is needed.

My choice is to just manually generate CSV file like this :
#orders = Order.all
header = ["id", "status" // put your header field ]
csv = CSV.generate do |csv|
csv << header
#orders.each do |order|
row = [ordrer.id, order.total_amount //mention your fields here ]
end
csv << row
end

Related

Multiple where clauses in Rails 4 returning no records

I am implementing search and want to give the user the option to select multiple check boxes to search for those options. When multiple checkboxes are selected an AND operator will be used so all records which contain every option selected will be returned.
The code below works when one checkbox is selected, but it always returns 0 records when multiple checkboxes are selected. Can you please help.
Here is the code:
User.rb
has_many :marketing_assets
has_many :marketing_platforms, through: :marketing_assets
def self.has_platform(platform_object)
where('marketing_platforms.name = ?', platform_object)
end
def self.search_for_platforms(platforms)
#platforms = MarketingPlatform.all
platforms_query_string = User
platforms.each do |platform|
#platforms.each do |platform_from_table|
if platform == platform_from_table.name
platforms_query_string = platforms_query_string.has_platform(platform_from_table.name)
end
end
end
return platforms_query_string
end
experts_controller.erb
class ExpertsController < ApplicationController
layout 'experts'
def index
#marketing_platforms = MarketingPlatform.all
if params[:marketing_platforms_p].present?
#users = User.joins(:marketing_platforms).search_for_platforms(params[:marketing_platforms_p])
##users = User.search_for_platforms(params[:marketing_platforms_p])
else
#users = User.text_search(params[:query]).page(params[:page]).per_page(10)
end
end
def show
#user = User.find(params[:id])
end
end
experts.index.html.erb
<h1>Search</h1>
<%= params %>
<%= form_tag experts_path, method: :get do %>
<p>
<%= text_field_tag :query, params[:query] %>
<hr>
<h3>Marketing Assets</h3>
<% MarketingPlatform.all.each do |platform| %>
<%= check_box_tag "marketing_platforms_p[]", "#{platform.name}",
((params[:marketing_platforms] != nil) && (params[:marketing_platforms].index(platform.name) != nil) ? true : false) %>
<%= platform.name %>
<% end %>
<hr>
<%= submit_tag 'Search', class: 'btn btn-primary', name: nil %>
<%= link_to 'Find All', experts_path %>
</p>
<% end %>
<h3>Results</h3>
<table class="table">
<thead>
<tr>
<th>First name</th>
<th>Last name</th>
<th>Company</th>
<th>Job title</th>
<th>Country</th>
<th>Email</th>
<th></th>
</tr>
</thead>
<tbody>
<%= #users.count %>
<% #users.each do |user| %>
<tr>
<td><%= user.first_name %></td>
<td><%= user.last_name %></td>
<td><%= user.company %></td>
<td><%= user.job_title %></td>
<td><%= user.country %></td>
<td><%= user.email %></td>
<td><%= link_to 'Show', expert_path(user) %></td>
</tr>
<% end %>
</tbody>
</table>
The SQL that is being executed is
SELECT COUNT(*) FROM "users" INNER JOIN "marketing_assets" ON "marketing_assets"."user_id" = "users"."id" INNER JOIN "marketing_platforms" ON "marketing_platforms"."id" = "marketing_assets"."marketing_platform_id" WHERE (marketing_platforms.name = 'Google+') AND (marketing_platforms.name = 'Facebook')
I found the answer to this questions by reading the following question Select Multiple Values From Single Column
I wrote the following SQL:
SELECT "users".*
FROM "users"
WHERE "users"."id"
IN (SELECT "users"."id" FROM "users"
INNER JOIN marketing_assets ON users.id = marketing_assets.user_id
WHERE marketing_assets.marketing_platform_id= 3
GROUP BY users.id HAVING COUNT(DISTINCT marketing_assets.marketing_platform_id) = 1)
I built the query object replacing all values with variables and then executed it using the find_by_sql Rails method:
#user = User.find_by_sql(**query**)

Get sum of record attributes when grouping in Rails?

I am grouping mileage entries by month in my Rails 3.2 application:
mileages_controller.rb
def index
#mileages = Mileage.find_all_by_user_id(current_user.id)
#mileages_months = Mileage.find_all_by_user_id(current_user.id).group_by { |t| t.created_at.beginning_of_month }
respond_to do |format|
format.html # index.html.erb
format.json { render json: #mileages }
end
end
index.html.erb
<% #mileages_months.sort.each do |month, mileages| %>
<h4><%= month.strftime('%B %Y') %></h4>
<p>Total miles <strong><%= mileages.miles.sum %></strong>.</p>
<table>
<tr>
<th>Name</th>
<th>Miles</th>
<th>Start</th>
<th>Destination</th>
<th></th>
</tr>
<% for mileage in mileages %>
<tr>
<td><%= mileage.name %></td>
<td><%= mileage.miles %></td>
<td><%= mileage.start %></td>
<td><%= mileage.end %></td>
<td><%= link_to 'Show', mileage %></td>
</tr>
<% end %>
</table>
<% end %>
As you can see, I am trying to sum the total miles in each month using <%= mileages.miles.sum %>. This won't work - but <%= mileages.first.miles %> correctly shows the first entry's miles for each month.
What is the correct way of totalling up the miles column for each month?
Well you can create a helper method(to keep this logic seperate from the view) in the mileage_helper as :
def sum_mileges(mileages)
mileages.map(&:miles).sum
end
and then calling it in the view as
<p>Total miles <strong><%= sum_mileges(mileages) %></strong>.</p>
OR
you can do it directly as :
<p>Total miles <strong><%= mileages.map(&:miles).sum %></strong>.</p>

Combine API data with local data in Rails

I am working with the GoCardless API in my Rails 3 application. I have a subscription model which has a resource_id column which matches the id of the remote record.
I am trying to get extra information for a local subscription record from the API.
Subscription Index View
<% #subscriptions.each do |subscription| %>
<tr>
<td><%= subscription.resource_id %></td>
<td><%= subscription.resource_type %></td>
<td><%= subscription.signature %></td>
<td><%= subscription.state %></td>
<td><%= #gocardless.next_interval_start %></td>
<td><%= link_to 'Show', subscription %></td>
<td><%= link_to 'Edit', edit_subscription_path(subscription) %></td>
<td><%= link_to 'Destroy', subscription, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
Subscription Controller
def index
#subscriptions = Subscription.all
#gocardless = GoCardless::Merchant.find("XXXXXXXXXX").subscriptions
respond_to do |format|
format.html # index.html.erb
format.json { render json: #subscriptions }
end
end
As you can see I'm using the following line to retrieve the next interval start date
<%= #gocardless.next_interval_start %>
This doesn't work and returns nil. However, if I change it to the following all records show the value from the first record from the API.
<%= #gocardless.first.next_interval_start %>
According to the GoCardless API documentation you can lookup a subscription using the following:
GoCardless::Subscription.find("XXXXXXXXXX") # => #<GoCardless::Subscription ...>
So, my question. How do I pass the current subscription resource_id to the API so that I can view the next_internal_start value for each of the local subscription records?
Update
Using Adam's example below I get a 404 response from GoCardless. I think it's due to me not setting the merchant ID in the request. When I change the method to:
def gc_subscription
#gc_subscription ||= GoCardless::Merchant.find("MERCHANTID").subscriptions.find(self.resource_id)
end
I get undefined methodinterval' for #` for any attribute I try and request using the following code:
<% for subscription in #subscriptions %>
<%= subscription.gc_subscription.amount
<% end %>
When using the same code to get local content it works as expected:
<% for subscription in #subscriptions %>
<%= subscription.resource_id %>
<% end %>
I've checked that the value I am trying to retrieve is available in the API. https://sandbox.gocardless.com/docs/api_guide#resources-available
Update Two
As before calling the first result works using Adam's method:
<%= subscription.gc_subscription.first.amount %>
This returns 2.5 which is the value of the first subscription.
If I had a local Subscription model which linked to a remote data source I would have a method like this on my Subscription model which provided access to the remote object:
def gc_subscription
#gc_subscription ||= GoCardless::Subscription.find(self.resource_id)
end
Then you can access this method as necessary without any need for any GC logic in the view or controller. For example:
for subscription in #subscriptions
subscription.gc_subscription.some_method #=> "output"
end
Or, if you are only working with one subscription:
subscription = Subscription.find(id)
subscription #=> Your local Subscription instance
subscription.gc_subscription #=> GoCardless::Subscription instance
With it configured like that, you will be able to remove the #gocardless from your controller and replace your view with this:
<% #subscriptions.each do |subscription| %>
<tr>
<td><%= subscription.resource_id %></td>
<td><%= subscription.resource_type %></td>
<td><%= subscription.signature %></td>
<td><%= subscription.state %></td>
<td><%= subscription.gc_subscription.next_interval_start %></td>
<td><%= link_to 'Show', subscription %></td>
<td><%= link_to 'Edit', edit_subscription_path(subscription) %></td>
<td><%= link_to 'Destroy', subscription, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
I hope that helps.

Tidiest way of highlighting record if older than X days?

What is the tidiest DRY way in a Rails 3 application of highlighting a table row depending on its age?
<% #faults_open.each do |fault| %>
<tr>
<td><%= fault.name %></td>
<td><%= fault.faulttype %></td>
<td><%= fault.priority %></td>
<td><%= time_ago_in_words(fault.created_at) %> ago</td>
<td><%= link_to 'Show', fault %></td>
</tr>
<% end %>
I would like a class applied to the table row with an indication of its age which I can then style using CSS.
<% #faults_open.each do |fault| %>
<tr <% if fault.created_at > Date.1.week.ago %>class="weekold"<% end %>>
<td><%= fault.name %></td>
<td><%= fault.faulttype %></td>
<td><%= fault.priority %></td>
<td><%= time_ago_in_words(fault.created_at) %> ago</td>
<td><%= link_to 'Show', fault %></td>
</tr>
<% end %>
Something like the above but obviously adding them to the view would be messy. I plan on adding a couple of ages, such as:
weekold
twoweeksold
monthold
sixmonthold
yearold
ancient
I imagine a helper is the tidiest way, but I'm unsure on how the helper would work. Any pointers would be appreciated.
I recently did something similar, adding a class name to the row that corresponded to it's approximate age in weeks, then I used CSS to do the actual highlighting.
Why not use a helper.. (just an example)
def highlight_age_class (created_at)
##today ||= Date.today
num_weeks = ((##today - created_at.to_date) / 7).floor
class_name = "aged_#{num_weeks}_weeks"
num_weeks == 1 ? class_name.singularize : class_name
end
With your HTML..
<tr class="<%= highlight_age_class fault.created_at %>">
Combined with some CSS..
.aged_1_week
.aged_1_weeks
.aged_4_weeks
.aged_24_weeks
.aged_56_weeks
etc
You can then focus on extending and optimizing your helper method for age highlighting.

output belongs_and_has_many value in show action

I have the following code but can't render color as expected. When I render item.color I get #<Color:0x007ffce487a648>for example. If I render item.color.map(&:name) I get undefined method map for #<Color:0x007ffce6616918>
<% #this_week_orders.each do |order| %>
<tr style="font-weight:bold;">
<td><%= link_to "Order #{order.id}", order_path(order) %></td>
<td><%= l order.date, :format => :long %></td>
<td><%= pluralize(order.items.count, "item") %></td>
<td><%= number_to_currency(order.total_price) %></td>
<tr>
<% for item in order.items %>
<tr>
<td><li><%= item.product.name %></li></td>
<td><%= item.color %></td>
</tr>
<% end %>
<% end %>
Order has_many :items
Item belongs_to :order
Item belongs_to :product
Item belongs_to :color
scope :this_week, lambda { where("date > ?", 7.days.ago) }
Order controller
def this_week
#this_week_orders = Order.this_week.all
respond_to do |format|
format.html # index.html.erb
end
end
#<Color:0x007ffce487a648> reperesents an object of class Color (not a collection of color objects, whereupon it would make sense to use map). If Color has a name attribute, just write <%= item.color.name %>.
map is for use on an Array. item.color only returns one object. Use:
<%= item.color.name %>
if Color is a class like it appears to be you need to set the color value:
Something like:
<%= item.color.name %>
or whatever your value for the color is.