Change pagination dynamically in ActiveAdmin or solutions for printing - ruby-on-rails

I'm new to Activeadmin and rails and I need some help.
I have a model that is paginated and I want to allow the user to change the pagination value or disable it completely, so it can print (to a printer) all the records (or filtered ones) for instance.
I know I can set the pagination using #per_page in :before_filter, but I can't figure out how I can change this value during execution.
To solve the problem of needing to show all the unpaginated records I defined a custom page, but in this page the filter or scope don't work so it's kind of useless.
How can I create a Print button in Active Admin?

This is a workaround to do it, I know it is not the best solution but it works ! :)
This is the app/admin/mymodel.rb file
ActiveAdmin.register MyModel do
before_filter :paginate
#other code
controller do
def paginate
#per_page = params[:pagination] unless params[:pagination].blank?
end
end
index do
panel "Pagination" do
render partial: "paginate", locals: {resource: "mymodels"}
end
#other code
end
#other code
end
And for the app/views/admin/articles/paginate.html.haml
#pagination_form
= form_tag do
= label_tag :pagination, "Number of " + resource + " per page : "
= text_field_tag :pagination
= submit_tag "Filter"
:javascript
$("#pagination_form form").submit(function(e){
e.preventDefault();
window.location = "/admin/#{resource}?pagination=" + $("#pagination").val();
})
Hoping that my answer can people with the same problem :)

I found a solution and I'm answering my own question for someone who has the same problem.
It may not be the best solution but it works, if someone has a better way please share:
ActiveAdmin.register mymodel do
before_filter :apply_pagination
# other code
index :download_links => false, :as => :table, :default => true do
if params[:pag].blank?
div link_to(I18n.t("text_for_the_link"), 'mymodel?pag=1', :class => "class_for_link")
else
div link_to(I18n.t("print.print"), 'mymodel', :class => "class_for_link")
end
# other code
end
controller do
def apply_pagination
if params[:pag].blank?
#per_page = 50
else
#per_page = 99999999
end
# other code
end
end

I found out you can define this by registering the following line on the resource:
ActiveAdmin.register MyModel do
config.per_page = [20, 50, 100, 200]
end
It automatically adds a select box in the index pagination with the preset values given in the array.

Related

Using case statement in a helper

I haven't used case statements before and was wondering how to do the following.
I have a number of news pages, each having posts relevant to department, so the pages
/tynewyddnews
/woodsidenews
/outreachnews
/sandpipernews
On my home page I am grabbing the latest post from each of these and displaying them.
Post Model
def self.top_posts
#Array with each of the 4 departments - first record
top_posts = [
self.tynewydd_posts.first,
self.woodside_posts.first,
self.sandpiper_posts.first,
self.outreach_posts.first
]
#remove entry if nil
top_posts.delete_if {|x| x==nil}
return top_posts
end
tynewydd_posts for example is a scope
scope :tynewydd_posts, :include => :department, :conditions => {"departments.name" => "Ty Newydd"}, :order => "posts.published_on DESC"
So if i am reading a post on the home page from tynewydd and want to create a link to /tynewyddnews or i am reading a post from woodside and want to link_to /woodside I have been advised that a case statement may help, but I am unsure on what to use as parameters, so my attempt so far is
def public_news
case Post.top_posts
when :tynewydd_posts == 'Ty Newydd'
link_to('...Read more', tynewyddnews_path)
when :woodside_posts == 'Woodside'
link_to('...Read More', woodsidenews_path)
end
end
And then in my view i can call the helper
<%= public_news %>
obviously a miserable attempt, firstly in examples I have seen a variable is being set when the case is being set? if someone could give some advice on how to achieve this it would be much appreciated
Try this variant:
def public_news
path = case
when Post.tynewydd_posts then tynewyddnews_path
when Post.woodside_posts then woodsidenews_path
...
else default_path end
end
link_to('...Read More', path)
end
when expression will fire up when expression is evaluated to true

Dynamic url_path in each loop

