default blank for boolean dropdown menu - ruby-on-rails

I am creating an application where users can create apartment listings.
The form asks users to specify whether there is an agent fee and if the apartment is furnished.
In the apartment form partial (which is rendered in the create and edit apartment views), I have two dropdown menus for these boolean variables (furnished and agent_fee).
I validate that these variables are present in the model validation:
class Apartment < ActiveRecord::Base
belongs_to :user
validate :agent_fee_and_furnished_are_present
def agent_fee_and_furnished_are_present
if agent_fee.nil?
errors.add(:agent_fee, "You must specify if there is an agent fee")
end
if furnished.nil?
errors.add(:furnished, "You must specify if the apartment is furnished")
end
end
end
(I created a custom validation so FALSE would be allowed. If I validated the presence of the variables, FALSE would fail the .blank test that ruby runs.)
My question is, how can I include a blank option as the first option in the dropdowns that will work in the create AND edit views?
(I want to do this so the user is forced to select one of the options, and doesn't end up with a default because that's what was the first in the dropdown)
I tried:
<div class="field">
<%= f.label :agent_fee, "Is there an agent fee?" %><br>
<%= f.select :agent_fee, options_for_select([['Yes', true], ['No', false]]), {:prompt => ""} %>
</div>
However, when this field is rendered in the edit apartment view, there is a blank prompt present, even if the agent_fee for an apartment the apartment was FALSE. (It seems that rails does a similar .blank? test which only overrides the prompt if the value is TRUE)
So again, my question is, how can I include a blank option as the first option in the dropdowns that will work in the edit view (and only be displayed if the agent_fee variable is NIL and not FALSE)

Use include_blank in the f.select call:
<%= f.select :agent_fee, options_for_select([['Yes', true], ['No', false]]), { :include_blank => true } %>

Related

Formtastic pre-check few checkboxes

I'm trying to manually tell formtastic to check a few checkboxes. #some_array currently has an element called checked which exists for each member.
= f.input :cboxes, label: "CBoxes", as: :check_boxes,
collection: #some_array.map { |a| [a[:name], a[:id]] }
I've tried to set the input_html to { checked: 'checked' } (How to pre-check checkboxes in formtastic) but this checks all checkboxes, not just the select few that I want.
The contents of #some_array are coming via an API, and I can't change the database structure (Ruby on Rails + Formtastic: Not checking checkboxes for multiple checked answers)
Suggestions?
If you are editing an ActiveModel, you don't need to "manually select checkboxes".
Let's consider a simple example with a single User model which has fields username and roles. Roles field is a string column, which Rails serializes as an Array. It might also be has_many relation to other ActiveModel, but we assume it's an Array for simplicity.
User is defined in user.rb:
class User < ActiveRecord::Base
serialize :roles, Array
end
Now you can "assign manually" desired roles to User in your controller:
#user = User.new(username: 'dimakura', roles: ['admin', 'editor'])
and define form in your view:
<%= semantic_form_for #user do |f| %>
<%= f.input :username %>
<%= f.input :roles, as: :check_boxes, collection: ['owner', 'admin', 'editor', 'viewer'] %>
<% end %>
In given example only "admin" and "editor" roles will be pre-selected in form. The "owner" and "viewer" role won't be selected.
Update Official documentation states:
Formtastic, much like Rails, is very ActiveRecord-centric.
But actually it's not a big challenge to create ActiveRecord-compatible model yourself. An example of doing this can be found in this blog post.

Money Rails Gem - null values

