How to use a variable as an attribute in update_attributes - ruby-on-rails-4

So I have an object with a set of attributes that are boolean flags that mark whether something has been published or not. There are several different formats it can be published to: published_to_web, published_to_email, published_to_pdf, etc. Rather than having a separate method to reset each format, I thought I would simply use one method, and set the attribute with a variable sent when the pertinent button (web, email, pdf, etc.) was clicked on. So for example a button calls the method and params[:format] = 'web', so I want to set the object's 'publish_to_web' attribute to false:
#bulletin.update_attributes( "published_to_#{params[:format]}", false)
but I can't get it to work. Seems like it should be simple in RoR but I can't seem to get the right juju. I've tried:
#bulletin.update_attributes( "published_to_#{params[:format]}".to_sym, false )
#bulletin.update_attributes( "published_to_#{params[:format]}", false )
#bulletin.update_attributes( "published_to_#{params[:format]}: false" )
#bulletin.update_attributes( ":published_to_#{params[:format]}" => false)
... what's the secret sauce?

#bulletin.update_attributes( "published_to_#{params[:format]}" => false)

Related

Logstash conditional check for nil/null value in a field

I have a json data with some field value as null (eg: "location": null). I would need to check whether this field is null, and take some action.
I have tried using if [location] == 'null' { do something } but it fails, also I have tried with if [location] == 'nill' { do something }
Found some relative links that mentioned to check whether the field exist if [location] but this can't be used in my case.
Please help me to solve this, thanks in advance.
You will need to use the ruby filter to check if the field has a null value.
The following filter checks if the field is null and then, if true, adds a tag to the event.
ruby {
code => "if event.get('location').nil?; event.set('tags','null-value');end"
}
You can then use the tag normally in logstash to do what you want, for example
if "null-value" in [tags] { do something }

emberjs - dynamic computed property does not trigger classNameBindings

I am creating a mixin to validate components with texFields it looks like this, I am using Ember.defineProperty to create a cp on the fly with a dynamic dependant key:
App.ValidationMixin = Ember.Mixin.create
classNameBindings: ['isInvalid']
input: (e) ->
#_super.apply this, arguments
setup: Ember.on 'didInsertElement', ->
unless validations = #get('validations')
el = #autocompleteElement()
# I had to add this to access the prop rather than it getting
# triggered when the dynamic property changes
if #get('isInvalid')
el.addClass 'is-invalid'
else
el.removeClass 'is-invalid'
validationMixin: Ember.on 'didInsertElement', ->
unless validations = #get('validations')
return
dynamicProperty = # logic to determine dynamic property
Ember.defineProperty this, 'isInvalid', Ember.computed dynamicProperty, 'validator.isSubmitted', ->
# validation logic
The problem is, I have to manually check for this.get('isInvalid') rather then the property function being executed when one of the dependant keys changes.
Can anyone explain why this is?
Ember probably thinks that the property 'isInvalid' is not used anywhere and therefore doesn't update it. I guess that 'didInsertElement' is called after the classNameBindings property... Try to output the 'isInvalid' property in the template to check if that's the case because therefore it must be updated.

Zend Framework 2 Saving layout and template content in database

