pdfkit send_data - ruby-on-rails

I'm trying to send pdf to user. For example if user is in /products?category_id=3 he has to get report of products whose category id is 3 not all reports. I couldn't find a way to pass parameter. How can i do this ?
products_controller
def index
#products Product.where("category_id = ?", params[:category_id)
end
def reporter
kit = PDFKit.new(render_to_string(:action => "products/index", :layout => "report"))
send_data(kit.to_pdf, :type => :pdf)
end
My view is like this
<% #products.each do |product| %>
<%= product.name %>
<% end %>
<%= link_to "Download(PDF)", reporter_path, :method => :post %>

Related

Designing a Search bar and retrieving data from database rails4

Now i am tried by following to this article http://www.rymcmahon.com/articles/2
My product.rb file is
class Product < ActiveRecord::Base
def self.search(search)
where("name LIKE ?","%#{search}%")
end
end
my index file is
Data
<%= form_tag(products_path, :method => "get") do %>
<%= text_field_tag :search, params[:search], placeholder: "products" %>
<%= submit_tag "Search", :name => nil %>
<% end %>
my index method is
def index
#product = Product.all
if params[:search]
#recipes = Product.search(params[:search]).order("created_at DESC")
else
#recipes =Product.all.order("created_at DESC")
end
end
But it didn't filtering the data
my output is:
dinesh 200 2016-09-21 06:10:40 UTC
reddyc 300 2016-09-21 06:16:31 UTC
Goods 200 2016-09-21 09:33:56 UTC
That article doesn't seem to be entirely correct, because the first collection assignment seems redundant. I'd write it like this:
def index
#products = search_products.order(created_at: :desc)
end
private
def search_products
if params[:search]
Product.search(params[:search])
else
Product.all
end
end
Then in your views you use #products variable instead of #recipes. It should work
You have taken two different variables for product, also #product = Product.all is not required, as your taking the product variable again in both if and else cases.
def index
if params[:search].present?
#products = Product.search(params[:search]).order("created_at DESC") //I recommend taking plural(products)
else
#products = Product.all.order("created_at DESC")
end
end
Your index.html.erb can be,
<% #products.each do |product| %>
<tr>
<td><%= product.field1 %></td>
<td><%= product.field2 %></td>
<td><%= product.field3 %></td>
</tr>
<% end %>
My controller is:
def show
#product = Product.find(params[:id])
end
def search
end
def searchable
searchword = params[:search]
#data = Product.where(name: searchword)
end
and my searchable.html.erb is:
<h1>searching for '<%= params[:search] %>'</h1>
<% if #data.empty? %>
<h1>no results found</h1>
<% end %>
<% #data.each do |s| %>
<%= s.name %>
<%= s.created_at %><br>
<% end %>
And search.html.erb
<%= form_tag searchable_path, method: 'get' do %>
<%= text_field_tag :search, params[:search] %>
<%= submit_tag "Search", name: nil %>
<% end %>
And my routes are assigned as
get 'search' => 'products#search'
get 'searchable' => 'products#searchable'
By this I am able to search data in my database.And it is working fine.

Building search REST API

I'm using a gem called gem 'open_taobao'
The following is how i get my data in json
class SearchController < ApplicationController
layout 'layouts/frontend_base'
def index
#searchterm = "basketball"
#search = OpenTaobao.get(
:method => "taobao.tbk.item.get",
:fields => "num_iid,title,nick,pict_url,cid,price,type,delist_time,post_fee,score,volume",
:q => #searchterm,
:page_size => 1,
:sort => "_des",
)
end
end
What I am trying to do from my view is have a input field with submit and whatever is in the input box will replace my query variable below
:q => #searchterm
What would be the best way of accomplishing this?
You can have your form like this:
<%= form_tag search_path do %>
<%= input_field_tag :q, params[:q] %>
<%= submit_tag "Submit" %>
<% end %>
in your controller, you shouldn't need to set another instance variable #searchterm
You could do:
def index
#search = OpenTaobao.get(
:method => "taobao.tbk.item.get",
:fields => "num_iid,title,nick,pict_url,cid,price,type,delist_time,post_fee,score,volume",
:q => params[:q],
:page_size => 1,
:sort => "_des",
)
# what you do depends on the data type returned here. if it's a JSON string, you should parse it and reassign to #search, if not you may not need to do anything
end
In your view,
#search/index.html.erb
<% #search.each do |result_key, result_value| %>
# you can deal with the html here
<%= result_key %>
<%= result_value %>
<% end %>

Rails accessing custom method instance variable

