RailsAdmin - hidden form fields and labels - ruby-on-rails

Using RailsAdmin. I have a Post model and a User model. Each post belongs to a user.
I use the following code to get RailsAdmin to handle the association for me and automatically set the user_id when a Post is created:
config.model Post do
edit do
field :user_id do
# use a form_field instead of the default drop-down
partial :form_field
# hide the input
view_helper :hidden_field
# set the value to current_user.id
def value
bindings[:view]._current_user.id
end
end
end
end
This code works, it sets the user_id to that of the current_user and it also hides the form_field (the html input) from view so that user is not even aware that it is being set on their behalf.
There is one small problem though. Whilst I'm able to hide the form_field, I can't hide it's associated label (i.e. the label that reads "User" which appears next to the input) - which means my users see this:
As you can see, there is a label "User" with an empty space next to it, and the word "Required" underneath.
Is there anyway to hide an input's associated label too (and not just the input itself) so that it's not confusing to the user? Is there something wrong with my code?
Thanks in advance

I think I've found a working solution:
field :user_id do
view_helper :hidden_field
# I added these next two lines to solve this
label ""
help ""
partial :form_field
def value
bindings[:view]._current_user.id
end
end
Not ideal, but it works

I also ran into the same obstacle and after some trial and error (and tips from the rails_admin group) arrived at a slight alternative:
config.model Library do
edit do
field :user_id do
# This hides the field label
label :hidden => true
# This hides the help field *yuk*
help ""
def value
bindings[:view]._current_user.id
end
# This hides the field input
view_helper do
:hidden_field
end
end
end
field :name
end

I think this feature is added to rails_admin already and no need a workaround solution for this. You can do it as the following
config.model Post do
edit do
field :user_id do
# This hides everything related with this field
hide
# You still need to set this value of course
def value
bindings[:view]._current_user.id
end
end
end
end

Related

RailsAdmin enum display existing value of the record

I have defined a User model in which there is a classical role
class User
enum role:[:user, :poweruser, :admin, :superadmin]
I am now using RailsAdmin to manage the fields of the user in rails_admin.rb file.
At the beginning, I manage the role attribute directly like that :
edit do
field :email do
required true
end
field :password
field :password_confirmation
field :role
...
Everything was fine. The current value is displayed (here poweruser), I get a combo automatically from RailsAdmin, with the 4 listed value. Perfect !
Now, I want to manage dynamically the list of roles : I need to restrict the list of roles regarding the current_user logged.
Therefore I use the :enum feature of RailsAdmin like that :
field :role, :enum do
required true
enum do
if bindings[:view]._current_user.superadmin?
{user:0, poweruser:1,admin:2,superadmin:3}
elsif bindings[:view]._current_user.admin?
{user:0, poweruser:1,admin:2}
else
{user:0}
end
end
end
This is working, the list is correctly restricted according to the current user role logged.
However, I would like that the initial value of the role should be set correctly, this value is not displayed at all : instead of the initial value poweruser, the 'Search' word (Chercher in french) is displayed.
How could I solve this issue ?
Thanks for any help.
You need to define the block default_value
rails_admin do
edit do
field :role do
default_value do
:poweruser
end
end
end
end
Thanks Guillermo, but it does not answer to my problem.
The problem is that railsadmin is not able to select the enum field on edit. It does not concern the default value for new record.
Now, I have found that it is an open issue of railsadmin gem, and find this link :
Not selecting enum field on edit #2669 and got a workaround from Richard Venneman
I have to change code in file app/views/rails_admin/main/_form_enumeration.html.haml and override the existing code by :
= form.select field.method_name, field.enum, { include_blank: true }.reverse_merge({ selected: form.object.class.send(field.method_name.to_s.pluralize)[field.form_value] }), field.html_attributes.reverse_merge({ data: { enumeration: true }, placeholder: t('admin.misc.search') })
It is working fine now ! So this problem is closed for me, until an official version of railsadmin !

how to make a field editable only if another is not blank in rails_admin

I want to be able to edit a field in Rails_Admin only if another is not blank
To be more specific, i want to be able to edit the "description" for an image only if there is an image already uploaded for this specific instance of the object
rails_admin do
edit do
field :uploaded_image
field :image_description
end
end
So in my admin, i don't want to display the field :image_description unless the uploaded_image field is not blank.
Any clues ?
Thanks!
Keep in mind that this will only work once the record has been saved, but the following configuration will let image_description be visible only if uploaded_image is present.
rails_admin do
edit do
field :uploaded_image
field :image_description do
visible do
bindings[:object].uploaded_image.present?
end
end
end
end

Rails 3 and ActiveAdmin. Filter is displaying Objects not the company name

