How to change css rails admin? - ruby-on-rails

I'm using Rails admin. I have a model named Order. The Order model has a Description field. When I look at the list of orders in the rails admin, the description fields of the orders are not completely showing. Only a portion of text and ellipsis is shown up.
Example: Some information about ordering ....
How to show the Description displayed completely without cutting?
config.model Orders do
list do
filters [:status, :created_at]
field :created_at do
label "Request date"
strftime_format "%b %d, %l:%M%P %Y"
end
field :description
field :status
field :scheduled_date do
strftime_format "%a %b, %d"
end
field :address do
filterable false
end
end
end

You should be able to increase the length for the description field this way:
field :description, :text do
html_attributes do
{:maxlength => 600}
end
end

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

Time zone dropdown where select value is index

I'm trying to create a select dropdown for time_zones in my user profile but I need the list and indexes to match up because I'm not using text, I'm using an integer for to store the zones in my database. I did that so I could display it as a dropdown in rails admin instead of a text input.
User:
validates_inclusion_of :time_zone, in: ActiveSupport::TimeZone.us_zones.map { |z| z.name },
message: "is not a valid time zone",
allow_blank: true
# This allows me to display the time_zone as a dropdown in rails admin instead of a text box
TIMEZONES = ActiveSupport::TimeZone.us_zones.map { |z| z.name }
def time_zone_enum
TIMEZONES.each_with_index.to_a
end
View:
<%= f.collection_select :time_zone, ActiveSupport::TimeZone.us_zones.map { |z| z.name }, value, name %>
# I don't know how to get the value to be an index of the map operation and to display the name
Try map.each_with_index as described here: How to map with index in Ruby?
<%= f.collection_select :time_zone, ActiveSupport::TimeZone.us_zones.map.each_with_index { |z, i| i.to_s.concat(" #{z.name}") }, name %>
You may need to modify that code to work in your rails application, but calling each_with_index on your map should give you a second parameter which will contain the index of your hash.

Rails 4: Accept year as string and store as date

In my Rails 4 app, I'd like to accept a year as a string in a text field but store it as a date in the database, in case I ever decide to accept full dates. However, when I try to do this, I keep getting a nil date value. I've verified that the controller is properly passing along the parameters to the model, but at some point before the validation happens, the date has been set to nil.
Is what I'm trying to do possible? And if so, what critical step have I missed? Thanks!
This is the relevant part of the form:
<p>
<%= f.label :publication_date %><br>
<%= f.text_field :publication_date, :size => 4 %>
</p>
And the schema:
create_table "books", force: true do |t|
t.string "title"
t.datetime "created_at"
t.datetime "updated_at"
t.date "publication_date"
...
end
And the model validation:
validates :publication_date, length: { is: 4 }, numericality: true
before_validation :check_pub_date
def check_pub_date
# this prints nil
logger.debug "Publication date: #{self.publication_date}"
end
before_save :convert_pub_year
def convert_pub_year
# Never gets here because validation never passes
logger.debug "Publication year: #{self.publication_date}"
if self.publication_date
self.publication_date = DateTime.strptime(self.publication_date, "%Y")
end
end
Given that your model is expecting a full date to come through, you are hitting a problem when you are passing only a string from your form - I would create a simple text_field to capture the year and go from there...
In your view
<%= text_field_tag :pub_year %>
In your controller
publication_year = params[:pub_year]
#book.publication_date = DateTime.strptime(publication_year, "%Y")
or, of course, factor the parsing of year into a full date into the model.
Edit - expanding on this, it's also possible to create a property in your model that doesn't get saved to the database if you prefer, so in your model, you would have this:
attr_accessor :pub_year
Then, in your convert_pub_year, substitute in pub_year instead of publication_date
def convert_pub_year
if self.pub_year
self.publication_date = DateTime.strptime(self.pub_year, "%Y")
end
end
You controller would need to allow the pub_year parameter in addition to any others you want - so in the private methods - something like the following:
def book_params
params.require(:book).permit(:title, :pub_year)
end
And finally in your view, remove publication_date' and includepub_year`:
<%= f.label :pub_year %><br>
<%= f.text_field :pub_year %>
Hope that helps
The problem exists because validation occurs AFTER assignment of the string passed from the controller, i.e. what you are validating is not the string but the attribute after the type cast to a date. If this fails (because - as in your case - the date is incomplete and consists only of a year), the attribute is nil.
For situations like yours you might want to look into the attribute_before_type_cast functions/variables which will give you access to the original date string BEFORE it was type cast into nil.

How to handle like one two separate date and time fields?

How to make two separated fields so can be handled to one datetime field in database?
I'm using jquery datetime picker that puts values like value in code example below.
Parameters includes only field with time but ignores field with date.
If I comment field with time then date is sent and saved but parameter looks like "2013-23-02" and it isn't forwarded like multi parameter.
#model
field :start_at, type: DateTime
#view
= f.text_field :start_at, :value => "2013-02-23"
= f.text_field :start_at, :value => "20:20:20"
you can use virtual attributes and callback (this is not tested but you should get the idea)
# model
attr_writer :start_at_time, :start_at_date
before_validation :build_start_at
def start_at_date
#start_at_date ||= start_at.to_date
end
def start_at_time
#start_at_time ||= start_at.strftime("%H:%M")
end
def build_start_at
self.start_at = Time.parse "#{start_at_date} #{start_at_time}"
end
# view
= f.text_field :start_at_date
= f.text_field :start_at_time