I want to save both layout and view template CONTENT in the database. Each view template will be associated to a layout_id. When a controller action loads, it will fetch the appropriate layout and view from database.
I've done fair amount of researching, looks like this hasn't been discussed before, at least not with ZF2. Not only I want different themes for the site, I also want version control on the design, user can work on a version of template, save it and when done publish the site. I've been looking into custom view strategy and renderer and could not find out how to piece everything together.
Please advice how to proceed with this problem. If there are any tutorials out there please let me know.
First, you have to decide your database structure. I would prefer a table where for each controller/action, depending on the version of the design, you have a file for the layout view, and another for the action view. I think it is a flexible way, since you can have for instance the same layout for all the controllers, but a a different view for the content of every action, or you can have a different layout for an specific controller.
It could be something like this.
CREATE TABLE `templates` (
`version` INT(5) NOT NULL,
`controller` VARCHAR(30) NOT NULL,
`action` VARCHAR(30) NOT NULL,
`layout_view` VARCHAR(30) DEFAULT NULL,
`action_view` VARCHAR(30) DEFAULT NULL,
PRIMARY KEY (`version`,`module`,`controller`,`action`)
)
remember that the template names has to be 'MODULE/CONTROLLER/ACTION' that is the format that the function ViewModel::setTemplate is expecting. So if in your Module Foo, you have the folder view, with a hierachy like this Foo/view/foo/controllerName/actionName.phtml in your database you should store: foo/controllerName/actionName
Then you have to set, somewhere in the config files, the current design version that has to be used. This version could be a different one in your local machine, and in the production server. For that, you leverage the /config/autoload/local.php that allows you to have different configuration in the different enviroments, just telling your git, subversion, or ftp, to ignore this file, so you can have a different one in every enviroment. Check this docs. It will be enough if you put something like this:
/config/autoload/local.php
return array(
'designVersion' => 1,
);
Then when the application loads, you have to check the current version of the design, and set the correct templates to be used. I would do it after the dispatch event, so the way would be to add a listener in the app bootstrarp. For that, in your main module (i.e. "App" or "Application" module), in the Module.php you overwrite the onBootstrap function, load the event manager, and add a callback to the MvcEvent::EVENT_DISPATCH event.
There, you can have access to the serviceManager, so you can retrieve your database adapter, also, you can know the current requested controller and action, the current viewmodel object, and from it, the action viewmodel. So you already have everything you need. So you can go like this:
public function onBootstrap(MvcEvent $e) {
//get the service manager
$sm = $e->getApplication ()->getServiceManager ();
//get your db adapter
$db=$sm->get("whatever is the service name of your database adapter, entity manager, or whatever you are using");
//get the config
$config = $sm->get ( 'config' );
$version = $config ['designVersion'];
//get the event manager, and attach a callback to the MvcEvent::EVENT_DISPATCH
$em = $e->getApplication ()->getEventManager ();
$em->attach ( MvcEvent::EVENT_DISPATCH, function ($e) use($sm) {
//you get the routeMath, so you can know the controller and action
$routeMatch = $e->getRouteMatch ();
$action=$routeMatch->getParam ( 'action' );
$controller=$routeMatch->getParam ( 'controller' );
//now, with $action, $controller, and $version
//you query your db to get the layout and view templates:
$views=$db->whetever..
$layout_template= $views->layout_view;
$action_template= $views->action_view;
//you get the current viewModel, it hasnt been rendered yet, so we can set the templates
$viewModel = $e->getViewModel ();
if (is_null ( $viewModel ))
return;
$viewModel->setTemplate ($layout_template);
//and now, we get the action view model, that we know that is set as a children of the layout viewmodel. So we can retrieve it like this:
$children = $viewModel->getCurrent()->getChildren();
$child = $children[0];
//if we are afraid the view could have more children, and you want to make sure that you rerieve the correct one, then you could iterate over $children and look for the child that has the correct captureTo name set. For the action’s view model, this defaults to content:
/*
$children = $viewModel->getCurrent()->getChildren();
$child=null;
foreach($children as $c) {
if ($c->captureTo() == 'content') {
$child=$c;
break;
}
}
*/
//and now, you set the template to the view:
$child->setTemplate ($action_template);
}, - 100 );
}

A proper way to separate concerns?