I have monetised two models of my Rails 4 app with Money-Rails gem.
One is called Participants, the other is called Funding. Each of these models is nested inside another model, called Scope. Scope belongs to Project.
The associations are:
Project has one Scope; Scope belongs to Project
Scope has one Participant and has one funding; each of Participant and Funding belong to Scope.
Project accepts nested attributes for Scope. Scope accepts nested attributes for Participant and Funding.
Params for each relevant attribute in Participant and Funding are permitted in the Scope and Project Controllers as well as the models themselves. Params for Scope are permitted in the Scope and Project controllers.
In my Project form, I ask several questions. That form also has nested forms for each of the models which belong to it. Inside the Scope form, I ask users two boolean questions, being: Do you want participants? Do you want funding? Each of these models has a follow up question about participation cost and funding (those attributes are monetised).
If the answer to those questions is true, then I reveal the participant or funding form partial and ask how much money they want.
I have two problems:
First problem: Not null violation
1. If a user says they do want participants, but there is no associated costs, so that the boolean question inside the participant model asking whether there is cost involved with participation, I get an error that says:
ERROR: null value in column "participation_cost_pennies" violates not-null constraint
If a user says they don't want participants in answer to the question asked in the Scope form, I get the same error as in 1 above
Second problem: If I save an amount in the monetised fields, and come back to edit the project form, the form does not show the saved amount in the monetised field - and if you don't reenter it, I get an error saying that it can't be blank.
Does anyone know how to:
make the first problem go away in all circumstances except those when participation costs are actually sought; and
Fix the second problem by displaying the original amount saved when you come back to edit the form? I have tried inserting :selected into my form element, but it doesn't do anything.
My code is as follows:
Inside my Scope form (nested inside my project form):
<%= f.simple_fields_for :scope do |s_all| %>
<%= s_all.input :if_participant, :as => :boolean, :label => false, inline_label: 'Public participants or volunteers' %>
<%= s_all.input :if_funding, :as => :boolean, :label => false, inline_label: 'Funding or expenses' %>
If the answer to these fields is true, then I reveal the partial forms for participant of funding (for whichever is true).
Inside my Participants partial form, I have:
<%= f.simple_fields_for :scope do |participants_s| %>
<%= participants_s.simple_fields_for :participant do |par| %>
<%= f.label 'Are participants reimbursed for their costs?', :class => 'question-project' %>
<%= par.collection_radio_buttons :costs, [[true, ' Yes'], [false, ' No']], :first, :last, {:item_wrapper_class => 'fixradio'}, {:class => "response-project"} %>
<%= f.label 'What amount will you pay for participation costs?', :class => 'question-project' %>
<%= par.select :participation_cost_currency,
options_for_select(major_currencies(Money::Currency.table)), selected: :participation_cost_currency,
label: false,
prompt: "Select your costs currency" %>
<%= par.input :participation_cost, label: false, placeholder: 'Whole numbers only', selected: :participation_cost_pennies, :input_html => {:style => 'width: 250px; margin-top: 20px', class: 'response-project'} %>
For the first problem, you'll want to set a default value for the participation_cost_cents column in a migration:
# in console
> rails g migration change_default_for_participation_cost_cents
# in migration file
class ChangeDefaultForParticipationCostCents < ActiveRecord::Migration
def change
change_column :participants, :participation_cost_cents, :integer, default: 0
end
end
I'm not sure I follow on the second problem though. Maybe you should split the question in two?
A meetup group for Rails has helped me answer this question. The answer is not obvious - especially for newcomers.
My problem was I had an attribute in my database called participation_cost. Monetise then tried to make a method with the same name and that was failing because of the attribute in my table. For others, you don't need the attribute in your database with the name of the field you want to monetise.
Removing that attribute (in my case, participation_cost) solved my problem.

ruby on rails how to use FormOptionHelpers to create dynamic drop down list