Rails date_select helper and validation

I have a date field in a model backed form in my Rails App:
<%= f.date_select :birthday,
{:start_year => Time.now.year,
:end_year => 1900,
:use_short_month => true,
:order => [:month, :day, :year],
:prompt => {:month => 'Month', :day => 'Day', :year => 'Year'}},
{:class => 'year',
:id => 'user_birthday'}
%>
It is being validated in the model code using:
validates_presence_of :birthday, :message => 'is a required field'
Unfortunately, if the user enters a partial value such as just the year, the form still submits without an error. Instead a funky date value gets written to the db. How do I make all three fields be mandatory?
I'd like to write a custom validation for this, but I don't know how to properly access the indvidual pieces of the birthday element. How can I do this?
Thanks!
Moe
I think you would have to create the validation in the controller itself.
The date parts are being passed to birthday(1i), birthday(2i) and birthday(3i). The problem here is that they are assigned immediately when passing the attributes and thus before any validations occur.
You could also overwrite the attributes= method to create your own validation there, but I would not suggest you to do that.
Keep in mind that if you do validations, it might be good to validate against any incorrect date as well. (for instance 31st of February, which when passed will yield 2nd of March and not an error).
I think the main issue here is that ActiveRecord is actually replacing the empty values with 1 before creating the Date, which also means that if the visitor pass only the year, the date will be created on the 1st of January that year. I guess that is an expected behaviour to allow use of only one of year/month/day select and still create a useful date.
Related to this post, this is the best solution I've found. However I should add :day, :month, :year as attr_accessible, thing I don't understand why.. (because of validation? please let me know..)
User.rb
MONTHS = ["January", 1], ["February", 2], ...
DAYS = ["01", 1], ["02", 2], ["03", 3], ...
START_YEAR = Time.now.year - 100
END_YEAR = Time.now.year
YEAR_RANGE = START_YEAR..END_YEAR
attr_accessible :day, :month, :year
attr_accessor :day, :month, :year
before_save :prepare_birthday
validate :validate_birthday
private
def prepare_birthday
begin
unless year.blank? # in order to avoid Year like 0000
self.birthday = Date.new(self.year.to_i, self.month.to_i, self.day.to_i)
end
rescue ArgumentError
false
end
end
def validate_birthday
errors.add(:birthday, "Birthday is invalid") unless prepare_birthday
end
user registration form
<%= f.select :month, options_for_select(User::MONTHS), :include_blank => "Month" %>
<%= f.select :day, options_for_select(User::DAYS), :include_blank => "Day" %>
<%= f.select :year, options_for_select(User::YEAR_RANGE), :include_blank =>"Year" %>
You could override the validate_on_create method, like the following:
class MyModel < ActiveRecord::Base
def validate_on_create
Date.parse(birthday)
rescue
errors.add_to_base("Wrong date format")
end
end
After following Benoitr's suggestions I came up with something similar using virtual attributes. On the View side there are 3 separate select's (year,mon,day) inside of a 'fields_for'. The data is submitted to the controller's mass assignment (no modifications in controller, see asciicasts #16) and then passed to a getter/setter (i.e. virtual attribute) in the model. I'm using Rails 3.0.3, and simpleForm for the view code.
In the View:
<%= f.label "Design Date", :class=>"float_left" %>
<%= f.input :design_month, :label => false, :collection => 1..12 %>
<%= f.input :design_day, :label => false, :collection => 1..31 %>
<%= f.input :design_year, :label => false, :collection => 1900..2020 %>
In the Model:
validate :design_date_validator
def design_year
design_date.year
end
def design_month
design_date.month
end
def design_day
design_date.day
end
def design_year=(year)
if year.to_s.blank?
#design_date_errors = true
else
self.design_date = Date.new(year.to_i,design_date.month,design_date.day)
end
end
def design_month=(month)
if month.to_s.blank?
#design_date_errors = true
else
self.design_date = Date.new(design_date.year,month.to_i,design_date.day)
end
end
def design_day=(day)
if day.to_s.blank?
#design_date_errors = true
else
self.design_date = Date.new(design_date.year,design_date.month,day.to_i)
end
end
#validator
def design_date_validator
if #design_date_errors
errors.add(:base, "Design Date Is invalid")
end
end
'design_date_attr' is the virtual attribute which sets the value of design_date in the database. The getter passes back an hash similar to what gets submitted in the form. The setter checks for blanks and creates a new date object and sets it and also sets the error variable. The custom validator :design_date_validator checks for the error instance variable and sets the errors variable. I used ':base' because the variable name was not human readable and using base removes that value from the error string.
A few things to refactor might be the error checking instance variable, but it seems to work at least. If anyone knows a better way to update the Date objects I'd love to hear it.

Resources