ActiveModel::ForbiddenAttributesError when executing a build inside an update action - ruby-on-rails-4

I am getting a pesky ActiveModel::ForbiddenAttributesError, and I can't find how to fix it.
I was following this guide:
https://rbudiharso.wordpress.com/2010/07/07/dynamically-add-and-remove-input-field-in-rails-without-javascript/
and everything works great except when I am updating the record.
My controller:
if params[:add_item]
# rebuild the baixa_itens attributes that doesn't have an id
unless params[:baixa][:baixa_itens_attributes].blank?
for attribute in params[:baixa][:baixa_itens_attributes]
#baixa.baixa_itens.build(attribute.last.except(:_destroy)) unless attribute.last.has_key?(:id)
end
(...)
# Never trust parameters from the scary internet, only allow the white list through.
def baixa_params
params.require(:baixa).permit(:prontuarios_id, :data, :profissional_id, :comentario, baixa_itens_attributes: [ :id, :item_id, :quantidade, :preco, :_destroy ])
end
end
When I got my crash, I tested it in the console:
>> attribute
=> ["1", {"item_id"=>"3", "quantidade"=>"1", "preco"=>"1", "_destroy"=>"0"}]
>> attribute.last.except(:_destroy)
=> {"item_id"=>"3", "quantidade"=>"1", "preco"=>"1"}
>> #baixa.baixa_itens.build(attribute.last.except(:_destroy))
!! #<ActiveModel::ForbiddenAttributesError: ActiveModel::ForbiddenAttributesError>
But if I try to make this build MANUALLY, it works:
>> #baixa.baixa_itens.build({"item_id"=>"3", "quantidade"=>"1", "preco"=>"1"})
=> #<BaixaItem id: nil, baixa_id: 6, item_id: 3, quantidade: 1, preco: #<BigDecimal:7ff97147b6f8,'0.1E1',9(18)>, created_at: nil, updated_at: nil>
>>
What am I missing?

I workaround this problem doing
for attribute in params[:baixa][:baixa_itens_attributes].permit!
in my controler (not using ! would give me error: "Unpermitted parameters: 0, 1", which i cant understand)
I still wish a better solution.

Related

How to test parameterized scope method using rspec(v3.4.1) in rails(v4.2.5)?

