HABTM association with Strong Parameters is not saving user in Rails 4 - ruby-on-rails-4

User model:
has_and_belongs_to_many :events
Event model:
has_and_belongs_to_many :users
Users controller:
params.require(:user).permit(:role, {:event_ids => []})
Events controller:
params.require(:event).permit(:subject, :location, :date, :time, :all_day, :reminder, :notes, {:users_ids => []})
My form:
<%= simple_form_for(#event) do |f| %>
<%= f.input :subject %>
<%= f.input :location %>
<%= f.input :date %>
<%= f.input :time %>
<%= f.association :users %>
<%= f.input :all_day %>
<%= f.input :reminder %>
<%= f.input :notes %>
<%= f.button :submit, :class =>"btn btn-default" %>
<% end %>
I want to be able to choose a user from a list and save that user to the database. But I am getting the following message in my console when I try to create a new Event:
Unpermitted parameters: user_ids
Do I have my setup incorrect? Am I not passing in the correct instance variables to the form?

Ugh...details details!
How it was previously:
params.require(:event).permit(:subject, :location, :date, :time, :all_day, :reminder, :notes, {:users_ids => []})
How it should be:
params.require(:event).permit(:subject, :location, :date, :time, :all_day, :reminder, :notes, {:user_ids => []})
Notice that :users_ids should actually be :user_ids!

Or you can simply use shorthand syntax like this.
params.require(:event).permit(:subject, :location, :date, :time, :all_day, :reminder, :notes, user_ids: [])
Notice: user_ids: [] instead of {:user_ids => []}

Attribute from simple_form: user_ids
Symbol in #permit: users_ids
You've added an s, remove that and you should be good to go as far as I can tell.

In my case I had a Rails 3 installation before. I upgraded to Rails 4. The select just passed a string, not an association. Thus the syntax proposed did not work. I simply had to allow user_ids. I.e.:
params.require(:event).permit(:subject, :location, :date, :time, :all_day, :reminder, :notes, :user_ids)
It seems Rails 4 changed the behavior.

Related

Activeadmin Nested Attributes

I have models products and gallery with has_many belongs_to relation, I'm implementing nested_attributes feature, Problem here is: When I click on add gallery two inner forms get created instead of one, as shown in below image:
CODE
form do |f|
f.inputs "Product" do
f.input :title, :required => true
f.input :description
f.input :price
f.input :display_image
f .input :product_detail, :hint => "Upload PDF file"
f.input :category
end
f.inputs 'Product Gallery' do
f.has_many :galleries, allow_destroy: true, new_record: 'Add Gallery' do |c|
c.input :image, :hint => c.template.image_tag(c.object.image.url(:thumb))
end
end
f.inputs 'Product Specification' do
f.has_many :specifications, allow_destroy: true, new_record: true do |c|
c.input :specification_label
c.input :specification_details
end
end
f.actions
end
I need help on this. I'm not able to solve this!!, any help would be appreciable.
Try this.
f.inputs 'Product Gallery' do
f.has_many :galleries do |c|
c.input :image, :hint => c.template.image_tag(c.object.image.url(:thumb))
c.input :_destroy, :as => :boolean
end
end
Hope this will work for you.

Rails nested_form Invalid association. Make sure that accepts_nested_attributes_for is used for assoctiation

I am using rails 4.0.4 with nested_form 0.3.2 to build an app that allows users to organize movies in lists.
I have these main models, a List model (I've excluded things such as validations):
class List < ActiveRecord::Base
belongs_to :user
has_many :list_movie_pairs
has_many :movies, :through => :list_movie_pairs
accepts_nested_attributes_for :list_movie_pairs, :allow_destroy => true
accepts_nested_attributes_for :movies, :allow_destroy => true
end
A Movie model:
class Movie < ActiveRecord::Base
has_many :list_movie_pairs
has_many :lists, :through => :list_movie_pairs
has_many :reviews
end
A ListMoviePair model for the many-to-many relationship:
class ListMoviePair < ActiveRecord::Base
belongs_to :list
belongs_to :movie
validates_presence_of :list_id, :movie_id
validates_uniqueness_of :movie_id, scope: :list_id
end
I am trying to build an interface for the user to add movies to a created list. These routes serve my purpose:
get "/users/:username/lists/:id/add" => "lists#add_movies", :as => :user_list_list_movie_pairs
post "/users/:username/lists/:id/add" => "lists#submit_movies"
These are the classes in my ListsController that should make this possible:
def add_movies
#pair = list.list_movie_pairs.new # "list" is a helper that returns the current list
end
def submit_movies
#list = current_user.lists.find(params[:id])
#pair = #list.list_movie_pairs.new(pair_params)
if #pair.save
redirect_to user_list_path(current_user.username, #list)
else
render :add_movies
end
end
def list_params
params.require(:list).permit(:name, :description, :private, \
list_movie_pairs_attributes: [:id, :list_id, :movie_id, :_destroy], \
movies_attributes: [:id, :title, :_destroy])
end
And this is the form in my view
<%= nested_form_for [current_user, list, #pair] do |f| %>
<%= f.fields_for :movies do |movie_form| %>
<%= movie_form.text_field :title %>
<%= movie_form.link_to_remove "Remove movie" %>
<% end %>
<%= f.link_to_add "Add movie", :movies %>
<% end %>
I get this error when trying to access the view:
Invalid association. Make sure that accepts_nested_attributes_for is used for :movies association.
Which pops at this line:
<%= f.link_to_add "Add movie", :movies %>
Note 1: I am using the Devise gem for users, hence the "current_user" helper;
Note 2: I have tried using both "movies" and "list_movie_pairs", i.e.:
f.fields for :list_movie_pairs
and
f.link_to_add "Add movie", :list_movie_pairs
in my view, neither association seems to work
Your code in the view should be like this
<%= nested_form_for [current_user, list, #pair] do |f| %>
<%= f.fields_for :movies do |movie_form| %>
<%= movie_form.text_field :title %>
<%= movie_form.link_to_remove "Remove movie" %>
<%= movie_form.link_to_add "Add movie", :movies %> #note the change here
<% end %>
<% end %>
Update
There are several issues in your code
1.In your List model,this line is not required
accepts_nested_attributes_for :movies, :allow_destroy => true #not requied
2.In your ListsController,you have this line
#pair = #list.list_movie_pairs.new(pair_params)
It should be
#pair = #list.list_movie_pairs.new(list_params) because you have list_params method not pair_params

Allowing has_many multiselect with rails 4 & active admin

When using activeadmin with rails 4, permit_params has to be set to allow fields to be saved.
simple fields are working, however a multi select for a has_many field is silently ignored. How can i set permit_params for that field?
so home has_many providers, and my admin looks like this:
ActiveAdmin.register Home do
permit_params :title, :intro, :providers, :providers_attributes => [:id]
menu :parent => "Content" , :label => "Home Page"
form do |f|
f.semantic_errors *f.object.errors.keys
f.inputs do
f.input :title
f.input :intro
f.input :providers
end
f.actions
end
index do
column :link
actions
end
end
I don't know if they changed it with Rails 4 .. but I've always done it this way
form do |f|
f.semantic_errors *f.object.errors.keys
f.inputs do
f.input :title
f.input :intro
end
f.has_many :providers do |pf|
pf.input :title #or whatever attributes you have there
pf.input :_destroy, :as => :boolean, :label => "Delete" if !pf.object.nil?
end
f.actions
end
And in your model.rb you should have something similar to
attr_accessible :providers_attributes
has_many :providers
accepts_nested_attributes_for :providers, :allow_destroy => true
Let me know if that helps !

Carmen Rails- Devise - Rails 4: issue with country_code

I'm new and I have a basic question
When I create a new user with devise using carmen-rails with Rails 4, country_code and states_code don't pass
Both country_code and state_code are permitted
Here are my codes:
in Devise registration:
= f.label :country_code
= f.country_select :country_code, {priority: %w(US CA), prompt: "Please select your country"}, :style => "width:170px;float:left;font-size:14px;", :type => 'text'
= f.label :state_code
= render partial: '/users/subregion_select', locals: {parent_region: f.object.country_code}
in users/ subregionselect:
<% parent_region ||= params[:parent_region] %> <% unless parent_region.nil? %>
<% country = Carmen::Country.coded(parent_region) %>
<% end %>
<% if country.nil? %>
Please select a country above
<% elsif country.subregions? %>
<%= f.subregion_select(:user, :state_code, parent_region) %>
<% else %>
<%= text_field(:user, :state_code) %>
<% end %>
in users.js.coffee
$('select#user_country_code').change (event) ->
select_wrapper = $('#user_state_code_wrapper')
$('select', select_wrapper).attr('disabled', true)
country_code = $(this).val()
url = "/users/subregion_options?parent_region=#{country_code}"
select_wrapper.load(url)
in routes.rb
get '/users/subregion_options' => 'users#subregion_options'
in users controllers:
def subregion_options
render partial: 'subregion_select'
end
On my console, all the data are saved except for country_code: nil (even though I put United States) and the states_code is not generated when I select a country.
Is that because I should need to use Formstatic?
Thank you for your help :)
Looks like an issue with Devise params sanitation.
#application_controller
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) { |u|
u.permit(:email,
:password,
:password_confirmation,
:first_name,
:last_name,
:street1,
:street2,
:city,
:state,
:zipcode,
:country_code)
}
Give that a try!
Cheers

Strong Params won't save nested has_many

I'm using Rails 4, and with it Strong Params. For some reason I can't save my nested parameters. I've looked at how to do it and even might've gotten it working in a different Rails app before. I know to permit draft_players_attributes and list all of it's accepted params in an array.
Here are the params coming in:
Started POST "/draft_groups" for 127.0.0.1 at 2013-12-04 22:55:32 -0500
User Load (1.6ms) SELECT "users".* FROM "users" WHERE "users"."id" = 1 ORDER BY "users"."id" ASC LIMIT 1
Processing by DraftGroupsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"2W3bs1U7+CEzsWl+jDi3xZi5CyldYeZXCz3KU6c+sYY=", "draft_group"=>{"name"=>"Best Group Ever", "draft_id"=>"3", "captain_id"=>"1"}, "draft_players"=>{"player_id"=>"1", "position"=>"Handler", "rating"=>"10", "info"=>"Smart"}, "commit"=>"Update"}
(0.3ms) BEGIN
SQL (2.6ms) INSERT INTO "draft_groups" ("captain_id", "created_at", "draft_id", "name", "updated_at") VALUES ($1, $2, $3, $4, $5) RETURNING "id" [["captain_id", 1], ["created_at", Thu, 05 Dec 2013 03:55:32 UTC +00:00], ["draft_id", 3], ["name", "Best Group Ever"], ["updated_at", Thu, 05 Dec 2013 03:55:32 UTC +00:00]]
(0.5ms) COMMIT
Redirected to http://lvh.me:3000/drafts/3
Completed 302 Found in 8ms (ActiveRecord: 3.3ms)
Here's my controller:
class DraftGroupsController < ApplicationController
def create
#draft_group = DraftGroup.create(draft_group_params)
redirect_to :back, :notice => "Draft Group successfully created."
end
def update
#draft_group = DraftGroup.find(params[:id])
#draft_group.update(draft_group_params)
redirect_to :back, :notice => "Draft Group successfully updated."
end
def destroy
#draft_group = DraftGroup.find(params[:id]).destroy
redirect_to :back, :notice => "Draft Group successfully destroyed."
end
private
def draft_group_params
params.require(:draft_group).permit(:name,
:draft_id,
:captain_id,
draft_players_attributes:
[
:_destroy,
:id,
:player_id,
:position,
:rating,
:info
]
)
end
end
And my models:
class DraftGroup < ActiveRecord::Base
has_many :draft_players, :dependent => :destroy
belongs_to :captain, :class_name => "User"
accepts_nested_attributes_for :draft_players
end
class DraftPlayer < ActiveRecord::Base
belongs_to :draft_group
belongs_to :player, class_name: "User"
end
And my view:
<% #groups.each do |group| %>
<div class="span6 group">
<h4><%= "#{group.name}" %></h4>
<%= simple_form_for(group, :html => { :class => "auto-width" } ) do |f| %>
<div class="row">
<%= f.input :name, :label => false %>
<%= f.hidden_field :draft_id %>
<%= f.hidden_field :captain_id %>
</div>
<table>
<tr>
<th>Player</th>
<th>Position</th>
<th>Rating</th>
<th>Info</th>
</tr>
<%= simple_fields_for :draft_players do |player| %>
<tr>
<td><%= player.input :player_id, :label => false, :as => :select, :collection => User.active %></td>
<td><%= player.input :position, :label => false %></td>
<td><%= player.input :rating, :label => false %></td>
<td><%= player.input :info, :label => false %></td>
</tr>
<% end %>
</table>
<div class="row">
<%= f.button :submit, "Update", :class => "btn btn-primary" %>
</div>
<% end %>
</div>
<% end %>
EDIT: Added view code, and will probably take table out, shifting it into using bootstraps columns layout.
To make sure parameters are nested correctly (and so Rails can understand nested model attributes) you should call f.simple_fields_for(:draft_players) rather than simple_fields_for(:draft_players).
In other words, call simple_fields_for on the FormBuilder object f rather than calling the helper directly.
That way Rails can look up and validate the nested association correctly.