attr_accessible with paperclip multiple picture uploads - paperclip

I followed the tutorial here and everything turned out nicely.. until I tried adding attr_accessible to the article model. Thanks in advance.
Here's the related code:
app/models/user.rb
class User < ActiveRecord::Base
attr_accessible :name, :email
has_many :assets, :dependent => :destroy
accepts_nested_attributes_for :assets, :allow_destroy => true
end
app/models/asset.rb
class Asset < ActiveRecord::Base
attr_accessible :user_id, :image
belongs_to :user
has_attached_file :image,
:styles => {
:thumb=> "100x100#",
:small => "300x300>",
:large => "600x600>"
}
end
db/schema.rb
create_table "assets", :force => true do |t|
t.integer "user_id"
t.datetime "created_at"
t.datetime "updated_at"
t.string "image_file_name"
t.string "image_content_type"
t.integer "image_file_size"
end
create_table "users", :force => true do |t|
t.string "name"
t.string "email"
t.datetime "created_at"
t.datetime "updated_at"
end
app/views/users/_form.html.erb
<%= form_for(#user, :html => { :multipart => true }) do |f| %>
<% if #user.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#user.errors.count, "error") %> prohibited this user from being saved:</h2>
<ul>
<% #user.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :name %><br />
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :email %><br />
<%= f.text_field :email %>
</div>
<div class="newPaperclipFiles">
<%= f.fields_for :assets do |asset| %>
<% if asset.object.new_record? %>
<%= asset.file_field :image %>
<% end %>
<% end %>
</div>
<div class="existingPaperclipFiles">
<% f.fields_for :assets do |asset| %>
<% unless asset.object.new_record? %>
<div class="thumbnail">
<%= link_to( image_tag(asset.object.image.url(:thumb)), asset.object.image.url(:original) ) %>
<%= asset.check_box :_destroy %>
</div>
<% end %>
<% end %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>

After trying various permutations and going through related posts, finally caught the gremblin that's been eluding me the past few days. All I needed is to add the :assets_attributes to the list of attr_accessible in the user model. Thanks for reading!
attr_accesible for nested objects

Related

Create Related Data using Nested attributes

api. Now need to insert a record which has associated records. I read nested attributes but didn't get any idea. I can't understand well.
I tried with one example in rails mvc project but even i can't create associated record in one-one mapping itself. Please guid me what the steps to do this or any good articles with sample?
Anyway the following is my workings
My model is
class Instructor < ActiveRecord::Base
has_one :office_assignment
has_many :departments
has_and_belongs_to_many :courses
accepts_nested_attributes_for :office_assignment
end
class OfficeAssignment < ActiveRecord::Base
belongs_to :instructor
end
My controller methods for create
def new
#instructor = Instructor.new
end
def create
#instructor = Instructor.new(instructor_params)
respond_to do |format|
if #instructor.save
format.html { redirect_to #instructor, notice: 'Instructor was successfully created.' }
format.json { render :show, status: :created, location: #instructor }
else
format.html { render :new }
format.json { render json: #instructor.errors, status: :unprocessable_entity }
end
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_instructor
#instructor = Instructor.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def instructor_params
params.require(:instructor).permit(:LastName, :FirstMidName, :HireDate, office_assignment_attributes: [:Location])
end
My create form
<%= form_for #instructor, :html => { :class => "form-horizontal instructor" } do |f| %>
<% if #instructor.errors.any? %>
<div id="error_expl" class="panel panel-danger">
<div class="panel-heading">
<h3 class="panel-title"><%= pluralize(#instructor.errors.count, "error") %> prohibited this instructor from being saved:</h3>
</div>
<div class="panel-body">
<ul>
<% #instructor.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
</div>
<% end %>
<div class="form-group">
<%= f.label :LastName, :class => 'control-label' %>
<div class="controls">
<%= f.text_field :LastName, :class => 'form-control' %>
</div>
<%= error_span(#instructor[:LastName]) %>
</div>
<div class="form-group">
<%= f.label :FirstMidName, :class => 'control-label' %>
<div class="controls">
<%= f.text_field :FirstMidName, :class => 'form-control' %>
</div>
<%= error_span(#instructor[:FirstMidName]) %>
</div>
<div class="form-group">
<%= f.label :HireDate, :class => 'control-label' %>
<div class="controls">
<%= f.text_field :HireDate, :class => 'form-control' %>
</div>
<%= error_span(#instructor[:HireDate]) %>
</div>
<div class="form-group">
<%= f.label :Location, :class => 'control-label' %>
<div class="controls">
<input type="text" name="office_assignment_Location" class ="form-control">
</div>
<%= error_span(#instructor[:HireDate]) %>
</div>
<%= f.submit nil, :class => 'btn btn-primary' %>
<%= link_to t('.cancel', :default => t("helpers.links.cancel")),
instructors_path, :class => 'btn btn-default' %>
<% end %>
Please guide me..
Edit:
Changes in html file
<%= f.fields_for :office_assignment_Location do |loc| %>
<div class="form-group">
<%= loc.label :Location, :class => 'control-label' %>
<div class="controls">
<%= loc.text_field :Location %>
</div>
</div>
<%= loc.link_to_add "Add Location", :office_assignment_Location , :class=>'btn btn-primary'%>
<% end %>
My param in controller
def instructor_params
params.require(:instructor).permit(:LastName, :FirstMidName, :HireDate, office_assignment_attributes: [:id, :Location ,:_destroy])
end
My schema
create_table "instructors", force: :cascade do |t|
t.string "LastName", limit: 255
t.string "FirstMidName", limit: 255
t.date "HireDate"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "office_assignments", primary_key: "Instructor_Id", force: :cascade do |t|
t.string "Location", limit: 255
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_foreign_key "office_assignments", "instructors", column: "Instructor_Id"
FYI: attribute's name should start with small letter not capital.
Here are some changes:
class Instructor < ActiveRecord::Base
has_one :office_assignment , :dependent => :destroy # add dependent destroy
has_many :departments
has_and_belongs_to_many :courses
accepts_nested_attributes_for :office_assignment, :reject_if => :all_blank, :allow_destroy => true # add allow destroy
end
Some change in strong Parameters:
def instructor_params
params.require(:instructor).permit(:LastName, :FirstMidName, :HireDate, office_assignment_attributes: [:id, :Lesson ,:_destroy])
end
Note: Don't forget to add :id and :_destroy in office_assignment_attributes
Now in View(form_template):
Instead of this:
<div class="form-group">
<%= f.label :Location, :class => 'control-label' %>
<div class="controls">
<input type="text" name="office_assignment_Location" class ="form-control">
</div>
<%= error_span(#instructor[:HireDate]) %>
</div>
It should be:
<%= nested_form_for #instructor, :html => { :class => "form-horizontal instructor" } do |f| %>
......
.....
<%= f.fields_for :office_assignment do |loc| %>
<div class="form-group">
<%= loc.label :Location, :class => 'control-label' %>
<div class="controls">
<%= loc.text_field :Location %>
</div>
</div>
<% end %>
<%= f.link_to_add "Add Location", :office_assignment , :class=>'btn btn-primary'%>
You have to create nested form like this. I hope this helps you.
Note: Use nested_form_for instead of form_for in your form:
For your reference:
http://railscasts.com/episodes/196-nested-model-form-part-1
http://railscasts.com/episodes/197-nested-model-form-part-2

Rails 4: How to to save models in new form with has_many through association

I am new to rails, and I am trying to create a new event that allows a user to select a place and an organization from places and organizations that already exist in the database. I am using a has_many through association. Now I cannot get the event to save, even when I try to save the event without the place_id or organization_id fields.
Models:
class Event < ActiveRecord::Base
belongs_to :organization
belongs_to :place
end
class Organization < ActiveRecord::Base
has_many :events
has_many :places, through: :events
end
class Place < ActiveRecord::Base
has_many :events
has_many :organizations, through: :events
end
Event Controller:
def new
#event = Event.new
end
def create
#event = Event.new(event_params)
if #event.save
render 'show'
else
render 'new'
end
end
def event_params
params.require(:event).permit(:name, :description, :contact, :tag_list, :address, :latitude, :longitude, :long_description, :event_date, :start_time, :end_time, :organization_id, :place_id)
end
New Event View:
<%= form_for #event do |f| %>
<%= f.label :name %>
<%= f.text_field :name %>
<%= f.label :event_date %>
<%= f.text_field :event_date %>
<%= f.label :start_time %>
<%= f.text_field :start_time %>
<%= f.label :end_time %>
<%= f.text_field :end_time %>
<%= f.label :description %>
<%= f.text_field :description %>
<%= f.label :contact %>
<%= f.text_field :contact %>
<%= f.label :address %>
<%= f.text_field :address %>
<%= f.label :long_description %>
<%= f.text_field :long_description %>
<%= f.label :tag_list, "Tags (separated by commas)" %>
<%= f.text_field :tag_list %>
<%= f.submit "Save event", class: "button" %>
<% end %>
What am I missing here to get the event to save, preferably with organization and place fields that have values of organization_id and place_id?
You should be looking at accepts_nested_attributes_for and fields_for.And then change your models to like this
class Organization < ActiveRecord::Base
has_many :events
has_many :places, through: :events
accepts_nested_attributes_for :places
end
class Place < ActiveRecord::Base
has_many :events
has_many :organizations, through: :events
accepts_nested_attributes_for :organizations
end
So that your event_params would be like this
def event_params
params.require(:event).permit(:name, :description, :contact, :tag_list, :address, :latitude, :longitude, :long_description, :event_date, :start_time, :end_time, places_attributes: [:some_attribute_of_place,..], organizations_attributes: [:some_attribute_of_organization,..)
end
And your form could be written as,
<%= form_for #event do |f| %>
<%= f.label :name %>
<%= f.text_field :name %>
<%= f.label :event_date %>
<%= f.text_field :event_date %>
<%= f.label :start_time %>
<%= f.text_field :start_time %>
<%= f.label :end_time %>
<%= f.text_field :end_time %>
<%= f.label :description %>
<%= f.text_field :description %>
<%= f.label :contact %>
<%= f.text_field :contact %>
<%= f.label :address %>
<%= f.text_field :address %>
<%= f.label :long_description %>
<%= f.text_field :long_description %>
<%= f.label :tag_list, "Tags (separated by commas)" %>
<%= f.text_field :tag_list %>
<%= f.fields_for :places do |p| %>
---- your code-----
<% end %>
<%= f.fields_for :organizations do |o| %>
------ your code-----
<% end %>
<%= f.submit "Save event", class: "button" %>
<% end %>

How to get one model value from another model in ruby on rails?

I got a task to integrate multiple models in a single form.I have one form 'register' and two models buyer and address. But by doing this i can not attach two forms together.
_form.html.erb is
<% #register.buyers.build %>
<%= form_for(#register) do |f| %>
<% if #register.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#register.errors.count, "error") %> prohibited this register from being saved:</h2>
<ul>
<% #register.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :date %><br />
<%= f.date_select :date %>
</div>
<div class="field">
<h4>Buyer</h4>
</div>
<div class="field">
<%# f.fields_for :buyers do |builder| %>
<%= render :partial => "buyer_fields", :locals => {:f => f } %>
<%# end %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
_buyer_fields.html.erb is
<% f.fields_for :buyers do |buyers_form| %>
<div class="fields">
<p>
<%= buyers_form.label :name, "Name" %><br/>
<%= buyers_form.text_field :name %>
</p>
<h4>Address</h4>
<% f.fields_for :addresses do |builder| %>
<%= render :partial => 'address_fields', :locals => { :f => builder} %>
<% end %>
</div>
<% end%>
and the _address_fields.html.erb is
<p class="fields">
<table>
<tr>
<td>
<%= f.text_area :name, :rows => "2",:cols => "20" %>
</td>
</tr>
</table>
</p>
register model is
class Register < ActiveRecord::Base
attr_accessible :date, :book_ids,:buyers_attributes
has_many :authorships
has_many :books, :through => :authorships
has_many :buyers
#accepts_nested_attributes_for :buyers, :reject_if => lambda { |a| a[:name].blank? }, :allow_destroy => true
accepts_nested_attributes_for :buyers, :allow_destroy => :true,
:reject_if => proc { |attrs| attrs.all? { |k, v| v.blank? } }
end
buyer model is
class Buyer < ActiveRecord::Base
belongs_to :register
attr_accessible :addresses_attributes, :name
has_many :addresses, :dependent => :destroy
accepts_nested_attributes_for :addresses, :reject_if => lambda { |a| a[:name].blank? }, :allow_destroy => true
end
and address model is
attr_accessible :name
belongs_to :buyer
But only register form is displayed. How can i integrate two models in single form in ruby on rails 3.2.9? Please help.
Your nested address view is wrong.
Make some changes in buyer_fields.html.erb
<%= f.fields_for :buyers do |buyers_form| %>
<div class="fields">
<p>
<%= buyers_form.label :name, "Name" %><br/>
<%= buyers_form.text_field :name %>
</p>
<h4>Address</h4>
<%= buyers_form.fields_for :addresses do |builder| %>
<%= render :partial => 'address_fields', :locals => { :f => builder} %>
<% end %>
</div>
<% end %>

can't convert Symbol into Integer + Rails 3.2 Nested Attributes

I'm working on a simple project to test the nested attributes of Rails 3.2. However, I'm getting this kind of error when trying to submit the form:
can't convert Symbol into Integer
post.rb and comment.rb
class Post < ActiveRecord::Base
attr_accessible :title, :comments_attributes
has_many :comments
accepts_nested_attributes_for :comments
validates_presence_of :title
end
class Comment < ActiveRecord::Base
attr_accessible :comment, :author
belongs_to :post
validates_presence_of :comment
validates_presence_of :author
end
posts_controller.rb
def new
#post = Post.new
#post.comments.build
respond_to do |format|
format.html # new.html.erb
format.json { render json: #post }
end
end
_form.html.erb
<%= form_for(#post) do |f| %>
<% if #post.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#post.errors.count, "error") %> prohibited this post from being saved:</h2>
<ul>
<% #post.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :title %><br />
<%= f.text_field :title %>
</div>
<%= f.fields_for :comments_attributes do |builder| %>
<fieldset>
<%= builder.label :comment %><br />
<%= builder.text_field :comment %><br />
<%= builder.label :author %><br />
<%= builder.text_field :author %>
</fieldset>
<% end %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
parameters
{"utf8"=>"✓",
"authenticity_token"=>"gNA0mZMIxkA+iIJjw8wsddcKxvmzaFnrgiHvFw1OrYA=",
"post"=>{"title"=>"Dummy Title",
"comments_attributes"=>{"comment"=>"Dummy Comment",
"author"=>"Dummy Author"}},
"commit"=>"Create Post"}
I agree with the comments that it's tough to troubleshoot without the stacktrace and create method, but that said, this looks weird:
<%= f.fields_for :comments_attributes do |builder| %>
The fields are for your comment objects, right? as opposed to the comment_attributes of the post object (the latter doesn't make sense here, at least on a first reading).
You might try changing :comments_attributes to :comments.

Rails 3 - save few models with foreign keys in same time

I have models User, Teacher, TeacherEducation. TeacherEducation belongs to Teacher, Teacher belongs to User.
I use nested attributes to save everything via one line in my controller user.save. But I met thing which I can't solve. I can set id for Teacher, but I can't give id for TeacherEducation before I can save Teacher.
Is it possible to fix that and keep using nested attributes in my models?
class User < ActiveRecord::Base
attr_accessor :password
attr_accessible :user_login,
:password,
:teacher_attributes
has_one :teacher
accepts_nested_attributes_for :teacher
end
class Teacher < ActiveRecord::Base
attr_accessible :teacher_last_name,
:teacher_first_name,
:teacher_middle_name,
:teacher_birthday,
:teacher_sex,
:teacher_category,
:teacher_education_attributes
belongs_to :user
has_one :teacher_education
accepts_nested_attributes_for :teacher_education
validates :user_id,
:presence => true
end
class TeacherEducation < ActiveRecord::Base
attr_accessible :teacher_education_university,
:teacher_education_year,
:teacher_education_graduation,
:teacher_education_speciality
belongs_to :teacher
validates :teacher_id,
:presence => true
...
end
My controller
class AdminsController < ApplicationController
def create_teacher
user = User.new( params[:user] )
user.user_role = "teacher"
user.teacher.user_id = current_user.id # Work
user.teacher.teacher_education.teacher_id = user.teacher.id # Doesn't work
if user.save
...
end
end
end
So, user.teacher.teacher_education.teacher_id = user.teacher.id doesn't work.
UPD
Error
Teacher teacher education teacher can't be blank, Teacher user can't be blank
View - new_teacher.html.erb
<%= form_for #user, :url => create_teacher_url, :html => {:class => "form-horizontal"} do |f| %>
<%= field_set_tag do %>
<%= f.fields_for :teacher do |builder| %>
<div class="control-group">
<%= builder.label :teacher_last_name, "Фамилия", :class => "control-label" %>
<div class="controls">
<%= builder.text_field :teacher_last_name, :value => #teacher_last_name %>
</div>
</div>
<div class="control-group">
<%= builder.label :teacher_first_name, "Имя", :class => "control-label" %>
<div class="controls">
<%= builder.text_field :teacher_first_name, :value => #teacher_first_name %>
</div>
</div>
<div class="control-group">
<%= builder.label :teacher_middle_name, "Отчество", :class => "control-label" %>
<div class="controls">
<%= builder.text_field :teacher_middle_name, :value => #teacher_middle_name %>
</div>
</div>
<div class="control-group">
<%= builder.label :teacher_sex, "Пол", :class => "control-label" %>
<div class="controls">
<%= label_tag nil, nil, :class => "radio" do %>
<%= builder.radio_button :teacher_sex, 'm', :checked => #user_sex_man %>
Мужской
<% end %>
<%= label_tag nil, nil, :class => "radio" do %>
<%= builder.radio_button :teacher_sex, 'w', :checked => #user_sex_woman %>
Женский
<% end %>
</div>
</div>
<div class="control-group">
<%= builder.label :teacher_birthday, "Дата рождения", :class => "control-label" %>
<div class="controls">
<%= builder.text_field :teacher_birthday, :value => #teacher_birthday %>
<p class="help-block">Формат даты: дд.мм.гггг</p>
</div>
</div>
<div class="control-group">
<%= builder.label :teacher_category, "Категория", :class => "control-label" %>
<div class="controls">
<%= builder.text_field :teacher_category, :value => #teacher_category %>
</div>
</div>
<%= builder.fields_for :teacher_education do |edu_fields| %>
<div class="control-group">
<%= edu_fields.label :teacher_education_university, "Название ВУЗа", :class => "control-label" %>
<div class="controls">
<%= edu_fields.text_field :teacher_education_university, :value => #teacher_university %>
</div>
</div>
<div class="control-group">
<%= edu_fields.label :teacher_education_year, "Дата выпуска из ВУЗа", :class => "control-label" %>
<div class="controls">
<%= edu_fields.text_field :teacher_education_year, :value => #teacher_finish_univ %>
<p class="help-block">Формат даты: дд.мм.гггг</p>
</div>
</div>
<div class="control-group">
<%= edu_fields.label :teacher_education_graduation, "Степень", :class => "control-label" %>
<div class="controls">
<%= edu_fields.text_field :teacher_education_graduation, :value => #teacher_graduation %>
</div>
</div>
<div class="control-group">
<%= edu_fields.label :teacher_education_speciality, "Специальность", :class => "control-label" %>
<div class="controls">
<%= edu_fields.text_field :teacher_education_speciality, :value => #teacher_specl %>
</div>
</div>
<% end %>
<% end %>
<hr/>
<div class="control-group">
<%= f.label :user_login, "Логин учетной записи", :class => "control-label" %>
<div class="controls">
<%= f.text_field :user_login, :value => #user_login %>
<%= link_to_function "Сгенерировать логин", "generate_login()", :class => "btn" %>
</div>
</div>
<div class="control-group">
<%= f.label :password, "Пароль учетной записи", :class => "control-label" %>
<div class="controls">
<%= f.text_field :password, :value => #user_password %>
<%= link_to_function "Сгенерировать пароль", "generate_password()", :class => "btn" %>
</div>
</div>
<% end %>
<%= f.submit "Создать", :class => "btn btn-large btn-success" %>
<% end %>
Also, some debug information:
user: !ruby/hash:ActiveSupport::HashWithIndifferentAccess
password: somepass
teacher_attributes: !ruby/hash:ActiveSupport::HashWithIndifferentAccess
teacher_birthday: 21.12.1990
teacher_category: categ
teacher_education_attributes: !ruby/hash:ActiveSupport::HashWithIndifferentAccess
teacher_education_graduation: grad
teacher_education_speciality: spec
teacher_education_university: univ
teacher_education_year: 28.09.2000
teacher_first_name: name
teacher_last_name: last
teacher_middle_name: middle
teacher_sex: w
user_login: schoolh_Lyp1v
utf8: ✓
controller: admins
My schema
create_table "teacher_educations", :force => true do |t|
t.integer "teacher_id"
t.string "teacher_education_university"
t.date "teacher_education_year"
t.string "teacher_education_graduation"
t.string "teacher_education_speciality"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
create_table "teacher_phones", :force => true do |t|
t.integer "teacher_id"
t.string "teacher_home_number"
t.string "teacher_mobile_number"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
create_table "teachers", :force => true do |t|
t.integer "user_id"
t.string "teacher_last_name"
t.string "teacher_first_name"
t.string "teacher_middle_name"
t.date "teacher_birthday"
t.string "teacher_sex"
t.string "teacher_category"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
create_table "users", :force => true do |t|
t.string "user_login"
t.string "user_role"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.string "encrypted_password"
t.string "salt"
end
If you are constructing your form properly to support the nested attributes then this is all you need:
user = User.new( params[:user] )
user.user_role = "teacher"
if user.save
...
end
The accepts_nested_attributes mechanics will take care of the rest. If the above doesn't work then lets look at how your form is put together.

Resources