Model:
scope :recent, ->(n) {where(:created_at => 6.months.ago..Time.now).order('created_at DESC').limit(n)}
I would do something like this in Rspec:
before(:each) do
#song = double(Song,id: 1, name: "Vegan artisan.", album_id: 1, artist_id: 20, created_at: "2016-03-04 13:15:36", updated_at: "2016-03-04 13:15:36")
end
it "should return the recent most songs within range" do
Song.stub_chain(:where,:order,:limit).with(created_at:6.months.ago..Time.now).with('created_at DESC').with(2).and_return([#song,#song])
Song.recent.should == [#song,#song]
end
The above case is failing , giving the below mentioned error:
ArgumentError:
wrong number of arguments (0 for 1)
I tried different approaches, but still hard luck. Any help on this would be appreciated. Thanks in advance!!
recent scope requires you to pass a parameter that limits the search result, thus you need to change this line appropriately:
Song.recent(2).should eq([#song,#song])
or
expect(Song.recent(2)).to match_array([#song,#song])

shoulda validate_inclusion_of not working

Recently upgraded a codebase to rails4 along with gems, now we're getting this error.
Failure/Error: it { is_expected.to ensure_inclusion_of(:usage).in_array(['Index', 'Slide', 'Body']).with_message("%{value} is not a valid usage") }
["Index", "Slide", "Body"] doesn't match array in validation
and here is the related model code
USAGES = ['Index', 'Slide', 'Body']
validates_inclusion_of :usage, :in => USAGES, :message => "%{value} is not a valid usage"
Is there something I'm missing? I don't understand why this is failing.
validate_inclusion_of uses allow_value internally. Admittedly, we should give you a better error message as to what's going on here, but you should be able to write the following tests to figure out what's happening:
it { should allow_value("Index").for(:usage) }
it { should allow_value("Slide").for(:usage) }
it { should allow_value("Body").for(:usage) }
it do
should_not allow_value("something else").
for(:usage).
with_message("%{value} is not a valid usage")
end
My guess is that shoulda-matchers isn't automatically interpolating the %{value} inside of your failure message. If this is true, then what I would do (after filing an issue) is extract the message to an i18n key, and then pass the name of the key to with_message instead.
worked for me -
expect { should validate_inclusion_of(:usage).in?(['a', 'b']) }
should try this -
validates :usage, inclusion: { :in => %w( Index Slide Body ), :message => "%{value} is not a valid usage" }

How to monkey patch enums in rails 4.1?

Say I have a class that has an enum
class Course < ActiveRecord::Base
enum status: { active: 1, in_progress: 2, disabled: 3, ... }
end
and I want to patch the enum functionality so I could do
Course.statuses.capitalize
which would return a list of all statuses - capitalized and without underscores.
I have tried a couple of things but nothing seems to be helping. Any ideas?
Thanks
Below is what I tried. My experience with monkey patching is limited so not really sure if I am on the correct path or not.
module ActiveRecord
module Enum
def capitalize
self.map{ |s| [s[0].capitalize, s[1]] }
end
end
end
I don't see the point of monkey patching this, because what you want already exists in Rails.
class Course < ActiveRecord::Base
enum status: { active: 1, in_progress: 2, disabled: 3 }
end
Course.statuses.transform_keys{|k| k.to_s.humanize}
# => {"Active": 1, "In progress": 2, "Disabled": 3}

How to Populate koGrid Groups Array

I have a koGrid configured as follows:
var myItemsGrid = {
data: myItems,
columnDefs: [
{ field: 'item.title', displayName: 'Title', cellTemplate: $("#cdfUrlCellTemplate").html() },
{ field: 'item.dueTimeUtc', displayName: 'Due', cellFormatter: formatDate, sortFn: sortDates },
{ field: 'id', displayName: 'Edit', cellTemplate: $("#editCellTemplate").html() }
],
showGroupPanel: true,
groups: ['item.title'],
showFilter: false,
canSelectRows: false
};
My problem is that the groups array, which I have tried to populate using the field name of one of the fields in my grid, causes the following error:
TypeError: Cannot read property 'isAggCol' of undefined
How should I be populating the groups array so that I can set up initial grouping for my grid?
I had the same problem and took a different approach by sending an event to the grid control to group by the first heading. Something like this:
jQuery("#symbolPickerView").find(".kgGroupIcon").first().click();
This works until there is some sort of patch generally available.
I ended up having to patch the koGrid script to get the initial grouping of columns to work.
If anyone else has the problem I'm happy to provide the patched script. I will look at making a pull request to get the fix into the koGrid repository after putting it through its paces a bit more.

Count an Attribute on a nested form?

Rails 3.2.12 and Ruby 1.9.3 and Haml
I would like to use the count of attribute to control the display of a 'link_to "remove"', but I am having problems with setting up the logic.
Following is some code from my form as it is currently:
.field
= codeline.label :name, "Units Alloc"
%br/
= codeline.text_field :units_alloc, :precision => 6, :scale => 2, :size => 10,
:class => "ui-state-default"
= codeline.hidden_field :_destroy
= link_to "remove", '#', class: "remove_fields"
this works well but I have the 'remove' link showing up and I would prefer it to only show if there are two :units_alloc attributes.
This is what I tried:
.field
= codeline.label :name, "Units Alloc"
%br/
= codeline.text_field :units_alloc, :precision => 6, :scale => 2, :size => 10,
:class => "ui-state-default"
- if :units_alloc.count > 1
= codeline.hidden_field :_destroy
= link_to "remove", '#', class: "remove_fields"
and here is my error:
NoMethodError in Contracts#new
Showing /home/tom/rails_projects/tracking/app/views/contracts
/_codeline_fields.html.haml where line #9 raised:
undefined method `count' for :units_alloc:Symbol
if I use units_alloc in the argument instead of the symbol, I still get an error:
NameError in Contracts#new
Showing /home/tom/rails_projects/tracking/app/views/contracts
/_codeline_fields.html.haml where line #9 raised:
undefined local variable or method `units_alloc' for
#<#<Class:0xadbde90>:0xa8956e8>
I tried to use 'codeline.units_alloc' but this did not work and the same error was flagged.
Any suggestions, or pointers to help me resolve this issue?
Thanks.
Solution: Thanks to James Scott Jr.
app/controller/contracts_controller.rb
def New
#show_remove = false
....
....
end
app/views/contracts/_codelines_fields.html.haml
.field
= codeline.label :name, "Units Alloc"
%br/
= codeline.text_field :units_alloc, :precision => 6, :scale => 2, :size => 10,
:class => "ui-state-default"
- if #show_remove
= codeline.hidden_field :_destroy
= link_to "remove", '#', class: "remove_fields"
- else
- #show_remove = true
And that did it ... the remove button only shows in the second and subsequent row of attributes.
By the time you're in the form (partial), codeline doesn't refer to an instance the instance of Codeline that the form (partial) is for, but an instance of an ActionView::Helpers::FormBuilder that simple knows how to associate information the the instance of Codeline. You knew that because in the first line of the partial, you have codeline.object.build_code.
So, if you want to access the information about the units_alloc associated, you would access them with codeline.object.units_alloc. That will give you your data for your conditional.
I would just like to add that if the purpose of your anchor tag is to remove elements from a form list using some javacscript, you might be using the wrong control for it. Anchor tags are not form elements, they should point to resources/content and are not there to be used as animation/client side behaviour triggers. According to the use case you describe, an input tag type=button would be a much more appropriated element for what you seem to be trying to achieve.