Default value of check_box in rails, work with failing validations? - ruby-on-rails-3

I'm trying to set the default value of a check box on a form so that it will be true UNLESS a user unchecked it. Normally, I could just set the :checked attribute to true on the checkbox
f.check_box :send_emails, :checked => true
However, if validations on the form fail, and the user unchecked the box, it will again be checked when the "new" action is re-rendered. Even though the value on the user object is indeed false when the re-rendering happens, because I have that "checked" attribute to true, it ignores that value.
To get around this, I put this in the controller for hte new action
#user.send_emails ||= true
It seems ugly, so I'm looking for a difference approach. Anyone come up with something different?

You could set the default value of :send_emails to true in the migration.
Here is an example, creating a migration to change the default value of a field:
class AddDefaultTrueToSendEmails < ActiveRecord::Migration
def change
change_column_default(:users, :send_emails, true)
end
end

Related

Validate if checkbox is checked depending on another validation in vuelidate

I'm just starting with Vue and vuelidate. I have a form which shall work in the following way:
The form shows a Yes/No radio button group.
If the radio button "Yes" is selected then the form shows a checkbox.
The submit button for the form shall be enabled if one of the following conditions is true:
The radio button is set to "No". OR
The radio button is set to "Yes" AND the checkbox is checked.
I'm having trouble with the conditions described in 3. My current validation looks like this:
termsAccepted: { checked: value => value === true }
This basically works for case 3.2 but not for 3.1. In that case the form is still disabled.
b-form-checkbox#termsAccepted(
v-model="termsAccepted"
:state="!$v.termsAccepted.$invalid"
:disabled="disableForm"
)
Thats sound like a computed property should to the job:
Computed Property Documentation
You could do something like:
computed: {
isEnabled() {
return !radiobutton || (radiobutton && checkbox.checked)
}
}

Override default scope in active_admin form.has_many

Given a model Post that has_many attachments, and an attachment has a hidden flag. Throughout the app I want to easily say post.attachments and only get the visible ones, so i setup a default scope in the Attachment model (using squeel):
default_scope -> { where { (hidden != true) | (hidden == nil) } }
But the admin page needs to be able to see all attachments for a post, not just the visible ones (so you can toggle the hidden checkbox). The default way of doing this (in admin/posts.rb) uses the default_scope and only lets me edit the visible ones:
f.has_many :attachments do |a|
...
end
I know I could just not use default_scope and instead name it :visible, and then everywhere (except the admin page) say post.attachments.visible but I prefer not having the do that.
How can I unscope the children attachments on the admin page?
Here's the solution I worked out:
In app/admin/posts.rb
f.has_many :attachments, for: [:attachments, f.object.attachments_including_hidden] do |a|
...
end
And in app/models/posts.rb
def attachments_including_hidden
Attachment.unscoped.where( attachable_id: id )
end
(where Attachment model belongs_to: :attachable, polymorphic: true )
What's going on? ActiveAdmin uses Formtastic, which uses Rails Form Builder.
The form.has_many method is an ActiveAdmin method, which calls Formtastic's form.inputs, which in turn calls Rails' fields_for. The :for option will get passed all the way down the fields_for, which can take a collection (as its 2nd arg) so I deliver this collection to it explicitly.

Rails 3 Active Admin add preset value to new record

I have tried to do it from the controller and from the active admin override controller and I can't make it work.
A user creates a website.
current_user has an id attribute
website has an user_id attribute
So when I create a new website I want to add the current_user.id into website.user_id. I can't.
Anybody know how?
Right now I need it on the new/create actions but I'll probably need this on the edit/update actions too.
This seems to work for me:
ActiveAdmin.register Website do
controller do
# Do some custom stuff on GET /admin/websites/*/edit
def edit
super do |format|
# Do what you want here ...
#website.user = current_user
end
end
end
end
You should be able to override other controller actions in the same way.
ActiveAdmin.register Model do
# also look in to before_create if hidden on form
before_build do |record|
record.user = current_user
end
end
See https://github.com/activeadmin/activeadmin/blob/master/lib/active_admin/resource_dsl.rb#L156
You need to add a 'new' method to the controller. The 'new' method creates an empty website object that will be passed to the form. The default 'new' method just creates an empty #website object. Your 'new' method should create the empty object, and then initialize the value of user to current user:
ActiveAdmin.register Website do
controller do
# Custom new method
def new
#website = Website.new
#website.user = current_user
#set any other values you might want to initialize
end
end

