RoR 4 unpermitted parameter - ruby-on-rails-4

I am creating a sign up page for users and accounts. Each account will be accessible to multiple users, but only 1 user will be the account owner.
# account.rb
class Account < ActiveRecord::Base
belongs_to :owner, class_name: "User", foreign_key: "owner_id"
accepts_nested_attributes_for :owner
end
# user.rb
class User < ActiveRecord::Base
has_secure_password
end
# accounts_controller.rb
class AccountsController < ApplicationController
def new
#account = Account.new
#account.build_owner
end
def create
#account = Account.new(account_params)
if #account.save
env["warden"].set_user(#account.owner, scope: :user)
env["warden"].set_user(#account, scope: :account)
flash[:success] = "Your account has been successfully created."
redirect_to root_url(subdomain: #account.subdomain)
else
flash[:error] = "Sorry, your account could not be created."
render :new
end
end
private
def account_params
params.require(:account).permit(:account_name, :subdomain,
{:owner => [:username, :password, :password_confirmation]})
end
end
I have also tried ":owner_attributes" as the key for the nested attributes hash.
The sign up page is pretty straightforward:
# /views/accounts/new.html.erb
<h2>Sign Up</h2>
<%= form_for(#account) do |account| %>
<%= account.error_messages %>
<p>
<%= account.label :account_name %><br>
<%= account.text_field :account_name %>
</p>
<p>
<%= account.label :subdomain %><br>
<%= account.text_field :subdomain %>
</p>
<%= account.fields_for #account.owner do |owner| %>
<p>
<%= owner.label :username %><br>
<%= owner.text_field :username %>
</p>
<p>
<%= owner.label :password %><br>
<%= owner.password_field :password %>
</p>
<p>
<%= owner.label :password_confirmation %><br>
<%= owner.password_field :password_confirmation %>
</p>
<% end %>
<%= account.submit %>
<% end %>
When running tests on this code, the server output indicates that there is an unpermitted parameter "user", which causes the account creation to fail:
Started GET "/sign_up" for 127.0.0.1 at 2015-07-10 14:41:26 +0000
Processing by AccountsController#new as HTML
Rendered accounts/new.html.erb within layouts/application (51.7ms)
Completed 200 OK in 127ms (Views: 57.7ms | ActiveRecord: 31.2ms)
Started POST "/accounts" for 127.0.0.1 at 2015-07-10 14:41:26 +0000
Processing by AccountsController#create as HTML
Parameters: {"utf8"=>"✓", "account"=>{"account_name"=>"Test Firm", "subdomain"=>"test", "user"=>{"username"=>"User1", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]"}}, "commit"=>"Create Account"}
Unpermitted parameter: user
For informational purposes, here is the test code that is being used:
RSpec.feature "Accounts", type: :feature do
owner = FactoryGirl.attributes_for(:user)
scenario "creating an account" do
visit root_path
click_link "Sign Up"
fill_in "Account name", :with => "Test Firm"
fill_in "Subdomain", :with => "test"
fill_in "Username", :with => owner[:username]
fill_in "Password", :with => owner[:password]
fill_in "Password confirmation", :with => owner[:password_confirmation]
click_button "Create Account"
success_message = "Your account has been successfully created."
expect(page).to have_content(success_message)
expect(page).to have_content("Signed in as #{owner[:username].downcase}")
expect(page.current_url).to eq("http://test.example.com/")
end
end
I'm confused why a parameter of "user" is being sent (and rejected) since both the model and controller are using the "owner" name? Thanks for any insight.

Related

Act-As-Taggable not saving to database

Hi I am attempting to use act_as_taggable ruby gem and have followed the github guide and a recent tutorial as well as checked stack overflow for advice. My code all seems to be correct but when I attempt to save tags via my form partial or via the rails console they do not save to the database.
Below relevant code excerpts.
Thanks in advance for any help!
post.rb
class Post < ActiveRecord::Base
acts_as_taggable
acts_as_taggable_on :tags
validates :title, presence: true, length: {minimum: 5}
validates :body, presence: true
extend FriendlyId
friendly_id :title, use: :slugged
end
post_controller.rb
class PostsController < ApplicationController
before_action :find_post, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!, except: [:index, :show]
def index
if params[:tag].present?
#posts = Post.tagged_with(params[:tag]).paginate(:page => params[:page], :per_page => 10)
else
#posts = Post.all.order('created_at DESC').paginate(page: params[:page], per_page: 10)
end
end
def new
#post = Post.new
end
def show
end
def create
#post = Post.new(post_params)
if #post.save
redirect_to #post, notice: "Article succesfully saved!"
else
render 'new', notice: "Try Again. I was unable to save your post."
end
end
def edit
end
def update
if #post.update(params[:post].permit(:title, :body))
redirect_to #post, notice: "Article succesfully edited!"
else
render 'edit'
end
end
def destroy
#post.destroy
redirect_to posts_path
end
private
def post_params
params.require(:post).permit(:title, :body, :slug, :tag_list => [])
end
def find_post
#post = Post.friendly.find(params[:id])
end
end
routes.rb
Rails.application.routes.draw do
devise_for :users, :skip => :registrations
root 'pages#home'
resources :posts
resources :portfolios
get 'tags/:tag', to: 'posts#index', as: :tag
end
_form.html.erb
<%= form_for #post do |f| %>
<% if #post.errors.any? %>
<div id="errors">
<h2><%= pluralize(#post.errors.count, "error") %> prevented this post from saving:</h2>
<ul>
<% #post.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<%= f.label :title %><br>
<%= f.text_field :title, class: 'form-control form-control-lg' %><br>
<br>
<%= f.label :body %><br>
<%= f.text_area :body, class: 'form-control form-control-lg', :rows => "10" %><br>
<br>
<%= f.label :tag_list, "Tags (separated by commas)" %>
<%= f.text_field :tag_list, class: 'form-control' %>
<br>
<%= f.submit %>
<% end %>
excerpt from show.html.erb
<% #post.tags.any? %>
<% #post.tags.each do |tag| %>
<li><a href="#">
<%= link_to tag.name, tag_path(tag.name) %>
</a></li>
<% end %>
Params log for _form as requested by Pavan:
Started PATCH "/posts/my-third-post-with-tags" for ::1 at 2015-09-23 15:56:36 +1000
Processing by PostsController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"GwLMImKSDyhPt77nI+fhIkF4QVsFxMen851wjcVorrxOCdU+TcRKIZv1im4/oNx7DERYCI91vE9YDjvSda7MAg==", "post"=>{"title"=>"My third post with tags", "body"=>"to update your local repository to the newest commit, execute\r\ngit pull\r\nin your working directory to fetch and merge remote changes.\r\nto merge another branch into your active branch (e.g. master), use\r\ngit merge <branch>\r\nin both cases git tries to auto-merge changes. Unfortunately, this is not always possible and results in conflicts. You are responsible to merge those conflicts manually by editing the files shown by git. After changing, you need to mark them as merged with\r\ngit add <filename>\r\nbefore merging changes, you can also preview them by using\r\ngit diff <source_branch> <target_branch>", "tag_list"=>"tag, css"}, "commit"=>"Update Post", "id"=>"my-third-post-with-tags"}
Post Load (0.1ms) SELECT "posts".* FROM "posts" WHERE "posts"."slug" = ? ORDER BY "posts"."id" ASC LIMIT 1 [["slug", "my-third-post-with-tags"]]
User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? ORDER BY "users"."id" ASC LIMIT 1 [["id", 1]]
Unpermitted parameter: tag_list
(0.0ms) begin transaction
(0.0ms) commit transaction
Redirected to http://localhost:3000/posts/my-third-post-with-tags
Completed 302 Found in 4ms (ActiveRecord: 0.3ms)
Started GET "/posts/my-third-post-with-tags" for ::1 at 2015-09-23 15:56:36 +1000
Processing by PostsController#show as HTML
Parameters: {"id"=>"my-third-post-with-tags"}
Post Load (0.1ms) SELECT "posts".* FROM "posts" WHERE "posts"."slug" = ? ORDER BY "posts"."id" ASC LIMIT 1 [["slug", "my-third-post-with-tags"]]
ActsAsTaggableOn::Tag Exists (0.1ms) SELECT 1 AS one FROM "tags" INNER JOIN "taggings" ON "tags"."id" = "taggings"."tag_id" WHERE "taggings"."taggable_id" = ? AND "taggings"."taggable_type" = ? AND "taggings"."context" = ? LIMIT 1 [["taggable_id", 2], ["taggable_type", "Post"], ["context", "tags"]]
ActsAsTaggableOn::Tag Load (0.1ms) SELECT "tags".* FROM "tags" INNER JOIN "taggings" ON "tags"."id" = "taggings"."tag_id" WHERE "taggings"."taggable_id" = ? AND "taggings"."taggable_type" = ? AND "taggings"."context" = ? [["taggable_id", 2], ["taggable_type", "Post"], ["context", "tags"]]
Rendered posts/show.html.erb within layouts/application (3.2ms)
Rendered layouts/_header.html.erb (496.3ms)
Rendered devise/shared/_links.html.erb (0.2ms)
Rendered devise/sessions/_new.html.erb (4.6ms)
Rendered layouts/_slideoutpanels.html.erb (460.2ms)
Rendered layouts/_footer.html.erb (0.0ms)
Completed 200 OK in 1486ms (Views: 1484.3ms | ActiveRecord: 0.2ms)
Your error is from PostsController#update as HTML
In controller you don;t permit tag_list
#post.update(params[:post].permit(:title, :body))

Trying to add delete button in order to delete users

I am following along with Michael Hartls tutorial and I am trying to add the destroy action in order to delete users as admin. However, the link is not displaying under users name. I am also using Devise, not sure if that matters. Any help is greatly appreciated. Thanks
Controller/users
def destroy
User.find(params[:id]).destroy
flash[:success] = "User deleted."
redirect_to users_path
end
def admin_user
redirect_to(root_url) unless current_user.admin?
end
_users.html
<li>
<class= "round-image-50"><%= image_tag(current_user.avatar.url(:thumb)) %>
<%= link_to user.name, user %>
<% if current_user.admin? && !current_user?(user) %>
<%= link_to "delete", user, method: :delete, data: { confirm: "You sure?" } %>
<% end %>
</li>
Routes
devise_for :admins
devise_for :users
resources :posts
resources :users
get "users/show"
get 'feed', to: 'posts#index', as: :feed
get "about" => "pages#about"
root "pages#home"
match 'users/:id' => 'users#show', via: :get
Migration
class AddAdminToUsers < ActiveRecord::Migration
def self.up
add_column :users, :admin, :boolean, :default => false
end
def self.down
remove_column :users, :admin
end
end
I was able to figure it out. The below code needed to go on my user index page instead not the _user.html page. Thank you for your help #Pavan
<% if current_user.admin? && !current_user?(user) %>
<%= link_to "delete", user, method: :delete, data: { confirm: "You sure?" } %>
<% end %>

Unpermitted parameters error for Carrierwave in Rails 4

Ok, really stuck here. Have read through all documentation and SO but can't figure out what's going on. Simple case of allowing a User to update their profile by uploading a file using Carrierwave. My log keeps showing an
Unpermitted parameters: avatar
error.
My view:
<%= form_for current_user, html: { multipart: true } do |f| %>
<%= f.file_field :avatar %>
<%= f.submit "Update Profile", remote: true, class: "btn btn-default" %>
<% end %>
my controller:
class UsersController < ApplicationController
def update
current_user.update_attributes(user_params)
respond_to do |format|
format.html { render 'show'}
format.js {}
end
end
def user_params
params.fetch(:user, {}).permit(:id, :email, :username, :password, :password_hash, :avatar, projects_attributes: [:id, :user_id, :name])
end
end
my model
class User < ActiveRecord::Base
mount_uploader :avatar, AvatarUploader
end
have not touched the uploader file
class AvatarUploader < CarrierWave::Uploader::Base
storage :file
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
end
Seems pretty straightforward, why am I getting this error?
UPDATE: Server Log:
Started PATCH "/users/91" for 127.0.0.1 at 2014-04-03 11:38:22 -0700
Processing by UsersController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"+cLF9iPcZSL3Lc87o7/gPZjwgc9ySr7dOKmm6Yxhbno=", "user"=>{"username"=>"s+ Index", "avatar_attributes"=>#<ActionDispatch::Http::UploadedFile:0x007f81db4060c8 #tempfile=#<Tempfile:/var/folders/xl/wpdby5jn59q7hy9w0v2nv8xc0000gn/T/RackMultipart20140403-3890-127m17g>, #original_filename="cover.jpg", #content_type="image/jpeg", #headers="Content-Disposition: form-data; name=\"user[avatar_attributes]\"; filename=\"cover.jpg\"\r\nContent-Type: image/jpeg\r\n">}, "commit"=>"Update Profile", "id"=>"91"}
[1m[35mUser Load (0.4ms)[0m SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 91]]
Unpermitted parameters: avatar
Just had the same problem,
I had a problem because I had fallowed documentation like so:
<%= f.file_field :avatar, multiple: true %>
Changed it to:
<%= form_for #user, multiple: true do |f| %>
in controller:
params.require(:user).permit(:avatar,...)

Rails 4 multiple image or file upload using carrierwave

How can I upload multiple images from a file selection window using Rails 4 and CarrierWave? I have a post_controller and post_attachments model. How can I do this?
Can someone provide an example? Is there a simple approach to this?
This is solution to upload multiple images using carrierwave in rails 4 from scratch
Or you can find working demo :
Multiple Attachment Rails 4
To do just follow these steps.
rails new multiple_image_upload_carrierwave
In gem file
gem 'carrierwave'
bundle install
rails generate uploader Avatar
Create post scaffold
rails generate scaffold post title:string
Create post_attachment scaffold
rails generate scaffold post_attachment post_id:integer avatar:string
rake db:migrate
In post.rb
class Post < ActiveRecord::Base
has_many :post_attachments
accepts_nested_attributes_for :post_attachments
end
In post_attachment.rb
class PostAttachment < ActiveRecord::Base
mount_uploader :avatar, AvatarUploader
belongs_to :post
end
In post_controller.rb
def show
#post_attachments = #post.post_attachments.all
end
def new
#post = Post.new
#post_attachment = #post.post_attachments.build
end
def create
#post = Post.new(post_params)
respond_to do |format|
if #post.save
params[:post_attachments]['avatar'].each do |a|
#post_attachment = #post.post_attachments.create!(:avatar => a)
end
format.html { redirect_to #post, notice: 'Post was successfully created.' }
else
format.html { render action: 'new' }
end
end
end
private
def post_params
params.require(:post).permit(:title, post_attachments_attributes: [:id, :post_id, :avatar])
end
In views/posts/_form.html.erb
<%= form_for(#post, :html => { :multipart => true }) do |f| %>
<div class="field">
<%= f.label :title %><br>
<%= f.text_field :title %>
</div>
<%= f.fields_for :post_attachments do |p| %>
<div class="field">
<%= p.label :avatar %><br>
<%= p.file_field :avatar, :multiple => true, name: "post_attachments[avatar][]" %>
</div>
<% end %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
To edit an attachment and list of attachment for any post.
In views/posts/show.html.erb
<p id="notice"><%= notice %></p>
<p>
<strong>Title:</strong>
<%= #post.title %>
</p>
<% #post_attachments.each do |p| %>
<%= image_tag p.avatar_url %>
<%= link_to "Edit Attachment", edit_post_attachment_path(p) %>
<% end %>
<%= link_to 'Edit', edit_post_path(#post) %> |
<%= link_to 'Back', posts_path %>
Update form to edit an attachment views/post_attachments/_form.html.erb
<%= image_tag #post_attachment.avatar %>
<%= form_for(#post_attachment) do |f| %>
<div class="field">
<%= f.label :avatar %><br>
<%= f.file_field :avatar %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Modify update method in post_attachment_controller.rb
def update
respond_to do |format|
if #post_attachment.update(post_attachment_params)
format.html { redirect_to #post_attachment.post, notice: 'Post attachment was successfully updated.' }
end
end
end
In rails 3 no need to define strong parameters and as you can define attribute_accessible in both the model and accept_nested_attribute to post model because attribute accessible is deprecated in rails 4.
For edit an attachment we cant modify all the attachments at a time. so we will replace attachment one by one, or you can modify as per your rule, Here I just show you how to update any attachment.
If we take a look at CarrierWave's documentation, this is actually very easy now.
https://github.com/carrierwaveuploader/carrierwave/blob/master/README.md#multiple-file-uploads
I will use Product as the model I want to add the pictures, as an example.
Get the master branch Carrierwave and add it to your Gemfile:
gem 'carrierwave', github:'carrierwaveuploader/carrierwave'
Create a column in the intended model to host an array of images:
rails generate migration AddPicturesToProducts pictures:json
Run the migration
bundle exec rake db:migrate
Add pictures to model Product
app/models/product.rb
class Product < ActiveRecord::Base
validates :name, presence: true
mount_uploaders :pictures, PictureUploader
end
Add pictures to strong params in ProductsController
app/controllers/products_controller.rb
def product_params
params.require(:product).permit(:name, pictures: [])
end
Allow your form to accept multiple pictures
app/views/products/new.html.erb
# notice 'html: { multipart: true }'
<%= form_for #product, html: { multipart: true } do |f| %>
<%= f.label :name %>
<%= f.text_field :name %>
# notice 'multiple: true'
<%= f.label :pictures %>
<%= f.file_field :pictures, multiple: true, accept: "image/jpeg, image/jpg, image/gif, image/png" %>
<%= f.submit "Submit" %>
<% end %>
In your views, you can reference the images parsing the pictures array:
#product.pictures[1].url
If you choose several images from a folder, the order will be the exact order you are taking them from top to bottom.
Some minor additions to the SSR answer:
accepts_nested_attributes_for does not require you to change the parent object's controller. So if to correct
name: "post_attachments[avatar][]"
to
name: "post[post_attachments_attributes][][avatar]"
then all these controller changes like these become redundant:
params[:post_attachments]['avatar'].each do |a|
#post_attachment = #post.post_attachments.create!(:avatar => a)
end
Also you should add PostAttachment.new to the parent object form:
In views/posts/_form.html.erb
<%= f.fields_for :post_attachments, PostAttachment.new do |ff| %>
<div class="field">
<%= ff.label :avatar %><br>
<%= ff.file_field :avatar, :multiple => true, name: "post[post_attachments_attributes][][avatar]" %>
</div>
<% end %>
This would make redundant this change in the parent's controller:
#post_attachment = #post.post_attachments.build
For more info see Rails fields_for form not showing up, nested form
If you use Rails 5, then change Rails.application.config.active_record.belongs_to_required_by_default value from true to false (in config/initializers/new_framework_defaults.rb) due to a bug inside accepts_nested_attributes_for (otherwise accepts_nested_attributes_for won't generally work under Rails 5).
EDIT 1:
To add about destroy:
In models/post.rb
class Post < ApplicationRecord
...
accepts_nested_attributes_for :post_attachments, allow_destroy: true
end
In views/posts/_form.html.erb
<% f.object.post_attachments.each do |post_attachment| %>
<% if post_attachment.id %>
<%
post_attachments_delete_params =
{
post:
{
post_attachments_attributes: { id: post_attachment.id, _destroy: true }
}
}
%>
<%= link_to "Delete", post_path(f.object.id, post_attachments_delete_params), method: :patch, data: { confirm: 'Are you sure?' } %>
<br><br>
<% end %>
<% end %>
This way you simply do not need to have a child object's controller at all! I mean no any PostAttachmentsController is needed anymore. As for parent object's controller (PostController), you also almost don't change it - the only thing you change in there is the list of the whitelisted params (to include the child object-related params) like this:
def post_params
params.require(:post).permit(:title, :text,
post_attachments_attributes: ["avatar", "#original_filename", "#content_type", "#headers", "_destroy", "id"])
end
That's why the accepts_nested_attributes_for is so amazing.
Also I figured out how to update the multiple file upload and I also refactored it a bit. This code is mine but you get the drift.
def create
#motherboard = Motherboard.new(motherboard_params)
if #motherboard.save
save_attachments if params[:motherboard_attachments]
redirect_to #motherboard, notice: 'Motherboard was successfully created.'
else
render :new
end
end
def update
update_attachments if params[:motherboard_attachments]
if #motherboard.update(motherboard_params)
redirect_to #motherboard, notice: 'Motherboard was successfully updated.'
else
render :edit
end
end
private
def save_attachments
params[:motherboard_attachments]['photo'].each do |photo|
#motherboard_attachment = #motherboard.motherboard_attachments.create!(:photo => photo)
end
end
def update_attachments
#motherboard.motherboard_attachments.each(&:destroy) if #motherboard.motherboard_attachments.present?
params[:motherboard_attachments]['photo'].each do |photo|
#motherboard_attachment = #motherboard.motherboard_attachments.create!(:photo => photo)
end
end
Here is my second refactor into the model:
Move private methods to model.
Replace #motherboard with self.
Controller:
def create
#motherboard = Motherboard.new(motherboard_params)
if #motherboard.save
#motherboard.save_attachments(params) if params[:motherboard_attachments]
redirect_to #motherboard, notice: 'Motherboard was successfully created.'
else
render :new
end
end
def update
#motherboard.update_attachments(params) if params[:motherboard_attachments]
if #motherboard.update(motherboard_params)
redirect_to #motherboard, notice: 'Motherboard was successfully updated.'
else
render :edit
end
end
In motherboard model:
def save_attachments(params)
params[:motherboard_attachments]['photo'].each do |photo|
self.motherboard_attachments.create!(:photo => photo)
end
end
def update_attachments(params)
self.motherboard_attachments.each(&:destroy) if self.motherboard_attachments.present?
params[:motherboard_attachments]['photo'].each do |photo|
self.motherboard_attachments.create!(:photo => photo)
end
end
When using the association #post.post_attachments you do not need to set the post_id.

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.