Non-model field is not validated in nested form - ruby-on-rails-3

I'm trying to add a validation of 'size' property for 'Creative' model. 'Creative' model is one-to-one related to the 'Ad', and it's field are displayed as a nested form in the 'Ads' form(code provided below).
The problem is, that when I'm actually saving the form, size is not validated — neither with format validator, nor with :presence validator(if I add one). At the same time, :filter property is validated.
Size is a non-model property, added with attr_acessor method and custom setters and getters.
Looking for a way to fix this code or any different solution to add a validation for non-model nested property will be much appreciated.
Controllers:
class Creative < ActiveRecord::Base
attr_accessible :size, :filter
belongs_to :ad
attr_accessor :size
validates :size, :format => { :with => /^\d+x\d+$/, :message => "Incorrect size param. Should be [width]x[height], e.g. 320x50" }
validates :filters, :presence => true
def size
"#{self.width}x#{self.height}"
end
def size=(size)
#width, #height = size.split("x").map(&:to_i)
end
end
class Ad < ActiveRecord::Base
attr_accessible :creative_attributes
has_one :creative
accepts_nested_attributes_for :creative
validates_associated :creative
end
class Campaign < ActiveRecord::Base
has_many :ads
end
Form:
<%= simple_form_for [:rtb, #campaign, #ad], :html => { :class => 'form-horizontal' } do |f| %>
<% if #ad.errors.any? %>
<div id="error_explanation" class="alert alert-error">
<h2><%= pluralize(#ad.errors.count, "error") %> prohibited this ad from being saved:</h2>
<ul>
<% #ad.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<%= f.input :name %>
<%= f.simple_fields_for :creative do |creative_f| %>
<fieldset>
<legend>Creative Settings</legend>
<%= creative_f.input :size %>
<%= creative_f.input :filters %>
</fieldset>
<% end %>
<%= f.button :submit, :class => 'btn-primary' %>
<% end %>

Related

fields_for accepts_nested_attributes_for not submitting properly

Having issues with nested attributes using fields_for. Anyone know what I am missing? I have checked many posts and RailsCasts and have not been able to figure it out.
Overview: I have a list of chart types (chart_type) that have one or more parameters (chart_param). Based on the chart type selected, I display the proper chart parameters and allow users to enter a value (chart_param_value). This is all from within my Indicators form.
Problem: The form submission is not retuning the nested attributes properly. The params being submitted look something like this "chart_param_values"=>{"value"=>"", "chart_param_id"=>"10024"}".
chart_type.rb
attr_accessible :multiple_indicators, :name, :chart_params_attributes
has_many :chart_params, :dependent => :destroy
accepts_nested_attributes_for :chart_params, :allow_destroy => true
def self.single_indicator
where(:multiple_indicators => false)
end
def self.multiple_indicators
where(:multiple_indicators => true)
end
chart_param.rb
attr_accessible :chart_type_id, :name, :required, :tooltip
belongs_to :chart_type
chart_param_value.rb
attr_accessible :chart_param_id, :indicator_id, :main_indicator_chart_id, :value
belongs_to :chart_param
#belongs_to :chart_type
belongs_to :indicator
indicator.rb
attr_accessible :chart_type_id, :description, :help_text, :key_name, :name, :display_screen, :any_details, :indicator_details_attributes, :chart_param_values_attributes
belongs_to :chart_type
has_many :chart_param_values, :dependent => :destroy
accepts_nested_attributes_for :chart_param_values
indicators/_form.html.erb
<%= form_for(#indicator) do |f| %>
...
<div class="field">
<%= f.label "Chart Type" %>
<%= f.select :chart_type_id, ChartType.single_indicator.collect { | ct | [ct.name, ct.id] }, {}, :onchange => "update_chart_params(this);" %>
</div>
<div id="Charts">
<% ChartType.single_indicator.each do |ct| %>
<div id="chart_type_params_<%= ct.id %>" <% if !#indicator.chart_type_id.eql?(ct.id) %> style="display: none" <% end %> >
<% ct.chart_params.each do |ctp| %>
<%= fields_for :chart_param_values do | builder | %>
<%= builder.hidden_field :chart_param_id, :value => ctp.id %>
<%= builder.label :value, ctp.required ? "* #{ctp.name}" : ctp.name %>
<%= builder.text_field :value %><br />
<% end %>
<% end %>
</div>
<% end %>
</div>
<script language="javascript">
update_chart_params = function(select){
alert(select.value);
<% ChartType.single_indicator.each do |ct| %>
$('#chart_type_params_' + <%= ct.id %>).hide();
<% end %>
$('#chart_type_params_' + select.value).show();
}
*Also, if I change the fields_for to f.fields_for and add #indicator.chart_param_values.build to the indicators_controller new/create methods, I get duplicated fields on the form based on how many chart_param_value records were built.

HABTM Checkboxes using simpleform gem

I have three models, and i am trying to save onto a third table using simple form gem and checkboxes.
class Work < ActiveRecord::Base
has_many :skills, through: :skillships
end
The second model is
class Skill < ActiveRecord::Base
has_many :works, through: :skillships
end
The third is
class Skillship < ActiveRecord::Base
belongs_to :work
belongs_to :skill
end
Using the Work model i am trying to save the data on the skillship table. Something similar to this http://railscasts.com/episodes/17-habtm-checkboxes-revised. Can you please help.
EDIT
The form
<%= simple_form_for(#work) do |f| %>
<%= f.error_notification %>
<div class="form-inputs">
<%= f.input :title, :label => 'Project Title' %>
<%= f.input :excerpt, :as => :text %>
<fieldset>
<legend>Skills Used </legend>
Would like to check the skills i used here.
</fieldset>
</div>
<div class="form-actions">
<%= f.button :submit %>
</div>
<% end %>
I tried..
<%= hidden_field_tag "work[skill_ids][]", nil %>
<% Skill.all.each do |skill| %>
<%= check_box_tag "work[skill_ids][]", skill.id, #work.skill_ids.include?(skill.id), id: dom_id(skill) %>
<%= label_tag dom_id(skill), skill.title %><br>
<% end %>
The reason i'm doing this it because work can have many skills used.
I was going about this the wrong way. A join table solved the problem.
rails g migration create_skills_works_table
Then
class CreateSkillsWorksTable < ActiveRecord::Migration
def self.up
create_table :skills_works, :id => false do |t|
t.references :skill
t.references :work
end
add_index :skills_works, [:skill_id, :work_id]
add_index :skills_works, [:work_id, :skill_id]
end
def self.down
drop_table :skills_works
end
end
Using simple form on the work view.
<fieldset>
<legend>Skills Used </legend>
<%= f.association :skills %>
</fieldset>

fields_for for has_many through relationship rails 3

I have problem in getting below code to work.
class Page < ActiveRecord::Base
has_many :page_parts, :through => :page_parts_pages
has_many :page_parts_pages
accepts_nested_attributes_for :page_parts, :allow_destroy => true
accepts_nested_attributes_for :page_parts_pages, :allow_destroy => true
end
class PagePart < ActiveRecord::Base
has_many :page_parts_pages
has_many :pages, :through => :page_parts_pages
end
class PagePartsPage < ActiveRecord::Base
belongs_to :page
belongs_to :page_part
end
Table Structure:-
pages
id, title
pages_parts
id, title
page_parts_pages
id, page_id, page_part_id
View code
<% page_fragment.each do |k,v| %>
<% if v.nil? or v.blank? or v.empty? %>
<% parts = f.object.page_parts.build if f.object.page_parts.blank? %>
<%= f.fields_for :page_parts, parts do |p| %>
<%= render 'page_part_form_field', :f => p %>
<% end %>
<% else %>
<% parts_page = f.object.page_parts_pages.build if f.object.page_parts_pages.blank? %>
<%= f.fields_for :page_parts_pages, parts_page do |p| %>
<%= render 'page_part_page_form_field', :f => p %>
<% end %>
<% end %>
<% end %>
Actually the scenario is, I have to display the fields for page_parts and page_parts_pages on condition basis. If condition is satisfied, display fields for page_parts else display fields for page_parts_pages.
It's working perfectly fine for new action but for edit action it is not displaying correctly.
Any help is highly appreciated.
Thanks in advance
You are creating new page_parts in this form:
parts = f.object.page_parts.build if f.object.page_parts.blank?
parts_page = f.object.page_parts_pages.build if f.object.page_parts_pages.blank?
'build' creates new objects (it will not persist them in database though). So, no wonder it works for new, but not for edit.
You can try this:
<% page_fragment.each do |k,v| %>
<% if v.blank? %>
<%= f.fields_for :page_parts do |p| %>
<%= render 'page_part_form_field', :f => p %>
<% end %>
<% else %>
<%= f.fields_for :page_parts_pages do |p| %>
<%= render 'page_part_page_form_field', :f => p %>
<% end %>
<% end %>
<% end %>
rails api has pretty good documentation of forms_for and other form helpers.

Rails: Validation for a simple_form using has_many relationship (e.g. Person, Phone)

I'm struggling getting the desired validation with nested models within a simple_form. You'll be able to see from the models below a Person can have many Phone's, the desired behaviour is to present edit fields for any existing numbers plus an additional one should for a new number, if this new number isn't filled in by the user then it's just ignore and not saved in the database. I also want to achieve similar with Email.
When landing on the /people/:id/edit page this blank field is being prematurely validated and producing visible errors on the form before submitting. It doesn't do this when visiting /people/:id/new page; I'm assuming that this is because new_record? returns true for the user model on the new page? In reading a similar post I added on: :save as a parameter to validates on the Phone model although this just allowed blank records into the database, perhaps because this isn't relevant when the user model is saving the record?
class Person < ActiveRecord::Base
belongs_to :company
has_many :phones, :as => :phoneable
has_many :emails, :as => :emailable
has_many :addresses, :as => :addressable
attr_accessible :first_name, :job_title, :last_name, :prefix, :phones_attributes, :emails_attributes, :addresses_attributes, :company_id
accepts_nested_attributes_for :phones, allow_destroy: true, reject_if: proc { |attributes| attributes['number'].blank? }
accepts_nested_attributes_for :emails, allow_destroy: true, reject_if: proc { |attributes| attributes['email'].blank? }
accepts_nested_attributes_for :addresses, allow_destroy: true, reject_if: :all_blank
validates :first_name, :last_name, presence: true
def to_s
"#{first_name} #{last_name}"
end
end
class Phone < ActiveRecord::Base
belongs_to :phoneable, polymorphic: true
attr_accessible :number, :phone_type
validates :number, :phone_type, presence: true, on: :save # as suggested in a similar post, just allows blank records into database.
def to_s
"#{phone_type}: #{number}"
end
end
With both the new and edit controller I'm creating a new instance of each of these models so that they show up on the form. #person is loaded in the controller using load_and_authorize_resource as part of cancan.
def new
#person.phones << Phone.new
#person.emails << Email.new
end
Here is the partial view for the form:
<%= simple_form_for #person, :html => { :class => 'form-horizontal' } do |f| %>
<fieldset id="<%= controller.action_name.capitalize %>_person">
<legend><%= controller.action_name.capitalize %> Person</legend>
<%= f.input :prefix %>
<%= f.input :first_name %>
<%= f.input :last_name %>
<%= f.input :job_title %>
<%= f.association :company, :prompt => "Select associated company..." %>
<%= f.simple_fields_for :phones do |phone| %>
<%= phone.input :phone_type, :collection => %w(Work Home Mobile Fax Other), :default => "Work" %>
<%= phone.input :number %>
<% end %>
<%= f.simple_fields_for :emails do |email| %>
<%= email.input :email_type, :collection => %w(Work Home Other), :default => "Work" %>
<%= email.input :email %>
<% end %>
<div class="form-actions">
<%= f.submit nil, :class => 'btn btn-primary' %>
<%= link_to t('.cancel', :default => t("helpers.links.cancel")),
people_path, :class => 'btn' %>
</div>
</fieldset>
<% end %>
Many thanks for any help in advance :-)

Simple form issue with Rails 3

I've been trying recently to show a list of the fields modified with success on submitting a form. The only problem is that my form (I use simple form) doesn't show the errors when there are some and the form can't be submitted.
Here's my code simplified :
def update
#wizard.assign_attributes(params[:wizard])
# Get changed attributes
if #wizard.save
# Set the success flash with fields modified
redirect_to #wizard
else
#title = "Edition du profil"
render 'edit'
end
end
The view :
<%= simple_form_for #wizard do |f| %>
<%= f.input :email %>
<%= f.input :story %>
<%= f.submit "Modifier", :class => "btn success small" %>
<% end %>
The model :
class Wizard < ActiveRecord::Base
has_secure_password
attr_accessible :email, :story, :password, :password_confirmation, :password_digest
serialize :ranks, Array
validates_presence_of :email, :first_name, :last_name, :gender, :story
validates_presence_of :password, :password_confirmation, :unless => Proc.new { |w| w.password_digest.present? }
# Other validations here
has_one :subject, :foreign_key => "teacher_id"
ROLES = %w[teacher]
scope :with_role, lambda { |role| {:conditions => "roles_bitmask & #{2**ROLES.index(role.to_s)} > 0"} }
# Other functions here
end
Has anyone an idea ?
Thank you in advance !
It has probably something to do with how you overwrote AR. I remember some plugin getting in trouble with assign_attributes. Meanwhile you can try :
#wizard.assign_attributes(params[:wizard], :without_protection => true)
If that works it will at least narrow down the problem to mass assignment.
you perhaps missing this part in edit/new view.Where #wizard is your model_name.
Write this piece of code in the form tag.
<% if #wizard.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#wizard.errors.count, "error") %> prohibited this task from being saved:</h2>
<ul>
<% #wizard.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>