Active Record Observer not firing in console/seed

I have observers set up to award badges on model changes.
It works when I'm using the view, but I doesn't seem to fire when I do something like :
Photo.create(:user_id => user.id, :file => file) from the console or from the seed file.
Any idea ?
class ExplorerObserver < ActiveRecord::Observer
observe :photo
def after_save(photo)
user = photo.user
Explorer.award_achievements_for(user) unless photo.new_record?
end
end
My mistake, it was a silly issue, but for the archive, here is my answer :
If you have multiple observers, dont put multiple lines like that
config.active_record.observers = :popular_observer
config.active_record.observers = :explorer_observer
instead chain your observers, my previous code was overwriting the observers with the last one !
config.active_record.observers = :popular_observer, :explorer_observer
Did you forget to put it in config/application.rb, inside your Application class?
config.active_record.observers = :photo_observer

Best way to combine Play and Pause button?

this is more of an advise thread I guess.
I've been wondering how one could create a button which display "play" when it's not pressed. And then shows "pause" once it's pressed. And visa versa when it's pressed again.
I had a similar problem when trying to create an expand panel button, but that was easy because I could just set a variable to true or false if PanelCollapsed was true.
But in this case I couldn't find any property in a button that I could query.
So I came up with this but I can't help thinking that this is a rather unsmart way of doing it?
If isPlay = True Then
If isPaused = False Then
btnPlay.Image = Image.FromFile("iconPause.png")
isPaused = True
isPlay = False
End If
GoTo Endline
End If
If isPlay = False Then
If isPaused = True Then
btnPlay.Image = Image.FromFile("iconPlay.png")
isPaused = False
isPlay = True
End If
End If
Endline:
How about using only one variable and code like this:
If isPlay Then
btnPlay.Image = Image.FromFile("iconPause.png")
else
btnPlay.Image = Image.FromFile("iconPlay.png")
End If
isPlay = not isPlay
You can use the "Tag" property. Its type is "object" so you can use any object you want, but in your case a string will do:
If Button1.Tag = "Pause" Then
Button1.Image = Image.FromFile("iconPlay.png")
Button1.Tag = "Play"
Else
Button1.Image = Image.FromFile("iconPause.png")
Button1.Tag = "Pause"
End If
Most .NET WinForm controls have a 'Tag' property (a button has one). You can set the Tag to be anything you want. An easy way to do this is to set the 'Tag' property to a boolean with the state of the button.
Just an idea...sure there are many other approaches.
UPDATE:
Otherwise, you can maintain the state of the button in your application as its own member variable. This might have several advantages because you can pass this state to other controls that might need it. The only weakness with this approach is that the state must be maintained separately.
If you have a fairly straight-forward implementation, use the Tag property.
A contrary opinion ...
... while other answers have given you some techniques to achieve your desired result, I'm going to ask you to reconsider your UI design.
Dual state buttons - ones that alternate purpose when clicked - can be a source of user frustation.
Here are two scenarios.
Scenario #1 ... if the users machine is under load (for any reason), there may be a perceptible delay between the users actual click on your button and when your click handler is executed.
Normally the time between click and handler is a few milliseconds or less, but it can run to several seconds. If this happens when the user clicks on a dual state button, they are likely to click the button again. Net effect, when the application catches up, is to toggle on, then immediately off again.
Scenario #2 ... many users habitually double click everything. Even experienced users who've been using computers for years may have this weird habit. When they try to press a dual state button, guess what happens ... the action toggles on, then immediately off again.
There are at least two solutions ...
Solution #1 ... use two buttons, one for "On", one for "Off".
Solution #2 ... write some debouncing code to suppress the effect of a second click if processed immediately (ie: < 75ms) after the first.
I don't personally use Visual Basic, but I do know that Buttons in Windows Forms have a property called 'Tag'. It is of the generic object type, so you can save whatever state you want, and just use casting to get the value back out.
How about using the "Image" property?
Rem form initialization
ImagePlay = Image.FromFile("iconPlay.png")
ImagePause = Image.FromFile("iconPause.png")
Button1.Image = ImagePlay
.
.
.
Rem on button1 click
If Button1.Image = ImagePlay Then
Button1.Image = ImagePause
Else
Button1.Image = ImagePlay
End If