Rails ActiveAdmin index formatting numbers - ruby-on-rails

I'd like to have my numbers right aligned and with a thousands separator. Can someone point me in the right direction?
ActiveAdmin.register Thing do
index do
column :id
column :amount # need to make this fomatted nicely
default_actions
end
end

You can pass a block to the column.
column :amount do |thing|
div :class => "amount" do
number_to_currency thing.amount
end
end
css
.amount {
text-align :right;
}
This railscast goes through some pretty good info too http://railscasts.com/episodes/284-active-admin?view=asciicast

Alternately:
column :amount, :class => 'text-right' do |thing|
number_to_currency thing.amount
end
then in your CSS
.text-right { text-align: right;}

you can use Active Admin Addons gem to improve the UI
https://github.com/platanus/activeadmin_addons/blob/master/docs/number-formatting.md

Related

Display the total for a single columns values in Activeadmin

I am trying to display a box at the bottom of my ActiveAdmin index page where it will total all of the values of the collection and display this total value. I am trying to sum the value of the column :number_books and I am currently using this code as suggested when someone answered a similar question a few years ago.
This does not appear to be having any impact on my index page as nothing is visibly changing on the index page for :orders.
Any help is greatly appreciated!
ActiveAdmin.register Order do
index do
column :email
column :customer_name
column :number_books
column :street_address
column :state
column :zip_code
column :total
default_actions
div class: "panel" do
h3 "Total amount: #{collection.pluck(:number_books).reduce(:+)}"
end
end
end
I found out I had to define this new index page I was creating as the default, otherwise activeadmin uses the default index page and ignores my custom one. I also had to change default_actions to simply actions and this now works great!
the working code is:
ActiveAdmin.register Order do
index default: true do
column :email
column :customer_name
column :number_books
column :street_address
column :state
column :zip_code
column :total
actions
div class: "panel" do
h3 "Total amount: #{collection.pluck(:number_books).reduce(:+)}"
end
end
end

Iterating through columns on active_admin model

New to Ruby and Rails, so perhaps I'm not searching/asking this the right way. I'm using the ActiveAdmin gem and want to turn this:
column :purchase_price, :sortable => :purchase_price do |piece|
div :class => "price" do
number_to_currency piece.purchase_price
end
end
column :appraised_value, :sortable => :appraised_value do |piece|
div :class => "price" do
number_to_currency piece.appraised_value
end
end
column :sale_price, :sortable => :sale_price do |piece|
div :class => "price" do
number_to_currency piece.sale_price
end
end
into this:
price_array = [:purchase_price, :appraised_value, :sale_price]
price_array.each do |p|
column p, :sortable => p do |piece|
div :class => "price" do
number_to_currency piece.p
end
end
end
...in the interest of DRY.
The longer solution works, but the shorter one gives a "NoMethodError in Admin::Pieces#index" and I'm kind of at a loss as to what's wrong. Any suggestions?
As house9 said, my problem was that I tried calling piece.p when really it should be piece.send(p). Still not exactly sure why you can't just replace all instances of p with the iterator loop like I did originally but maybe someone else can explain.
In any case, thank you!

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 & Sunspot facets and filtering

