I've been getting the UnkownAttributeError for no particular reason, my models seem to be setup correctly...
School.rb
class School < ActiveRecord::Base
attr_protected :id, :created_at, :updated_at
#relationships
has_many :users
accepts_nested_attributes_for :users
end
My School model used to have the following, but it produced a MassAssignmentSecurity error for the user fields:
attr_accessible :country, :name, :state_or_province, :users_attributes
User.rb
class User < ActiveRecord::Base
attr_accessible :email, :password, :password_confirmation, :remember_me, :username, :instructor_id, :first_name, :last_name, :school_id
#relationships
belongs_to :school
end
new.html.haml
= simple_form_for #school do |f|
.well
= f.input :name, :as => :hidden
= f.input :country, :as => :hidden
= f.input :state_or_province, :as => :hidden
.well
= f.simple_fields_for #school.users.build do |user_form|
= user_form.input :first_name, :required => true
= user_form.input :last_name, :required => true
= user_form.input :username, :required => true
...
= f.button :submit, "Next"
Note: #school is being populated in my new action from session information gathered on the previous page, I'm making a multi-step form. The school data is perfectly valid, if I was to remove the user form it would have no trouble saving the school.
The specific error message I'm getting in my create action:
ActiveRecord::UnknownAttributeError in SchoolsController#create
unknown attribute: user
And the sent params looks a little like this:
{"school"=>{"name"=>"Elmwood Elementary", "country"=>"38",
"state_or_province"=>"448", "user"=>{"first_name"=>"joe",
"last_name"=>"asdas", "username"=>"asasdads",
"email"=>"asdasd#sdas.ca", "password"=>"[FILTERED]",
"password_confirmation"=>"[FILTERED]"}}, "commit"=>"Next"}
Is this maybe a bug with either Devise or simple_form? I'm using Rails 3.2.3
Ok, so apparently I needed to provide the symbol :users - the name of the relationship as my first argument for it to work.
Related
I cleaned up my code, it looks much nicer now, but still doesn’t work. It starts to be a pain…
I just can’t save a parent with an existing child in nested form with parent has_many childs :through joinmodel.
In my case a Project has_many contributing Teachers and many contributing Pupils, both are Join-Models to Users. A Project has_many Schools as well.
(May be I should better name the models Teacherize and Pupilize or ProjectTeacher and ProjectPupil.)
As long as all records are new it all works fine. As soon as I want to connect an existing User as new Teacher of a new Project I get the following error:
Couldn't find User with ID=1 for Teacher with ID=
(1 is the correct user ID)
The problem should be somewhere her in my helper to setup empty form fields:
At least I guess so...
module ProjectsHelper
def setup_project(project)
if project.teachers.length <= 0 # usually there is just one teacher, so add one if there isn't one
teacher = project.teachers.build(:role_in_project => 'master')
if user_signed_in?
#teacher = project.teachers.new(:role_in_project => 'master', :user => current_user)
teacher.user = current_user # associate first teacher with current_user
else
#teacher = project.teachers.build
teacher.user = User.new # associate first teacher with a new user instance
end
end
if project.project_schools.length <= 0 # usually there is just one school, so add one if there isn't one
project_school = project.project_schools.build
project_school.school = School.new
end
if project.pupils.length < 3 # There can be up to 3 people, so add a blank fieldset as long as there are less than 3
pupil = project.pupils.build
pupil.user = User.new
end
project
end
end
These are my params received:
{"utf8"=>"✓", "authenticity_token"=>"uCCMk/s3SpDfR7+fXcsCOHPvfvivBQv8pVFVhdh6iro=",
"project"=>{
"teachers_attributes"=>{
"0"=>{
"id"=>"",
"user_attributes"=>{
"id"=>"1",
"gender"=>"male",
"title"=>"",
"firstname"=>"Firstname1",
"name"=>"Lastname1",
"faculty"=>"",
"fon"=>"",
"fax"=>""}
}
},
"id"=>"",
"title"=>"First Project",
"description"=>"This is a foo bar project!",
"presentation_type"=>"experimentell",
"note"=>""
},
"commit"=>"Register Project",
"action"=>"create",
"controller"=>"projects"
}
The case isn’t too abstract; it has to be possible to achieve it.
It’s just to connect a new parent record with an existing child record!
In this article, which is very good, exactly the case is explaint:
http://rubysource.com/complex-rails-forms-with-nested-attributes
# app/helpers/form_helper
module FormHelper
def setup_user(user)
user.address ||= Address.new
(Interest.all - user.interests).each do |interest|
user.interest_users.build(:interest => interest)
end
user.interest_users.sort_by! {|x| x.interest.name }
user/tmp/clean-controllers.md.html
end
end
There the interest is existing and gets connected through a new record in interest_uesers.
Why do I get the error when trying to do the same thing?
project.teachers.build(:user => current_user)
I studied several articles and casts, but none of them connect existing childs.
http://railscasts.com/episodes/196-nested-model-form-revised
http://apidock.com/rails/ActionView/Helpers/FormHelper/fields_for
http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html
Rails 3.1+ Nested Forms Issue: Can't mass-assign protected attributes
Trying to use accepts_nested_attributes_for and has_and_belongs_to_many but the join table is not being populated
Quote: “accepts_nested_fields_for is used to create and modify related objects in a form. It can be used to populate join table, which is kind of what you're trying to do. However, using accepts_nested_fields_for to populate the join table is impossible with a HABTM relationship.”
That’s what I wanna do! Populate the join table!
It starts to be frustrating and I’d be glad to get some help!
My Models
class Project < ActiveRecord::Base
attr_accessible :title, :description, :presentation_type, :note,
:project_schools_attributes, :schools_attributes, :teachers_attributes, :pupils_attributes,
:users_attributes
validates_presence_of :title
validates_presence_of :description
validates_presence_of :presentation_type
has_many :project_schools, :dependent => :destroy
accepts_nested_attributes_for :project_schools
has_many :schools, :through => :project_schools
#accepts_nested_attributes_for :schools, :reject_if => :all_blank
has_many :pupils, :dependent => :destroy
accepts_nested_attributes_for :pupils, :reject_if => :all_blank
has_many :users, :through => :pupils
has_many :teachers, :dependent => :destroy
accepts_nested_attributes_for :teachers, :reject_if => :all_blank
has_many :users, :through => :teachers
#accepts_nested_attributes_for :users, :reject_if => :all_blank
end
class ProjectSchool < ActiveRecord::Base
attr_accessible :role_in_project, :comment,
:school_attributes, :school_id, :project_id
belongs_to :school
accepts_nested_attributes_for :school
belongs_to :project
end
class School < ActiveRecord::Base
attr_accessible :email, :fax, :fon, :name, :place, :street, :type_of_school, :www, :zip
has_many :project_schools
has_many :projects, :through => :project_schools
has_many :users # in real live they are named teachers and pupils but in this case the association goes directly to a user_id, not to teacher/pupil model
validates_presence_of :name, :type_of_school, :street, :place, :zip, :fon
validates :email, :format => { :with => /\A([^#\s]+)#((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i, :on => :create }, :allow_blank => true
end
class Teacher < ActiveRecord::Base
attr_accessible :role_in_project, :user, :user_attributes, :project_id, :user_id
belongs_to :project
belongs_to :user
accepts_nested_attributes_for :user
serialize :role_in_project
end
class Pupil < ActiveRecord::Base
attr_accessible :classname, :user_attributes #, :project_id, :user_id
belongs_to :project
belongs_to :user
accepts_nested_attributes_for :user
end
class User < ActiveRecord::Base
serialize :roles
belongs_to :school
has_many :teachers
has_many :pupils
has_many :projects, :through => :teachers
has_many :projects, :through => :pupils
# Setup accessible (or protected) attributes for your model
attr_accessible :email, :gender, :firstname, :name, :street, :place, :title, :faculty, :assignment,
:classname, :zip, :fon, :fax, :school_id, :roles,
:password, :added_by_user_id, :password_confirmation, :remember_me
# Include default devise modules. Others available are:
# :token_authenticatable, :confirmable,
# :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable#, :validatable
after_initialize :init
def init
# the default guest user
self.roles ||= ['default'] #will set the default value only if it's nil
end
end
My controller
class ProjectsController < ApplicationController
require 'axlsx'
before_filter :load_page, only: [:show, :index, :destroy]
def new
#project = Project.new
end
def create
#project = Project.new(params[:project])
respond_to do |format|
if #project.save
sign_in(:user, #project.teachers[0].user) unless user_signed_in?
# TODO: send mail
# save as excel file in dropbox
save_in_dropbox(#project)
format.html { redirect_to #project, notice: t('project.was_created') }
else
logger.debug #project.errors.inspect
format.html { render action: "new" }
end
end
end
end
projects/_form.html.haml
%h1
= t('project.register_headline')
= simple_form_for( setup_project(#project), :html => {:class => 'form-horizontal'} )do |f|
= f.error_notification
#teachers-wrapper.well
%span.jumpanchor#lehrkraft_anchor
%fieldset.form-inputs
= f.simple_fields_for :teachers do |teacher|
= render "teacher_fields", :f => teacher
.school-wrapper.well
%span.jumpanchor#schule_anchor
%h2
Informationen zur Schule
%fieldset.form-inputs
= f.simple_fields_for :project_schools do |project_school|
= render "school_fields", :f => project_school
.project-wrapper.well
%span.jumpanchor#projekt_anchor
%h2
Informationen zum Projekt der Schüler
%fieldset.form-inputs
= f.hidden_field :id
= f.input :title, :input_html => { :class => 'span6' }
= f.input :description, :input_html => { :class => 'span6', rows: 5 }
= f.input :presentation_type, collection: ['theoretisch', 'experimentell'], as: :radio_buttons, :class => 'controls-row', :input_html => { :class => 'inline' }
.clearfix
= f.input :note, :input_html => { :class => 'span6', rows: 3 }
.pupils-wrapper.well
%span.jumpanchor#schuler_anchor
%fieldset.form-inputs
= f.simple_fields_for :pupils do |pupil|
= render "pupil_fields", :f => pupil
projects/_teacher_fields.html.haml
= f.simple_fields_for :user do |user|
=# render "teacher_user_fields", :f => user
%h2
Betreuende Lehrkraft
- if user_signed_in?
= user.input :email, :disabled => true, :input_html => {:class => 'email_validation'}
- else
= user.input :email, :autofocus => true, :input_html => {:class => 'email_validation'}, :hint => 'Dies muß Ihre eigene E-Mailadresse sein!'
.details
=# user.hidden_field :id
= user.input :id
= user.input :gender, collection: [:female, :male]
= user.input :title
= user.input :firstname
= user.input :name
= user.input :faculty
= user.input :fon
= user.input :fax
It is Rails 3.2 with Ruby 1.9.3
OK this is weird, I have basically the following classes:
class PriceProfile < ActiveRecord::Base
has_many :prices
has_many :price_profile_date_ranges
attr_accessible :name, :price_profile_date_ranges_attributes
accepts_nested_attributes_for :price_profile_date_ranges
}
class PriceProfileDateRange < ActiveRecord::Base
attr_accessible :end_date, :price_profile_id, :start_date, :prices, :prices_attributes
has_many :prices, :dependent=>:destroy
belongs_to :price_profile
accepts_nested_attributes_for :prices
}
class Price < ActiveRecord::Base
attr_accessible :price_profile_date_range_id, :price_profile_id, :product_id, :value
belongs_to :price_profile
belongs_to :price_profile_date_range
belongs_to :product
}
A price profile defines a pricing scheme for a particular product whose price changes over time. The date ranges over which a price is applied is stored in the price_profile_date_range table and finally the prices table holds all the prices. I'm using the following controller & view to create the form here for setting prices while creating a date range. Basically the form has a start and end date fields and a grid i.e it would have a list of texteboxs against all products to enter the price.
This is the view:
.row
.span9
= simple_form_for(#price_profile_date_range, :class=>'well') do |f|
.form-inputs
= f.input :start_date, :required => true, :as => :string, :input_html =>{:class=>'datepicker'}
= f.input :end_date, :required => true, :as => :string, :input_html =>{:class=>'datepicker'}
= f.input :price_profile_id, :as=>:hidden
%table.table.table-bordered.table-condensed.table-striped
%tr
%td
- #products.each do |product|
%td
=product[:name]
%td
- f.fields_for(:prices) do |price_element|
= price_element.input :value, :class=>'span1'
= price_element.input :price_profile_id, :as=>:hidden
= price_element.input :price_profile_date_range_id, :as=>:hidden
= price_element.input :product_id, :as=>:hidden
.form-actions
= f.button :submit
This isnt exactly the final form - the problem is that the f.fields_for line doesn't seem to execute. In the controller I initialise the #price_profile_date_range object with a set of prices. If I do a raise inspect it shows all the price objects even in the view however the fields_for doesn't execute at all. I'm pretty stuck here real badly.
Try changing the - to a = - sounds silly but maybe that's the problem.
I'm trying to set up a polymorphic association for photo uploads which are processed using Carrierwave. I'm using Simple Form to build my forms. I feel like the association is correct so I'm wondering if my problem is just something with the form or controller.
Here are my associations:
property.rb:
class Property < ActiveRecord::Base
attr_accessible :image
...
has_many :image, :as => :attachable
...
end
unit.rb
class Unit < ActiveRecord::Base
attr_accessible :image
...
has_many :image, :as => :attachable
end
image.rb
class Image < ActiveRecord::Base
belongs_to :attachable, :polymorphic => true
mount_uploader :image, PhotoUploader
end
properties_controller.rb:
def edit
#property = Property.find params[:id]
#property.image.build if #property.image.empty?
end
def update
#property = Property.find params[:id]
if #property.update_attributes params[:property]
redirect_to admin_properties_path, :notice => 'The property has been successfully updated.'
else
render "edit"
end
end
Snippet from properties/_form.html.erb
<%= f.input :image, :label => 'Image:', :as => :file %>
Here is the error I get when submitting with an image attached:
undefined method `each' for #<ActionDispatch::Http::UploadedFile:0x00000102291bb8>
And here are the params:
{"utf8"=>"✓",
"_method"=>"put",
"authenticity_token"=>"lvB7EMdc7juip3gBZD3XhCLyiv1Vwq/hIFdb6f1MtIA=",
"property"=>{"name"=>"Delaware Woods",
"address"=>"",
"city"=>"",
"state"=>"",
"postal_code"=>"",
"description"=>"2 bedroom with large kitchen. Garage available",
"incentives"=>"",
"active"=>"1",
"feature_ids"=>[""],
"user_ids"=>[""],
"image"=>#<ActionDispatch::Http::UploadedFile:0x00000102291bb8 #original_filename="wallpaper-4331.jpg",
#content_type="image/jpeg",
#headers="Content-Disposition: form-data; name=\"property[image]\"; filename=\"wallpaper-4331.jpg\"\r\nContent-Type: image/jpeg\r\n",
#tempfile=#<File:/tmp/RackMultipart20120608-3102-13f3pyv>>},
"commit"=>"Update Property",
"id"=>"18"}
I'm looking everywhere for help on polymorphic associations and am getting nowhere. I've seen simple examples that look pretty straight forward. One thing I've noticed is that it seems like in a lot of the examples the has_many association in my case should be images and not image. However when I do that I get an error:
Can't mass-assign protected attributes: image
I've tried updating my form to use fields_for as I've seen in other blogs like so:
<%= f.input :image, :label => "Photo", :as => :file %>
<% f.simple_fields_for :images do |images_form| %>
<%= images_form.input :id, :as => :hidden %>
<%= images_form.input :attachable_id, :as => :hidden %>
<%= images_form.input :attachable_type, :as => :hidden %>
<%= images_form.input :image, :as => :file %>
<% end %>
All I know is I'm having a heck of a time getting this to work. I'm pretty new to Rails so even debugging it is difficult. It doesn't help that the debugger doesn't really work in 3.2 :(
Since your models have_many :images (it should be :images, not :image), you'll want to use nested_forms in your views. You should set up accepts_nested_attributes_for :images on the unit and property models and change the attr_accessible from :image to :image_attributes.
Check out http://railscasts.com/episodes/196-nested-model-form-part-1 for a good guide on getting going with it.
I'm using ActiveAdmin (0.4.0) with Rails (3.1.1).
I can't find a nice way/hack to handle multiple nested resources.
Considerer 3 models as:
class Program < ActiveRecord::Base
has_many :knowledges, :dependent => :destroy
end
class Knowledge < ActiveRecord::Base
belongs_to :program
has_many :steps, :dependent => :destroy
end
class Step < ActiveRecord::Base
belongs_to :knowledge
end
And the ActiveAdmin resources:
ActiveAdmin.register Program do
end
ActiveAdmin.register Knowledge do
belongs_to :program
end
ActiveAdmin.register Step do
belongs_to :knowledge
end
In routes.rb:
namespace :admin do
resources :programs do
resources :knowledges do
resources :steps
end
end
end
Here's the urls for the index of the programs, the knowledges and the steps :
http://localhost:3000/admin/programs
http://localhost:3000/admin/programs/1/knowledges
http://localhost:3000/admin/programs/1/knowledges/1/steps
No problem for the "Knowledge" admin but the "Step" admin don't keep the nested context.
For example, when I use filters in steps#index I'm redirected to:
http://localhost:3000/admin/knowledges/1/steps?params...
But it must have been:
http://localhost:3000/admin/programs/1/knowledges/1/steps?params...
Same problem when I create a new resource:
http://localhost:3000/admin/knowledges/1/steps/new
Instead of:
http://localhost:3000/admin/programs/1/knowledges/1/steps/new
Same problem with the breadcrumb... etc...
What I've tried so far in app/admin/steps.rb:
ActiveAdmin.register Step do
belongs_to :knowledge
config.clear_action_items!
action_item :only => :index do
link_to('Create Step', new_admin_program_knowledge_step_path(knowledge.program.id, knowledge.id))
end
index do
column :id
column :knowledge
column :title
column "Actions" do |step|
link_to("Voir", admin_program_knowledge_step_path(step.knowledge.program, step.knowledge, step), :class => "member_link show_link") +\
link_to("Editer", edit_admin_program_knowledge_step_path(step.knowledge.program, step.knowledge, step), :class => "edit_knowledge member_link edit_link", :id => "knowledge_#{dom_id(knowledge)}") +\
link_to("Supprimer", admin_program_knowledge_step_path(step.knowledge.program, step.knowledge, step), :class => "member_link delete_link", :method => :delete, :confirm => "Delete?")
end
end
filter :id
filter :title
filter :subtitle
filter :stage_type
filter :order_by
filter :created_at
filter :updated_at
form :partial => "form"
end
And in app/views/admin/steps/_form.html.erb I must use the activeadmin formbuilder:
<%= semantic_form_for(resource, :url => admin_program_knowledge_steps_path(resource.knowledge.program, resource.knowledge), :builder => ActiveAdmin::FormBuilder) do |f|
f.inputs "Step" do
f.input :knowledge, :as => :hidden
f.form_buffers.last << f.template.content_tag(:li, f.template.content_tag(:label, "Knowledge")+f.template.content_tag(:p, f.object.knowledge.title))
f.input :title
f.input :order_by
end
f.buttons
end %>
Well... I'm stuck.
How to handle this nicely? Any clues appreciated...
Well, the solution is pretty simple...
https://github.com/josevalim/inherited_resources
ActiveAdmin.register Step do
controller do
nested_belongs_to :program, :knowledge
end
end
when I visit 'company/new', then I get the following error:
undefined method `companies_path'
Extracted source (around line #1):
1: <%= form_for(#company) do |f| %>
But when I visit 'company/1/edit' (which uses the same form) everything works fine.
This is the company controller for 'new' and 'edit':
def new
#company = Company.new
end
def edit
#company = Company.find(params[:id])
end
And this is (part of) the form:
<%= form_for(#company) do |f| %>
<!-- Show errors -->
<%= render('layouts/form_errors', :object => #company) %>
I really don't understand the error message, because 'companies_path' is not being used in the code?
Update: here is the routes.rb:
get "users_dashboard/show"
get "login" => "sessions#new", :as => "login"
get "logout" => "sessions#destroy", :as => "logout"
resources :company
resources :relations
resources :activities
resources :contacts
resources :notes
resources :tasks
resources :users
resources :sessions
get "site/index"
get "site/features"
get "site/dashboard"
root :to => 'users_dashboard#show'
And here is the company model:
class Company < ActiveRecord::Base
has_many :users
has_many :relations
has_many :contacts, :through => :relations
has_many :notes, :through => :contacts
has_many :tasks, :through => :contacts
has_one :subscription
accepts_nested_attributes_for :subscription
attr_accessible :name, :address1, :address2, :zipcode, :city, :country, :email, :website, :telephone, :twitter, :linkedin, :code
validates :name, :address1, :zipcode, :city, :country, :code, presence: true
validates_length_of :code, :maximum => 3
end
You should change
resources :company
to
resources :companies