What I am trying to do is add a simple search to a 'show' view in my rails app. I've watched the rails cast about simple search and it's given me some good direction but I can't seem to get it to work with my situation. I just have a list of FAQs and want to have a search filter for the 'question(s)'.
Here's my views/guests/show.html.erb
<%= form_tag faq_search_guests_path, method: :get, remote: true, :id => "faq_search_form" do %>
<p>
<%= text_field_tag :search, params[:search] %>
<%= submit_tag "Search", :name => nil %>
</p>
<% end %>
<div id="faq-search-test"></div>
<% #faqs.each do |f| %>
<h4>Question</h4>
<%= f.question %>
<h4>Answer</h4>
<%= f.answer %>
<% end %>
Here's the controller/guests_controller.rb method that originally sets #faqs
def show
#guest = Guest.find(params[:id])
#hotel = Hotel.find(params[:hotel_id])
#faqs = Faq.where(hotel_id: #hotel.id)
#template = Template.where( hotel: #hotel.id )
#visit = Visit.where("hotel_id = ? AND guest_id = ?", #hotel.id, #guest.id).last
#visit = Visit.find(params[:visit_id]) if params[:visit_id] && (#visit.hotel_id == #hotel.id)
unless current_user.hotels.include?(#hotel)
render :file => "public/401.html", :status => :unauthorized
end
end
Here's my controllers/guests_controller.rb custom method my form is calling
def faq_search
#faq_result = Faq.search(params[:search])
render :nothing => true
end
Here's my routes.rb for that
resources :guests do
get 'faq_search', :on => :collection
end
resources :faqs
Here's my models/faq.rb
def self.search(search)
if search
where('question LIKE ?', '%#{search}%')
else
scoped
end
end
So from here, I am having trouble displaying #faq_result in show.html.erb. I guess I have no idea how to access an instance variable from a custom controller method from a view.
Any help would be much appreiciated :)!

How can I implement fragment cache with dalli when using pagination (kaminari)?