Pretty much a noobie here, so I appreciate any help someone can give.
I'm trying to add faceting to the search on my site through Sunspot. Ryan just released a great Railscast which got me started: http://railscasts.com/episodes/278-search-with-sunspot. I got that working and was able to add additional facets. My problem is that the facets are independent of each other. If I have 3 facets on 3 different attributes, when I select a facet once I already have on selected, I would like to display only results falling into both of those facests. As of now, it just switches from one facet to the other. I feel like this shouldn't be that difficult, but I can't figure out how to do it.
I did find this tutorial: http://blog.upubly.com/2011/01/06/using-sunspot-in-your-views/ which I think is doing what I want. I tried to get this working but, even when I attempt to make it work with just one facet I don't any results listed. Just the facet name and then nothing else.
Thoughts?
Thank you!!
UPDATE
Here is the code samples of what I am trying to do:
Adjusting the Railscasts code I got this:
In my StylesController:
def index
#search = Style.search do
fulltext params[:search]
facet :departmental, :seasonal, :classifier
with(:departmental, params[:department]) if params[:department].present?
with(:classifier, params[:classification]) if params[:classification].present?
with(:seasonal, params[:season]) if params[:season].present?
end
In my Style Index view (I know I need to condense this)
= form_tag styles_path, :method => :get do
%p
= text_field_tag :search, params[:search]
= submit_tag "Search", :name => nil
#facets
%h4 Departments
%ul
- for row in #search.facet(:departmental).rows
%li
- if params[:department].blank?
= link_to row.value, :department => row.value
(#{row.count})
- else
%strong= row.value
(#{link_to "remove", :department => nil})
%h4 Classifications
%ul
- for row in #search.facet(:classifier).rows
%li
- if params[:classification].blank?
= link_to row.value, :classification => row.value
(#{row.count})
- else
%strong= row.value
(#{link_to "remove", :classification => nil})
%h4 Seasons
%ul
- for row in #search.facet(:seasonal).rows
%li
- if params[:season].blank?
= link_to row.value, :season => row.value
(#{row.count})
- else
%strong= row.value
(#{link_to "remove", :season => nil})
In my Style Model:
searchable do
text :number, :description, :department, :classification, :season
string :departmental
string :classifier
string :seasonal
end
def departmental
self.department
end
def classifier
self.classification
end
def seasonal
self.season
end
And my version of the upubly code, paired down to just try to get the "seasonal" facet working:
I left the the Search Partial, the Search Model and the SearchHelper the same as in the example. I tried to mess with the Helper as my Facets will be pulling text values, not just IDs of other Models, but to no avail. I don't have my various attributes set up as individual Models as I didn't think I needed that functionality, but I am starting to think otherwise.
StylesController:
def index
#title = "All styles"
#search = search = Search.new(params[:search]) # need to set local variable to pass into search method
#search.url = styles_path
#search.facets = [:seasonal]
#solr_search = Style.search do
keywords search.query
with(:seasonal, true)
search.facets.each do |item|
facet(item)
with(:seasonal, params[:season]) if params[:season].present?
end
any_of do
# filter by facets
search.facets.each do |item|
with(item).all_of( params[item].try(:split, "-") ) if params[item].present?
end
end
paginate(:page => params[:page], :per_page => 10)
end
Again, I appreciate the help. Definitely a noob, but really enjoying the process of building this site. Stackoverflow has been a HUGE help for me already, so I owe everybody who posts answers on here a big-time thank you.
I needed the answer to this myself, and seeing as there seems to be nothing else on the web about it, I decided I'd try to figure it out myself.
First I came to the conclusion through logic, that the controller can handle multiple facets and there's no reasons it cannot, I remembered that the best part about ruby is that it is the most human readable code, try to read your first controller and you'll see that it makes sense that it works. I tested this by manually entering in a query string in url, which returned expected results. Therefore, once I figured that out, I knew the issue resided in my view (which made me facepalm because it's fairly obvious now)
Your example is significantly more complex than mine, and my answer might not 100% meet every requirement but I'm pretty sure it's close. Also your code in your model regarding "departmental" etc is a little redundant in my view
Controller
def index
#search = Style.search do
fulltext params[:search]
facet :departmental, :seasonal, :classifier
with(:departmental, params[:department]) if params[:department].present?
with(:classifier, params[:classification]) if params[:classification].present?
with(:seasonal, params[:season]) if params[:season].present?
end
View
%h4 Departments
%ul
- for row in #search.facet(:departmental).rows
%li
- if params[:department].blank?
= link_to row.value, styles_path(
:department => row.value,
:classification => (params[:classification] unless params[:season].blank?),
:season => (params[:season] unless params[:season].blank?))
(#{row.count})
- else
%strong= row.value
= link_to "remove", styles_path(
:department => nil,
:classification => (params[:classification] unless params[:season].blank?),
:season => (params[:season] unless params[:season].blank?))

Internationalization for constants-hashes in rails 3

Could you tell me whats the best practice for storing constants with internationalization in rails3?
f.e. i want to have a constant-hash for haircolours for my user model:
# btw: how can I store such hashes in the locales.yml-files?
# en.yml
HAIR_COLOURS = { "brown" => 0, "white" => 1, "red" => 2, "dark-brown" => 3...}
# de.yml
HAIR_COLOURS = { "braun" => 0, "weiss" => 1, "rot" => 2, "dunkel-braun" => 3...}
# i18n.default_locale = :de
User.find(1).haircolour
=> 0
User.find(1).haircolour_str
=> "brown"
# i18n.default_locale = :de
User.find(1).haircolour
=> 0
User.find(1).haircolour_str
=> "braun"
I would suggest the following. Create a string column for the hair colour. This would normally be an enumeration column (ENUM), but this isn't supported by Rails unless you're okay with some SQL in your migrations.
In your model, restrict the colours to a few valid values.
class User < ActiveRecord::Base
# Store the colours in the database as string identifiers (my preference
# would be English, lower case, with underscores). Only accept known values.
validates_inclusion_of :hair_colour, :in => %w{brown white red dark_brown}
end
Then, in config/locales/en.yml:
en:
user:
hair_colours:
brown: brown
white: white
red: red
dark_brown: dark brown
And in config/locales/de.yml:
de:
user:
hair_colours:
brown: braun
white: weiss
red: rot
dark_brown: dunkelbraun
In any view, you can do:
<%= t "user.hair_colours.#{#user.hair_colour}" %>
Or you can write a helper method in app/helpers/users_helper.rb:
def translated_hair_colour(user)
t "user.hair_colours.#{user.hair_colour}"
end
Because I believe that translation is in principle a concern of the presentation, I would not create a method on the User model, but in principle there is nothing stopping you from doing:
class User
# ...
def hair_colour_name
I18n.t "user.hair_colours.#{hair_colour}"
end
end
Update:
Making select boxes in a view that are translated can be done in two ways. The first option is to use the translated values as a source. This requires the translations to be complete and accurate. If not all values are translated, the missing values will not be displayed in the select box.
<%= form_for #user do |user| %>
<%= user.select :hair_colour, t("user.hair_colours").invert %>
<%= user.submit %>
<% end %>
The second option is to use the validation values from your model. This is the "right" way, but it requires a slight adjustment to the setup of the validation.
class User < ActiveRecord::Base
HAIR_COLOURS = %w{brown white red dark_brown}
validates_inclusion_of :hair_colour, :in => HAIR_COLOURS
end
Now, in your views:
<%= form_for #user do |user| %>
<%= user.select :hair_colour,
User::HAIR_COLOURS.map { |c| [t("user.hair_colours.#{c}"), c] } %>
<%= user.submit %>
<% end %>
Of course, the mapping can be easily extracted into a helper.

Resources