I have a list of customers but on the filter section on the right column, I get a list like this #<Customer0X0B500> in the select menu. How can I display the company_name attribute of Customer instead?
Figured it out, thanks!
filter :customer, :collection => proc {(Customer.all).map{|c| [c.company_name, c.id]}}
i'm not sure I understand you but probably you should define to_s method inside your Customer class e.g.
class Customer
def to_s
self.company_name
end
end
it would be easier if you shared some code
class Customer
def display_name
self.company_name
end
end
Defining display_name instead of to_s works better...
to_s may be called automatically by other objects.
display_name only affects ActiveAdmin
You can also define:
show :title => :display_name
This will make your company_name appear as the title on the view pages instead of Company #x.
To make ActiveAdmin display select menu properly try in Model.rb:-
alias_attribute :name, :category_name

How to set some field in model as readonly when a condition is met?

I have models like this:
class Person
has_many :phones
...
end
class Phone
belongs_to :person
end
I want to forbid changing phones associated to person when some condition is met. Forbidden field is set to disabled in html form. When I added a custom validation to check it, it caused save error even when phone doesn't change. I think it is because a hash with attributes is passed to
#person.update_attributes(params[:person])
and there is some data with phone number (because form include fields for phone). How to update only attributes that changed? Or how to create validation that ignore saves when a field isn't changing? Or maybe I'm doing something wrong?
You might be able to use the
changed # => []
changed? # => true|false
changes # => {}
methods that are provided.
The changed method will return an array of changed attributes which you might be able to do an include?(...) against to build the functionality you are looking for.
Maybe something like
validate :check_for_changes
def check_for_changes
errors.add_to_base("Field is not changed") unless changed.include?("field")
end
def validate
errors.add :phone_number, "can't be updated" if phone_number_changed?
end
-- don't know if this works with associations though
Other way would be to override update_attributes, find values that haven't changed and remove them from params hash and finally call original update_attributes.
Why don't you use before_create, before_save callbacks in model to restrict create/update/save/delete or virtually any such operation. I think hooking up observers to decide whether you want to restrict the create or allow; would be a good approach. Following is a short example.
class Person < ActiveRecord::Base
#These callbacks are run every time a save/create is done.
before_save :ensure_my_condition_is_met
before_create :some_other_condition_check
protected
def some_other_condition_check
#checks here
end
def ensure_my_condition_is_met
# checks here
end
end
More information for callbacks can be obtained here:
http://guides.rubyonrails.org/activerecord_validations_callbacks.html#callbacks-overview
Hope it helps.

In Rails, How do I validates_uniqueness_of :field with a scope of last 6 months

First Item
I Want to validate a field to make sure it is unique (in the last 6 months) before saving it to the database.
I am thinking I should use validates_uniqueness_of :field, case_sensitive => false, Scope => ...
For my application it only has to be unique if, it was used <6 months ago.
Thinking to compare it to created_at, but don't really know how to go about it.
Second Item
I think I should somehow use .strip to remove any spaces before or after the text that the use may have put in accidentally (I know that these extra spaces are used by default in rails and if they are there can make a filed unique.)
If anyone has any hints on how this should be done correctly I really would appreciate it.
validates_uniqueness_of works by checking if a record already exists with the same value of the given field within the given scope. :scope lets you define the scope (obviously) of the uniqueness; for instance, if I was creating blog software and wanted to only allow a post title to be used once per blog, I could say validates_uniqueness_of :title, :scope => :blog_id -- without the scope, I'd only be allowing each title to be used once across the entire system. :scope won't let you do a complex check, like that which you desire.
What you're probably need to do is create your own validation function to check the uniqueness of the field in question within the given timeframe (code goes within the model):
validate :field_must_be_unique_within_six_months
def field_must_be_unique_within_six_months
return if field.blank?
num_duplicates = self.class.count(:conditions => ["field = ? AND created_at < ?", self.field, 6.months.ago])
if num_duplicates > 0
errors.add(:field, :taken)
end
end
The field_must_be_unique_within_six_months method will work similarly to validates_uniqueness_of, in that it will add an error message if there is already a record with the same given field, but with the added condition that it will also check the date. The validate :field_must_be_unique_within_six_months will add the method to the validation process when a record is saved.
To validate multiple fields at the same time without violating DRY, you could use validates_each to do something like the following:
validates_each :field1, :field2 do |record, attr, value|
if record.class.exists?(["#{attr.to_s} = ? AND created_at < ?", value, 6.months.ago])
errors.add(attr, :taken)
end
end
In the above block, record is the record being validated, attr is the attribute (so field1, field2, etc.) and value is the value of that attribute.
You can probably do something like this:
def validate
errors.add(:field, 'blah blah') if is_used_recently && !has_unique_field?
end
def has_unique_field?
Model.exists?(['field = ? and created_at > ?', self.field, 6.months.ago])
end
def is_used_recently
self.created_at < 6.months.ago || self.new? # i don't know if created_at would be set by this point
end
Alternatively you might want to create a new validation handler, or extend the existing one to pass in a :within option if that's something you're going to be doing often.
To get rid of leading and trailing white space the method you want is 'strip'. You can run this on all your fields by doing something like:
before_validation :clean_up_whitespace
def clean_up_whitespace
self.some_field.strip! # this does the strip in place
end
I hope this helps, let me know if I've made any mistakes!

Resources