I know dalli (caching) is pretty powerful plugin to enhance performance for static pages.
But what about dynamic pages with pagination, which are updated quite often?
What is the correct way to set up dalli?
One problem I've encountered for example: dalli recognizes different params[:page] as the same page when using pagination:(
How would you guys design the system when using dalli for both
the page that gets updated so often
the page that won't be updated so often
For example. I have 4 models such as User, Community, Topic, and Comment(defined Polymorphic to both Community, and Topic. They can be created or shown in #show pages)
It's like
Community > (has_many) > Topics > (has_many) > Comments
Community > (has_many) > Comments
All of them belongs to user(creator)
My current codes are just like this(This is quite bit long. Sorry about that)
I'm facing the pagination problem when using caching...
-------------------------------------Settings----------------------------------------
config/environments/development.rb
config.consider_all_requests_local = true
config.action_controller.perform_caching = true
config.cache_store = :dalli_store
routes.rb
resources :communities do
resources :topics do
resources :comments do
end
end
-------------------------------------Community----------------------------------------
controllers/communities_controller.rb#index&show
caches_page :show
caches_action :edit, :new
def index
....
if params[:sort] == 'new'
#communities = Community.scoped.page(params[:page]).order("created_at DESC")
elsif params[:sort] = 'popular'
#communities = Community.scoped.page(params[:page]).order("follow_count DESC")
elsif params[:sort] = 'reputation'
#communities = Community.scoped.page(params[:page]).order("reputation_count DESC")
else
#communities = Community.scoped.page(params[:page]).order("created_at DESC")
end
....
end
def show
#community = Community.find(params[:community_id])
#comments #community.comments.page(params[:page]
#topics = #community.topics.limit(10)
end
views/communities/index.html.erb
note: However, the content will be the same even if I move to next params[:page]:( It seems caching recognize different page as the same contents...
#here, the url will could be something like this example.com/communities?utf8=✓&location=14&genre=3&search=strawberry
But this is going to create gigantic petterns of the caches:(
So I want to make it work only when params[:sort] was not empty. Because, no other parameters come with when params[:sort] is not empty.
It could be like, example.com/communities?sort=new, example.com/communities?sort=popular, example.com/communities?sort=reputation
...
<% if params[:sort] %>
<% #key = "community_index_" + params[:sort] + params[:page] %>
<% cache(:controller => "communities", :action => "index", :action_suffix => #key) do %>
<%= page_entries_info(#communities, :entry_name => 'community').html_safe %>
<%= paginate #communities, :window => 4 %>
<% #communities.each do |community| %>
<%= render 'communities/community', :community => community %>
<% end %>
<% end %>
<% end %>
...
views/communities/show.html.erb
...
<% #key = params[:community_name] + "_community_show_information" %>
<% cache(:controller => "communities", :action => "show", :action_suffix => #key) do %>
<h2>Information</h2>
<div class="CommunityInformation">
<%= render 'communities/information'%>
</div>
<% end %>
<% #key = params[:community_name] + "_community_show_wall_" + params[:page] + %>
<% cache(:controller => "communities", :action => "show", :action_suffix => #key) do %>
<%= paginate #comments, :window => 4 %>
<h2>Topic</h2>
<div class="WallInformation">
<% #comments.eager.recent.each do |comment| %>
<%= render 'communities/comment', :comment => comment %>
<% end %>
</div>
<% end %>
<% #key = params[:community_name] + "_community_show_topics" %>
<% cache(:controller => "communities", :action => "show", :action_suffix => #key) do %>
<h2>Topic</h2>
<div class="TopicInformation">
<% #topics.eager.recent.each do |topic| %>
<%= render 'communities/topic', :topic => topic %>
<% end %>
</div>
<% end %>
...
models/community_sweeper.rb
class CommunitySweeper < ActionController::Caching::Sweeper
observe Community
def after_save(record)
expire_fragment(url_for(:action => 'index', :only_path => true) + '?????(all the caches related to the community#index)')
expire_fragment(url_for(:action => 'show', :only_path => true) + '?????(the cache related to the particular community#show)')
end
end
end
-------------------------------------Topic----------------------------------------
controllers/topics_controller.rb#index&show
caches_page :show
caches_action :edit, :new
def index
....
#community = Community.find(params[:community_id])
#topics = #community.topics.page(params[:page]
....
end
def show
#topic = Topic.find(params[:id])
#comments = #topic.comments.page(params[:page]
end
views/topics/index.html.erb
...
<% #key = params[:community_id] + "_topic_index_" + params[:page] %>
<% cache(:controller => "topics", :action => "index", :action_suffix => #key) do %>
<%= page_entries_info(#communities, :entry_name => 'community').html_safe %>
<%= paginate #communities, :window => 4 %>
<% #communities.each do |community| %>
<%= render 'communities/community', :community => community %>
<% end %>
<% end %>
<% end %>
...
views/topics/show.html.erb
...
<% #key = params[:community_name] + "_topic_show_" + params[:id] + "_comments" + params[:page] %>
<% cache(:controller => "topics", :action => "show", :action_suffix => #key) do %>
<%= paginate #comments, :window => 4 %>
<%= page_entries_info(#comments, :entry_name => 'comment').html_safe %>
<h2>Comment</h2>
<div class="CommentInformation">
<% #comments.each do |comment| %>
<%= render 'topics/comment', :comment => comment %>
<% end %>
</div>
<% end %>
...
models/topic_sweeper.rb
class TopicSweeper < ActionController::Caching::Sweeper
observe Topic
def after_save(record)
expire_fragment(url_for(:action => 'index', :only_path => true) + '?????(all the caches related to the topic#index)')
expire_fragment(url_for(:action => 'show', :only_path => true) + '?????(the cache related to the particular topic#show)')
end
end
-------------------------------------Comment----------------------------------------
models/comment_sweeper.rb
class CommentSweeper < ActionController::Caching::Sweeper
observe Comment
def after_save(record)
expire_fragment(url_for(:action => 'index', :only_path => true) + '?????(all the caches related to the topic#index)')
expire_fragment(url_for(:action => 'show', :only_path => true) + '?????(the cache related to the particular topic#show)')
end
end
I am following on on from my answer to
How should I set up dalli for a dynamic page with lots of content updates?
Please note that I am not an expert but I did try your approach and abandoned it as it just kept getting more and more complex as my application grew and I went for the cache key fragment based approach mentioned in the last question. There are a few things to bear in mind.
The cache sweeper approach requires you to make sure that the sweeper is up to date as you make changes to your application which means extra maintenance and testing work.
In a dynamic application you probably wont be able to easily cache whole pages especially if the views show information from many models.
You wont be able to deal with the paging issue unless the page parameter becomes part of your cache keys.
When your cache gets full, memcached will simply remove the least used / oldest cache items when putting in a new cache fragment.
So there is no issue with you just pushing in a new cache fragments when your models change and letting memcached clear out the old out of date cache items.
Therefore fragment caching in your views will probably be the easiest solution as it will deal with paging and you wont have to deal with manual cache invalidation
So looking at one of your views, what I might do is
<% if params[:sort] %>
<%= page_entries_info(#communities, :entry_name => 'community').html_safe %>
<%= paginate #communities, :window => 4 %>
<% #communities.each do |community| %>
<% cache(community, :suffix => "community_index") do
<%= render 'communities/community', :community => community %>
<% end %>
<% end %>
<% end %>
What I have done is cache the rendering of each community record and paging becomes irrelavent

Returning search results inside of a Rails 3 app

We followed Ryan Bates' Railscast #37, and the search form appears without error on our app, but is not functional. It doesnt return any search results.
UsersController:
class UsersController < ApplicationController
def index
#title = "All users"
#users = User.search(params[:search])
end
The search function is defined in our user.rb file
def self.search(search)
if search
where('name LIKE ?', "%#{search}%")
else
all
end
end
and finally our index.html.erb file where that search box is displayed
<h1>All users</h1>
<%= form_tag users_path, :method => 'get' do %>
<p>
<%= text_field_tag :search, params[:search] %>
<%= submit_tag "Search", :name => nil %>
</p>
<% end %>
Are you looping though somewhere to display the results? You do have matching records in the database, right?
# create some users in the console
User.create([{:name => "Bo Jangles"}, {:name => "Some dude"}])
# somewhere in index.html.erb
<% #users.each do |user| %>
<p><%= user.name %></p>
<% end %>

Resources