I have a city page with a jQuery content carousel. The content of the carousel is filed by a each loop.
CityController
#events = #city.events.find_all_by_hot(true)
#activities = #city.activities.find_all_by_hot(true)
#sights = #city.sights.find_all_by_hot(true)
#hot = #events + #activities + #sights
Class city
has_many: events
end
class events
belongs_to :city
has_many :attachments, :as => :attachable
accepts_nested_attributes_for :attachments
end
Activities and sights models are the same
City view content slider:
#hot.each do |a|
a.attachments.each do |a|
= image_tag(a.file.url, :height =>"325px", :width =>"650px" ), url_path
I want to generate links (url_path) in my each loop...how can I realize this? It cannot place the url_path of the routes because they are dymanic based on which attachment (image) is loaded.
Although your syntax of image_tag is incorrect you can try this
#hot.each do |hot|
hot.attachments.each do |a|
link_to polymorphic_path(a.attachable) do
image_tag(a.file.url, :height => "325px", :width => "650px")
end
end
end
If I understand your problem correctly. Also check out the polymorphic_path helper, which is what you need.
Am I right that the link should point to the a which can be any of events, activities, sights? as
#hot = #events + #activities + #sights
I would try creating a special controller action in the CityController
def hottie
#duck = Kernel.const_get(params[:type]).find_by_id(params[:id])
redirect_to #duck
end
then add something like
match 'hottie/:type/:id' => 'city#hottie', as: 'hot'
which should give you a path helper that you can use as this:
<%=link_to("Open", hot_path(a.class.to_s, a.id)) %>
Addition: this is of course a bit dirty and needs some security things considered (e.g. limit it to show only special types). You could also consider moving the three classes Event, Activities and Sights into a Object Hierarchy using STI; that should eliminate the need of passing the type in the request.

How highlight found word with Sunspot?

I want to highlight found words in text, for example, as shown here.
As far as I know I must follow these steps:
1) In my model, I must add :stored => true option to the field which I want to highlight:
searchable do
text :title, :stored => true
text :description
end
2) In my controller, I have to declare which field I want highlighted:
def search
#search = Article.search do
keywords params[:search] do
highlight :title
end
end
end
3) In the view I'm not sure what to do, I tried this:
- #search.each_hit_with_result do |hit, result|
%p= link_to raw(hit_title(hit)), article_path(result)
It is what doing method hit_title:
def hit_title(hit)
if highlight = hit.highlight(:title)
highlight.format { |word| "<font color='green'>#{word}</font>" }
else
h(hit.result.title)
end
end
But it doesn't work as expected, it always highlights the first word of the title, even if the searched word is at the end of it.
Is there an easier way to do this?
I bumped into this looking for a solution to render highlights from sunspot search on rails view.
I didn't find much of a ready solution anywhere, so I used part of this post to make one of my one.
I am quite new to rails so this might not be fully the RoR way.
In my case, I did a full text search on two fields, call them notes and description.
In order to be able to render to html the highlights, I introduced a hash of values containing the id of the record, the name of the column and its highlighted value, adequately formatted. This allows me to highlight the search results on different fields.
entry.rb:
searchable do
text :description, :stored => true
text :notes, :stored => true
end
entries_controller.rb:
#search = Entry.search
if params[:search].nil? || params[:search].empty?
stext=''
else
stext=params[:search]
end
fulltext stext, :highlight => true
paginate(page: params[:page], :per_page => 10)
end
#entries=#search.results
#results=Hash.new
#search.hits.each do |hit|
hit.highlights(:description).each do |highlight|
id=hit.primary_key.to_s.to_sym
fr=highlight.format { |word| "<result>#{word}</result>" }
#results.merge!(id => ["description",fr])
end
hit.highlights(:notes).each do |highlight|
id=hit.primary_key.to_s.to_sym
fr=highlight.format { |word| "<result>#{word}</result>" }
#results.merge!(id => ["notes",fr])
end
end
and on the view, wherever I want to render any value of those, I do the following:
<% #entries.each do |f| %>
<% j=f[:id].to_s.to_sym %>
<% if !#results[j].nil? && #results[j][0]=="description" %>
<%= #results[j][1].html_safe %>
<% else %>
<%= f[:description] %>
<% end %>
[...] (likewise for notes)
<% end %>
Please, note I created a css definition for <result> markup to make the text notable.
Code looks good to me for highlighting the first matching word in the title, since I have similar code. Have you tried rebuilding your solr index and restarting the servers?
Also, can you try reverting your solrconfig.xml to its default values? Someone had a similar problem after modifying solrconfig.xml, Ref https://groups.google.com/forum/#!searchin/ruby-sunspot/highlight/ruby-sunspot/kHq0Dw35UWs/ANIUwERArTQJ
If you want to override the highlighting option in solrconfig.xml, search for max_snippets on this site http://outoftime.github.io/ . You may want to try options like
highlight :title, :max_snippets => 3, :fragment_size => 0 # 0 is infinite
Are you using substring search? I've got the same problem here and realized that enabling substring match by following sunspot wiki tutorial led to the problem.