My app allows the users to manage their documents. When creating one, a user has to either enter the document content manually or select a file from their computer (which would convert many formats to HTML for the user).
Currently, I have a simple FileUploaderView which is basically an <input type="file"> that listens to file changes, and updates the value property of the view with an object like { file: { type: SOME_TYPE' }, content: SOME_CONTENT }.
Then, DocumentsNewController listens to changes in it and converts supported files to HTML, and puts the result into the document body.
However, doing it this way feels simply wrong and does not allow for simple reuse (which I want to be able to do).
App.DocumentsNewController = Ember.ObjectController.extend
# ... stuff ...
handleDocumentUpload: (->
doc = #get 'documentUpload'
return unless doc
Ember.run =>
#set 'uploadError', false
#set 'unsupportedFile', false
#set 'processingUpload', true
type = doc.file.type
text = ''
try
if type.match /^text\//
text = doc.content
# Convert new lines to br's and paragraphs
text = '<p>' + text.replace(/\n([ \t]*\n)+/g, '</p><p>').replace('\n', '<br />') + '</p>'
else if type == 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
text = new DOCX2HTML(doc.content).convert()
else
#set 'unsupportedFile', true
catch error
#set 'uploadError', true
finally
#set 'text', text
Ember.run => #set 'processingUpload', false
).observes 'documentUpload'
And the template is something like
... stuff ...
{{view App.FileUploaderView valueBinding="documentUpload" accept="text/*"}}
What would be the proper way to refactor file converting stuff out of the controller?
I want to be able to do something like:
{{documentHandler resultBinding="documentUpload"}}
and in controller
App.DocumentsNewController = Ember.ObjectController.extend
# ... stuff ...
handleDocumentUpload: (->
if doc = #get 'documentUpload'
#set 'text', doc
).observes 'documentUpload'
My first thought was to make a DocumentHandlerView which would display the input field, show the spinner, show the errors, parse the document and assign the result to result (and since controller's template has resultBinding="documentUpload", the HTML would trigger the controller's observer).
Using a view for that would allow for easier reuse but I still feel it's not the view's job to parse the document.
Is there a better way?
After reading closely your question the best thing that comes in mind would be to create a Ember.Mixin and then use it for all the controllers that need the same functionality.
Example taken from the ember API docs:
App.Editable = Ember.Mixin.create({
edit: function() {
console.log('starting to edit');
this.set('isEditing', true);
},
isEditing: false
});
// Mix mixins into classes by passing them as the first arguments to
// .extend.
App.CommentView = Ember.View.extend(App.Editable, {
template: Ember.Handlebars.compile('{{#if isEditing}}...{{else}}...{{/if}}')
});
commentView = App.CommentView.create();
commentView.edit(); // outputs 'starting to edit'
The example is only conceptual, but it will be easy to create a mixin yourself and put all the common logic in there.
Hope it helps.

Format a property before displaying it

Hello StackOverflow experts,
I would like to know if it would be possible to use Ember.js' computed properties to modify the value of the property before returning to whatever object requests it.
Imagine this simple example:
I have a User object with mail property
When I set the property, I want the email address to change from first.last#example.com to first.last#anotherexample.com, then return it
When I request the property ( via User.get ) I want to get the modified property back.
I think it should be pretty simple by utilising another 'helper' property, like formatted_mail, where I would store and retrieve the formatted value, but I wonder if something like this can be done without additional model properties.
So far, I have this coffescript code, but I always get 'undefined' when reading the property, even though I set it before, so I suspect the value does not get saved by Ember anywhere:
mail: ( ( key, value ) ->
if arguments.length == 1
return this.get 'mail'
else
return value.split( '#' )[0] + '#anotherexample.com'
).property 'mail'
Thank you for your assistance!
You are close to solution.
As computed properties are always cached by default in Ember (you could disable this behaviour using .volatile()), you do not have to specify what to do when arguments.length is 1, except if you want to specify a default value.
So here it should looks like:
App.User = Ember.Object.extend({
mail: function(key, value) {
if (arguments.length === 2) {
return value.split('#')[0] + "#tieto.com";
}
return null;
}.property()
});
The return null just specify the default value.
When you set the mail property, it will cache the returned value and always returns it without recomputing this property.
Note that you can do that only because the mail property does not depend on other properties. If you were declaring it with .property('anotherProperty'), the mail property will be recomputed any time anoterProperty changes. So in the example above it will reset it to null.
You can try it in this JSFiddle.