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 !
Related
I'm new in Ruby and make some simple admin using ActiveAdmin.
I have a model Question which I want to create, fill and store to database, it has an attribute themes (array of Theme models). When user creates a new record he doesn't enter themes manually but provide some string and system will automatically parse it and find or create themes. So I have code like that:
form do |f|
f.inputs "Questions Details" do
f.input :question, as: :string
f.input :autocomplete_themes, hint: "You should enter here multiple themes,
divide them with `,` or `;`"
end
f.actions
end
It creates a new field autocomplete_themes for entering string and it doesnt' exist in model Question. So what I want - is to get autocomplete_themes value like string and then use split() and my custom logic - but it gives an error.
before_create do |question|
array = []
puts "******"
puts :autocomplete_themes.text
themeTitles = :autocomplete_themes.split(",") #split(/,|;/)
for title in themeTitles do
theme = Theme.find_by(title: title)
theme = Theme.create(title: title) unless theme
array << theme
end
question.themes = array
end
Question: how can I get autocomplete_themes value as string? Thx!
Update: as I understood here - it looks like the similiar case, but there was problem with setting default value to custom field, but I need to get its value from code.
You did not specify the error you were getting, but based on the information you gave, you don't need autocomplete_themes to be a real database-backed attribute of the Question model, but rather you only need the information temporarily so that your before_create filter can use it to execute the appropriate logic.
Therefore, you could make autocomplete_themes a "virtual attribute" that is like a traditional member variable of an instance of Question.
class Question < ActiveRecord::Base
attr_writter :autocomplete_themes
attr_reader :autocomplete_themes
...other code
end
This will allow you to do things like:
#question.autocomplete_themes = "1,2,3"
themes_text = #question.auto_complete_themes
And best of all, ActiveAdmin supports having form inputs assign to virtual attributes. So you can keep your form like this:
form do |f|
f.inputs "Questions Details" do
f.input :question, as: :string
f.input :autocomplete_themes, hint: "You should enter here multiple themes,
divide them with `,` or `;`"
end
f.actions
end
And your before_filter would look like this:
before_create do |question|
array = []
themeTitles = question.autocomplete_themes.split(",") #split(/,|;/)
for title in themeTitles do
theme = Theme.find_by(title: title)
theme = Theme.create(title: title) unless theme
array << theme
end
question.themes = array
end
Please, explain, how can I make records in database with several methods, changing attributes I DON'T want to be attr_accessible.
For example, in User Model:
attr_accessible :email, :password, :password_confirmation, :guest
I don't want 'admin' true or false row be placed here because of security issue
You can assign the attribute manually, for example if your model is named User you can do the following :
user = User.first
user.update_attributes(attributes_hash)
user.admin = true
user.save
attr_accessible is used only for mass assignment via update_attributes for example, but you can always assign a specific property by calling it directly like in my example above.
I think you may be asking how to change the admin attribute in your test or development environment without adding it to attr_accessable.
One way would be the toggle method. For example,
user = User.first
user.admin?
=> false
user.toggle!(:admin)
user.admin?
=> true
A couple of things about toggle to consider. The attribute must be passed as a symbol and all callbacks and validations are skipped. In other words use caution for anything outside of testing and development. So this is how you can mass-assign the admin attribute without adding it to attr_accessable.
I am using Active Admin with Ruby on Rails and I am having an issue with the way that some models are shown in the panel.
Taking the class User as an example, if I do not define any method to display it friendly, I see #<User:00000006b47868>. So Active Admin suggests implementing a method to specify, for each class, how to show it.
According to the documentation (http://activeadmin.info/docs/3-index-pages/index-as-table.html), Active Admin looks for one of these methods to guess what to display, in the following order:
:display_name, :full_name, :name, :username, :login, :title, :email, :to_s
So having this method within the User class would solve the problem:
def display_name
return self.id.to_s + '-' + self.full_name
end
However, before using Active Admin, I was already using the method display_name with other purposes (for example, in views) in order to show the user name in a friendly way, and I do not want to show the same in Active Admin panel.
I cannot change the name of the method because I use display_name in a lot of files along the project, and changing it would probably introduce bugs in the application.
An ideal solution for this case would be to have something like an active_admin_name method that is used by Active Admin to show models in its panel. So the question is:
Is there any way to have a method that is called by Active Admin instead of display_name? For example, to result in the following order:
:active_admin_name, :display_name, :full_name, :name, :username, :login, :title, :email, :to_s
I have searched in Active Admin documentation and in config/initializers/active_admin.rb, but I could not find a way to do it.
Thanks!
Try
ActiveAdmin.setup do |config|
config.display_name_methods = [:active_admin_name, :display_name ...]
end
You can find this setting in lib/active_admin/application.rb
You could also use :title key to define it for each page, like this:
show(title: 'Something') do |record|
...
end
# or with a Proc
show(title: ->(record) { record.another_method_to_display }) do |record|
...
end
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
I need a "I accept terms of service" checkbox on a page, it has to be checked in order for the order to proceed. It seems hence illogical to have a column in the database to match this (whether user has accepted or declined terms).
I am using the form helper like this in my view:
<%= check_box("client", "terms") %>
And in my model:
validates_acceptance_of :terms
At the moment it is not working at all.
This seems like a really common piece of code, yet I can't find it used anywhere without having the terms in the model. Else I could use javascript to validate it, but would prefer to keep it all the in model.
This should work fine, without a database column or attr_accessor:
http://guides.rubyonrails.org/active_record_validations.html#acceptance
I would be inclined to check your params hash is as it should be i.e. that the 'terms' attribute is being passed within the 'client' hash, perhaps try adding raise params.inspect on your controller create action to help you debug?
What about having an attr_accessor :terms in your Client model?
I had this working with these settings:
In the controller, I have added :terms_of_service as a permitted field:
def application_params
params.require(:application).permit(. . . , :terms_of_service)
end
In the model:
attr_accessor :terms_of_service
validates :terms_of_service, :acceptance => true
In the view:
<%= f.check_box("terms_of_service", :checked => false) %>
attr_accessor :terms will do the trick nicely.
Either go with #neutrino's solution, or to reset :terms to "not accepted" if you need to redisplay the form (because validation may fail), use this:
def terms
nil
end
def terms=(val)
# do nothing
end