Rails/ajax - whitespace and request.raw_post

I am starting to learn Ajax with rails.
I have a catalog index page with a text_field_tag querying db if it finds similar "section" results.
Index.html.erb
<h1>Catalogs</h1>
<label>Search by Section:</label>
<%=text_field_tag :section %>
<%= observe_field(:section,
:frequency=> 0.1,
:update=> "article_list",
:url=>{ :action => :get_article_list }) %>
<div id="article_list"></div>
Catalogs_controller.rb
def index
end
def get_article_list
#section = request.raw_post.split(/&/).first
#catalogList = "<ol>"
Catalog.find(:all, :conditions => ["section = ?", #section]).each do |catalog|
#catalogList += "<li>" + catalog.title + "</li>"
end
#catalogList += "</ol>"
render :text => #catalogList
end
Question:
request.raw_post renders something like:
xml&authenticity_token=tgtxV3knlPvrJqT9qazs4BIcKYeFy2hGDIrQxVUTvFM%3D
so I use
request.raw_post.split(/&/).first
to get the section query ("xml"). It works, however how can I do if the query have a whitespace. (like "Open Source") In fact, I have Open Source sections in my db, but request.raw_post.split(/&/).first renders Open%20Source. How can I manage this? Did I have to use a full text search engine to achieve it or there is another way?
Thanks a lot for your explanation!
Look over your logs, in them you will see the post and the params being passed. You should not need to do your own query-string splitting. You should be able to use params[:section] to get the post data.
As your comment implies, there's something missing. Your observe_field needs to tell the Rails helper what to do. Check out: http://apidock.com/rails/ActionView/Helpers/PrototypeHelper/observe_field. Anyhow, you'll want to do something like:
observe_field(... # lots of parameters
:with => 'section'
)
And that should give you params[:section].

Searching in Ruby on Rails - How do I search on each word entered and not the exact string?

I have built a blog application w/ ruby on rails and I am trying to implement a search feature. The blog application allows for users to tag posts. The tags are created in their own table and belong_to :post. When a tag is created, so is a record in the tag table where the name of the tag is tag_name and associated by post_id. Tags are strings.
I am trying to allow a user to search for any word tag_name in any order. Here is what I mean. Lets say a particular post has a tag that is 'ruby code controller'. In my current search feature, that tag will be found if the user searches for 'ruby', 'ruby code', or 'ruby code controller'. It will not be found if the user types in 'ruby controller'.
Essentially what I am saying is that I would like each word entered in the search to be searched for, not necessarily the 'string' that is entered into the search.
I have been experimenting with providing multiple textfields to allow the user to type in multiple words, and also have been playing around with the code below, but can't seem to accomplish the above. I am new to ruby and rails so sorry if this is an obvious question and prior to installing a gem or plugin I thought I would check to see if there was a simple fix. Here is my code:
View: /views/tags/index.html.erb
<% form_tag tags_path, :method => 'get' do %>
<p>
<%= text_field_tag :search, params[:search], :class => "textfield-search" %>
<%= submit_tag "Search", :name => nil, :class => "search-button" %>
</p>
<% end %>
TagsController
def index
#tags = Tag.search(params[:search]).paginate :page => params[:page], :per_page => 5
#tagsearch = Tag.search(params[:search])
#tag_counts = Tag.count(:group => :tag_name,
:order => 'count_all DESC', :limit => 100)
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => #tags }
end
end
Tag Model
class Tag < ActiveRecord::Base
belongs_to :post
validates_length_of :tag_name, :maximum=>42
validates_presence_of :tag_name
def self.search(search)
if search
find(:all, :order => "created_at DESC", :conditions => ['tag_name LIKE ?', "%#{search}%"])
else
find(:all, :order => "created_at DESC")
end
end
end
If I read your problem correctly, you want to return a row if the tag names for the row matches one of the words passed in the query string.
You can rewrite your search method as follows:
def self.search(search)
all :conditions => (search ? { :tag_name => search.split} : [])
end
If you need partial matching then do the following:
def self.search(str)
return [] if str.blank?
cond_text = str.split.map{|w| "tag_name LIKE ? "}.join(" OR ")
cond_values = str.split.map{|w| "%#{w}%"}
all(:conditions => (str ? [cond_text, *cond_values] : []))
end
Edit 1
If you want pass multiple search strings then:
def self.search(*args)
return [] if args.blank?
cond_text, cond_values = [], []
args.each do |str|
next if str.blank?
cond_text << "( %s )" % str.split.map{|w| "tag_name LIKE ? "}.join(" OR ")
cond_values.concat(str.split.map{|w| "%#{w}%"})
end
all :conditions => [cond_text.join(" AND "), *cond_values]
end
Now you can make calls such as:
Tag.search("Ruby On Rails")
Tag.search("Ruby On Rails", "Houston")
Tag.search("Ruby On Rails", "Houston", "TX")
Tag.search("Ruby On Rails", "Houston", "TX", "Blah")
Tag.search("Ruby On Rails", "Houston", "TX", "Blah", ....) # n parameters
Caveat:
The wild card LIKE searches are not very efficient(as they don't use the index). You should consider using Sphinx (via ThinkingSphinx) OR Solr(via SunSpot) if you have lot of data.
You can try to set up ferret, or if you are really bend on just using rails, try this:
# Break the search string into words
words = params[:search].blank? ? [] : params[:search].split(' ')
conditions = [[]] # Why this way? You'll know soon
words.each do |word|
conditions[0] << ["tag_name LIKE ?"]
conditions << "%#{word}%"
end
conditions[0] = conditions.first.join(" OR ") # Converts condition string to include " OR " easily ;-)
# Proceed to find using `:conditions => conditions` in your find
hope this helps =)
Sounds like you need a full text search. The best search integration right now is with Sphinx and the Thinking_Sphinx plugin. I have used it on several projects and it's super easy to setup.
You do need to install sphinx on your host so if you are using a shared host that could present some issues.
You could also use full text search in a MyISAM MySQL database, but performance on that is pretty poor.
Once you have your sphinx installed you just put what you want to index in your model and call model.search. The results will be a list of model objects. It supports will_paginate as well.
I'd suggest looking at Searchlogic if you don't want to use a separate fulltext search engine (Ferret, Sphinx, etc). It makes simple searches extremely easy, although you may not want to use it in a public facing area without lots of testing.
Also check out the Railscast on it: http://railscasts.com/episodes/176-searchlogic
1.You can do some coding in your controller post as such:-
<pre>
def show
#post = Post.find(params[:id])
#tag_counts = Tag.count(:group => :name, :order => 'updated_at DESC', :limit => 10)
respond_to do |format|
format.html # show.html.erb
format.json { render json: #post }
end
end
</pre>
2.Now make some changes in your view file:-
<pre>
<b>Tags:</b>
<%= join_tags(#post) %>
<%unless #tag_counts.nil?%>
<% #tag_counts.each do |tag_name, tag_count| %>
<tr><td><%= link_to(tag_name, posts_path(:name => tag_name)) %></td>
<td>(<%=tag_count%>)</td>
</tr><% end %>
<%end%>
</pre>
3. And one important thing is that there should be many to many relationship between tags and post.

Resources