I have checked some tutorials but I got confused by the parameters in this method
collection_select (object, attribute, collection, value_method, text_method, options = {}, html_options ={})
I have a map model includes: :area, :system, :file
and I want to read :area from database to a drop down list, and let user choose one
I already did #map = Map.all in the view
what the method should be?
especially the parameter "attribute". In a lot tutorials, people put "id" here. But I don't know what "id" is, and in my situation I don't need any other value, just the "area".
Im not exactly sure what you are asking here but if you are trying to make a dropdown selection for use in an html form will this example help you at all?
<% nations = {'United States of America' => 'USA', 'Canada' => 'Canada', 'Mexico' => 'Mexico', 'United Kingdom'=> 'UK'} %>
<% list = nations.sort %>
<%= f.select :country, list, %>
Here nations is a hash of countries then list becomes the sorted copy of that hash. An html dropdown is then created as a part of the form "f". ":country" is the part of the model that the data is connected to while list is the options to populate the dropdown with
It's not clear from your question what the model is that's being populated with the area.
Typically, collection_select is used between related models.
eg.
class Category < ActiveRecord::Base
has_many :products
end
class Product < ActiveRecord::Base
belongs_to :category
end
When selecting the 'category' for a product, your view would have something like:
<%= f.collection_select(:category_id, :id, Category.all, :name, include_blank: true) %>
What this does is specify the Product.category_id as the attribute being populated with the value of Category.id. The values come from the Category.all collection, and with Category.name being the item displayed in the select. The last (optional) parameter says to include a blank entry.
Something like the following is probably what you need:
<%= f.collection_select(:map_id, :id, #map, :area) %>
However, if the model you're trying to populate has an area attribute (instead of an ID linking to the map), you might need to use:
<%= f.collection_select(:area, :area, #map, :area) %>
This specifies that the area attribute of the receiving table will be populated with Map's area attribute, which is also being used as the "description" in the select.

Accept Rails model attribute only if it was previously blank

I have a Rails model (persisted with Mongoid) that can be collaboratively edited by any registered user. However, I want to allow editing any particular attribute only if it was previously blank or nil.
For example, say someone created an object, and set its title attribute to "Test Product". Then another user comes along and wants to add a value for price, which until now has been nil.
What's the best way to do this, while locking an attribute that has previously been entered?
Look into the ActiveRecord::Dirty module for some nice utility methods you can use to do something like this:
NON_UPDATABLE_ATTRIBUTES = [:name, :title, :price]
before_validation :check_for_previously_set_attributes
private
def check_for_previously_set_attributes
NON_UPDATABLE_ATTRIBUTES.each do |att|
att = att.to_s
# changes[att] will be an array of [prev_value, new_value] if the attribute has been changed
errors.add(att, "cannot be updated because it has previously been set") if changes[att] && changes[att].first.present?
end
end
The easiest way, i think, is by checking for it in the form itself.
Just say add :disabled => true to the input field if the person cannot edit it.
<% if #my_object.name %>
<%= f.text_field :name, :disabled => true %>
<% else %>
<%= f.text_field :name, :disabled => true %>
<% end %>
(i think there is a prettier way to write this code)
But by using this the user has a visual feed back that he can't do something, it is always better to not allor something than to give an error message

declarative_authorization problem with creating new user

I used declarative_authorization for my app and had problem with creating new user.
my User model code:
class User < ActiveRecord::Base
ROLE_TYPES = ["admin", "user", "guest"]
validates_inclusion_of :roles, :in => ROLE_TYPES
def role_symbols
#role_symbols ||= (roles || []).map{|r| r.to_sym}
end
my view code:
<% form_for(#user) do |f| %>
...
<p>
<%= f.label :roles %><br />
<%= f.select :roles, User::ROLE_TYPES, :prompt => "Select a role" %>
</p>
<%= f.submit 'Add User' %>
<% end %>
every time i tried to create a new user and select the role from the drop-down list, the view complaint:
Roles is not included in the list
from the output of the script/server, i can see the roles was actually set:
"user"=>{"name"=>"kc", "password_confirmation"=>"kc", "roles"=>"guest", "password"=>"kc", "email"=>"kc#one.com"}
can anyone tell me what's wrong? why the validation wont' pass?
Is it possible that you've got attr_accessible attributes on the user to prevent mass assignment of certain attributes and that :roles isn't in there? You would get a warning about this in your logs though. The default User class generated by restful_authentication does include the attr_accessible call so it may be there without you having added it if you are using that authentication plugin too.
Is there definitely a roles attribute of the right type for users? It looks like you're expecting roles to be a single string from your form but in the code from declarative_authorization you've got (roles || []).map which suggests that that part of the code at least is expecting an array of roles.

Resources