Passing variable to edit form within ActiveAdmin controller - activeadmin

I'm trying to pass a rather large configuration hash into the data options attribute of an input in my edit form. Instead of sticking the whole thing in the one line I want to tidy up the page by moving the entire hash into a place that makes it more readable. So this is essentially what it looks like now:
controller do
before_action do
#froala_options = {
foobar: 'baz',
key: Figaro.env.froala_key,
image_upload_url: upload_image_path,
image_upload_to_s3: true,
imageUploadToS3: Rails.application.config.x.aws.s3_upload_defaults
}
end
end
# Edit
form title: 'New Page' do |f|
f.inputs do
f.input :country
f.input :title
f.input :slug
f.input :content, as: :froala_editor, input_html: { data: { options: #froala_options } }
end
actions
end
I've tried using:
controller do
def edit
# options variable here
end
end
and
controller do
def edit
# options variable here
edit!
end
end
As well as:
f.input :content, as: :froala_editor, input_html: { data: { options: proc { #froala_options } } }
.. to no avail.
When I inspect what's available with binding.pry inside the proc or form block I'm unable to see the #froala_options variable. All there are is methods that deal with the DOM.
I really don't want to begin creating partials to pass things in by using the semantic_form_for (unless I can use that within this AA register page).
What can I do?

In ActiveAdmin, when your code executes the form do..end block, it gets into the context of ActiveAdmin::Views::ActiveAdminForm, which is out of the scope of all instance variables defined inside the controller (like #froala_options).
Here you need to know that AA defines accessors for those instance variables, which you can get access from inside any view-specific code.
So the solution is really simple: use Accessors in place of Instance Variables inside the view context.
form title: 'New Page' do |f|
f.inputs do
...
f.input :content, as: :froala_editor, input_html: { data: { options: froala_options } }
...
end
actions
end

ActiveAdmin.register DslPort do
form do |f|
f.inputs do
f.input :snmp_profile, as: :select, collection: #dsl_port.snmp_profiles
end
f.buttons
end
end
or
f.input :snmp_profile, as: :select, collection: DslPort.find(params[:id]).snmp_profiles

Related

jquery jtable deleteConfirmation function not working

I am trying to use the deleteConfimation function option but I find that the default confirmation box pops up before I even get into the deleteConfimation function - what am I missing?
In the code below I can set break points and watch the data object being set up correctly with its new defaultConfirmMessage, but the basic jtable default delete confirmation box has already appeared and I never see an altered one.
$(container).jtable({
title: tablename,
paging: true,
pageSize: 100,
sorting: true,
defaultSorting: sortvar + ' ASC',
selecting: false,
deleteConfirmation: function(data) {
var defaultMessage = 'This record will be deleted - along with all its assignments!<br>Are you sure?';
if(data.record.Item) { // deleting an item
// Check whether item is in any preset lists
var url = 'CampingTablesData.php?action=CheckPresets&Table=items';
$.when(
ReturnAjax(url, {'ID':data.record.ID}, MyError)
).done(
function(retdata, status) {
if(status=='success') {
if(retdata.PresetList) {
data.deleteConfirmMessage = 'Item is in the following lists: ' + retdata.PresetList + 'Do you still want to delete it?';
}
} else {
data.cancel = true;
data.cancelMessage = retdata.Message;
}
}
);
} else {
data.deleteConfirmMessage = defaultMessage;
}
},
messages: {
addNewRecord: 'Add new',
deleteText: deleteTxt
},
actions: {
listAction: function(postData, jtParams) {
<list action code>
},
createAction: function(postData) {
<create action code>
},
updateAction: 'CampingTablesData.php?action=update&Table=' + tablename,
deleteAction: 'CampingTablesData.php?action=delete&Table=' + tablename
},
fields: tableFields --- preset variable
});
==========
After further testing the problem is only when deleting an item and it goes through the $.when().done() section of code. The Ajax call to the deletion url does not wait for this to complete - how do I overcome this?
i don't think you can get your design to work. What does the A in ajax stand for? Asynchronous! Synchronous Ajax has been deprecated for all sorts of good design and performance reasons.
You need to design you application to function asynchronously. Looking at your code, it feels you are misusing the deleteConfirmation event.
Consider changing the default deleteConfirmation message to inform the user, that the delete might not succeed if certain condition are met. Say
messages: {
deleteConfirmation: "This record will be deleted - along with all its assignments, unless in a preset list. Do you wish to try to delete this record?"
},
Then on the server, check the preset lists, and if not deletable, return an error message for jTable to display.
Depending on how dynamic your preset lists are, another approach might be to let the list function return an additional flag or code indicating which, if any, preset lists the item is already in, then your confirmation function can check this flag / indicator without further access to the server.
Thanks to MisterP for his observation and suggestions. I also considered his last approach but ended up setting deleteConfirmation to false (so as not to generate a system prompt) then writing a delete function that did not actually delete, but returned the information I needed to construct my own deleteConfimation message. Then a simple if confirm(myMessage) go ahead and delete with another Ajax call.

what is the proper way for testing create action in rails RESTfull controller?

I have a users_controller.rb file in which the create action is defined as:-
def create
#user = User.new(user_params)
if current_user.g_admin?
#user.role = 'c_admin'
elsif current_user.c_admin?
#user.role = 'c_user'
end
#user.admin_provisioned = true
authorize #user
respond_to do |format|
if #user.save
format.html { redirect_to authenticated_root_url, notice: 'User was successfully created and email has been sent.' }
format.json { render :show, status: :created, location: #user }
else
format.html { render :new }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
Now, I would like to write test for this method reflecting all the behaviour in this method. I'm completely new to testing, so detailed and standard way for writing test will be accepted as answer. The version to rspec is 3.4. Happy coding.
So the following way you could test this with rspec and capybara. For the fill in part you have to use the input elements that you have on your page.
describe "let an guest create a user account" do
fill_in :user_object, with: "value"
click_button "Save User"
expect(page).to have_content("User was successfully created and email has been sent.")
end
describe "let an guest try to create an account with invalid data" do
fill_in :user_object, with: "invalid value"
click_button "Save User"
expect(page).to_not have_content("User was successfully created and email has been sent.")
expect(page).to have_content("content from the :new page")
end

How do I add a custom form for my collection_action/controller?

I have the following:
collection_action :new, :method => :post do
begin
user = User.find_by_email(params[:email])
if user
UserPermission.create(:user_id => user.id,
:permission => UserPermission::SUPPORT,
:creator => current_user)
end
rescue ActiveRecord::RecordNotFound
flash[:warn] = 'User not found'
end
redirect_to admin_support_users_path, notice: 'Support user added.'
end
form do |f|
f.inputs do
f.input :email
end
end
action_item only: [:index], :method => :post do
link_to 'Add Support User', new_admin_support_user_path
end
The above works in the sense that no error is thrown. The support users page loads and I'm able to click the Add Support User button. However, 'Support user added.' is immediately shown. The Add Support User button does not take me to a form to enter an email. How do I add/create/use a form that passes an email parameter to my collection_action?
I'm new to activeadmin and documentation is sparse, so any help is appreciated. Thanks.
Figured it out. I'll try to explain as I understand it. And my initial question may have been unclear. The reason I was getting the, 'Support user added.' message is because I was updating the wrong method. The method above should have been the :create controller method, not the :new controller method. :new uses HTTP GET, which is why it would go directly to the redirect. :create accepts an HTTP POST. So, instead, I have the following:
def create
begin
user = User.find_by_email(params[:email])
if user
UserPermission.create(:user_id => user.id,
:permission => UserPermission::SUPPORT,
:creator => current_user)
end
rescue ActiveRecord::RecordNotFound
flash[:warn] = 'User not found'
end
redirect_to admin_support_users_path, notice: 'Support user added.'
end
def new
render 'new.html.arb', :layout => 'active_admin'
end
And this correctly creates a nice looking active admin form, accepting an email parameter.
You just need to add another action--just like a normal resource needs separate actions for create and new. Your 'new' action can render a custom form either inline or in a separate partial, as shown here:
http://www.activeadmin.info/docs/5-forms.html
That said, I'm not sure I understand why you need a custom action. Is this in your User resource file in active admin? If so you can just use the default new user action and include the current user in the form as a hidden variable as the creator. If this is not in your User resource active admin file then you probably need one.

validation on unbound form field

I have a form with an extra unbound field added using 'property_path' => false.
I would like to have a simple validation on this field and I've found many answers that suggest to use something like
$builder->addValidator(...);
but I've seen that in symfony 2.1 $builder->addValidator is deprecated. Does anyone know what is the correct way to put a validation on an unbound field in Symfony 2.1?
Edit :
I've just made a more complete answer on topic Symfony validate form with mapped false form fields
Original answer
Validating unbound (non mapped) field in a form is not well documented and the fast evolving form and validator components make the few examples obsoletes (for Symfony 2.1.2).
For now I succeed in validated non mapped fields with event listener.
Here is my simplified code :
namespace Dj\TestBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Symfony\Component\Form\FormEvents;
use Dj\TestBundle\Form\EventListener\NewPostListener;
class PostType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('lineNumber', 'choice', array(
'label' => 'How many lines :',
'choices' => array(
3 => '3 lines',
6 => '6 lines'
),
// 'data' => 3, // default value
'expanded' => true,
'mapped' => false
))
->add('body', 'textarea', array(
'label' => 'Your text',
'max_length' => 120));
// this listener will validate form datas
$listener = new NewPostListener;
$builder->addEventListener(FormEvents::POST_BIND, array($listener, 'postBind'));
}
// ... other methods
}
And the event listener :
namespace Dj\TestBundle\Form\EventListener;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormError;
/**
* listener used at Post creation time to validate non mapped fields
*/
class NewPostListener
{
/**
* Validates lineNumber and body length
* #param \Symfony\Component\Form\FormEvent $event
*/
public function postBind(FormEvent $event)
{
$form = $event->getForm();
$data = $event->getData();
if (!isset($data->lineNumber)) {
$msg = 'Please give a correct line number';
$form->get('lineNumber')->addError(new FormError($msg));
}
// ... other validations
}
}
This is how I validate my non mapped fields until I find out how to do this with validators.
I have the same problem from the docs we get this:
The interface FormValidatorInterface was deprecated and will be
removed in Symfony 2.3. If you implemented custom validators using
this interface, you can substitute them by event listeners listening
to the FormEvents::POST_BIND (or any other of the *BIND events). In
case you used the CallbackValidator class, you should now pass the
callback directly to addEventListener.
This suggest to use event listeners but I have not found and example.
https://github.com/symfony/symfony/blob/master/UPGRADE-2.1.md

Understanding the sencha touch object model

Okay, so I have the following class definition:
MyApp.views.ItemAction = Ext.extend(Ext.ActionSheet, {
items: [{
text: 'cancel',
handler: function(){
this.hide();
}
}]
});
When I create an instance of ItemAction and show() it, an action sheet appears. Brilliant.
Now my problem: pushing the cancel button will hide the button itself, and not the parent sheet.
How do I solve this?
Cheers
You can also try
handler: function(){
this.up().hide();
}
up will navigate up the owner chain. Calling it without any variables will get the immediate owner. But calling destroy is also a good idea since it will remove the sheet from the dom.
Okay, so I amended my code to look like this:
MyApp.views.ItemAction = Ext.extend(Ext.ActionSheet, {
id: 'itemaction',
items: [{
text: 'cancel',
handler: function(){
Ext.getCmp('itemaction').destroy();
//do other stuff here...
}
}]
});
And it works; I will use that for now, but of course I will appreciate a less kludgy solution (and no, setting the item scope to this does not work -- I get a DomWindow object if I do this).
Cheers

Resources