This is my hacked together attempt at getting Carrierwave to work right from watching Railscast. I have a Post Project page where users enter in details for a project. They can also upload a file to this page, and submit the project. So I am using a nested_form_for on the page.
new_step_3.html.erb
<%= nested_form_for #project, :html => {:multipart => true} do |f| %>
<%= f.text_field :title %>
<%= f.text_field :description %>
<%= f.fields_for :document do |attachment_form| %>
<%= attachment_form.file_field :title %>
<% end %>
<%= f.text_field :skills %>
<%= f.submit 'Post Project' %>
<% end %>
project.rb model
attr_accessible :category, :title, :budget, :end_date, :description, :skills, :document, :days_lasting, :documents_attributes
belongs_to :user
has_many :posts
has_many :documents, :as => :attachable
validates_presence_of :category, :title, :description, :skills
accepts_nested_attributes_for :documents
document.rb model
attr_accessible :project_id, :title, :document
belongs_to :user
belongs_to :project
has_many :posts
mount_uploader :document, DocumentUploader
projects_controller.rb
def create
#project = current_user.projects.build(params[:project])
respond_to do |format|
if #project.save
format.html { redirect_to project_step_4_path(:start => #project.id), notice: 'Project was successfully created.' }
format.json { render json: #project, status: :created, location: #project }
else
format.html { render action: "new" }
format.json { render json: #project.errors, status: :unprocessable_entity }
end
end
end
Right now, when I try to submit the form, it will say unknown attribute: document
app/controllers/projects_controller.rb:85:in `create'
Running the command in Rails console works Document.create!(:document => File.new("test.jpg"))
I think it should be
<%= f.fields_for :documents do |attachment_form| %>
<%= attachment_form.file_field :title %>
<% end %>
with fields_for :documents
That's why it's not finding the document attribute. Your form probably sends a hash like that:
{
:project => {
:title => "blabla",
:document => {...}
}
}
and it doesnt know what to do with the document.
Now your nested documents will be in :documents => {}, and with the accepts_nested_attributes_for, it should work.
You have to build a document for this project in the controller:
#project.documents.build
Related
In my db there are a lot of users with invalid data (without mobile number). Because I added mobile presence validation just now. When I'm trying to add new event, I get error messages "Users mobile number must be in ... format". How I can skip user validation when creating events?
event.rb
class Event < ActiveRecord::Base
has_many :participations
has_many :users, :through => :participations
end
user.rb
class User < ActiveRecord::Base
has_many :participations
has_many :events, :through => :participations
end
events_controller.rb
def create
#event = Event.new(event_params)
respond_to do |format|
if #event.save
format.html { redirect_to events_path, notice: 'Event was successfully created.' }
else
format.html { render action: 'new' }
end
end
end
_form.html.erb
<%= form_for #event, :html => {:class => 'row'} do |f| %>
<%= f.error_messages %>
<%= f.label :name %>
<%= f.text_field :name %>
<%= f.label :user_ids, "Participants" %>
<%= f.collection_select :user_ids, User.all, :id, :name, {}, { :multiple => true } %>
<%= clear %>
<%= f.submit 'Save' %>
<% end %>
Set validate: false in Event has_many :users association
class Event < ActiveRecord::Base
has_many :participations
has_many :users, :through => :participations, validate: false
end
I am new to rails and keep struggling with the following issue. Unfortunately, hours of search have not led to a solution, so I would be more than happy to get your input.
On creating an order, I attempt to create a client (as parent) and order items (as child). The latter works fine. However, on saving the order, both order and client are stored in the database with the exception that the *client_id* is not passed to the order record.
Here follows my code:
Company Model
class Company < ActiveRecord::Base
has_many :orders, foreign_key: "client_id"
accepts_nested_attributes_for :orders
validates :name,
:presence => true,
:uniqueness => { :case_sensitive => false }
validates_associated :users,
:orders
attr_accessible :name,
:account,
:users_attributes,
:orders_attributes,
:company_id
end
Order Model
class Order < ActiveRecord::Base
has_many :order_items
accepts_nested_attributes_for :order_items
belongs_to :client, class_name: "Company",
foreign_key: "id"
accepts_nested_attributes_for :client
attr_accessible :order_items_attributes,
:order_number,
:client_attributes,
:client_id
validates_associated :order_items
validates_presence_of :order_number
:client_id
end
Orders Controller
def create
#order = #client.orders.build(params:[orders])
puts #order.to_yaml
respond_to do |format|
if #order.save!
format.html { redirect_to #order, notice: 'Order was successfully created.' }
format.json { render json: #order, status: :created, location: #order }
else
format.html { render action: "new" }
format.json { render json: #order.errors, status: :unprocessable_entity }
end
end
end
New Order Form
<%= simple_form_for #order, :html => { :class => 'form-horizontal' } do |f| %>
<%= render 'shared/error_messages', :object => #order %>
<div class = "span3">
<%= f.simple_fields_for :client do |client_builder| %>
<%= client_builder.input :name,
:label => 'Client' %>
<% end %>
<%= f.input :order_number %>
<%= f.simple_fields_for :order_items do |items_builder| %>
<%= items_builder.input :reference_number %>
<%= items_builder.input :item_description %>
<% end %>
<%= f.button :submit,
:class => 'btn'%>
<%= link_to t('.cancel', :default => t("helpers.links.cancel")),
orders_path, :class => 'btn' %>
</div>
<% end %>
Thanks for your help in advance!
Stefan
belongs_to :client, class_name: "Company", foreign_key: "id"
Should be
belongs_to :client, class_name: "Company", foreign_key: "client_id"
Also i would update your migration and make that field not nullable, better to get an exception than saving an order without client
I have 3 model the first user.rb:
class User
has_many :boards, dependent: :destroy
has_many :posts, dependent: :destroy, :autosave => true
accepts_nested_attributes_for :boards
accepts_nested_attributes_for :posts
end
The second model its board.rb
class Board
has_many :posts, :dependent => :destroy , :autosave => true
accepts_nested_attributes_for :posts
belongs_to :user
end
The third model its post.rb
class Post
belongs_to :user
belongs_to :board
end
I want create a new post with a parent board in my action new from posts_controllers I have:
#post = Post.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #post }
end
I create a new board with:
def create
#board = current_user.boards.new(params[:board])
respond_to do |format|
if #board.save
format.html { redirect_to #board, notice: 'Board was successfully created.' }
format.json { render json: #board, status: :created, location: #board }
else
format.html { render action: "new" }
format.json { render json: #board.errors, status: :unprocessable_entity }
end
end
end
In partial _form.thml.erb I have this:
<%= form_for(#post, :html => {:multipart => true}) do |f| %>
<%= f.label :content %><br />
<%= f.text_area :content %>
<%= f.collection_select :board_id, Board.all, :id, :name%>
<%= f.submit %>
<% end %>
The problem is that in my select field appear every boards. I want only show and choose the boards that belongs_to the current_user.
Note I'm using mongoid.
Your model can be simpler.
class User
has_many :boards, dependent: :destroy
accepts_nested_attributes_for :boards
end
class Board
has_many :posts, :dependent => :destroy , :autosave => true
belongs_to :user
accepts_nested_attributes_for :posts
end
class Post
belongs_to :board
end
<%= form_for(#post, :html => {:multipart => true}) do |f| %>
<%= f.label :content %><br />
<%= f.text_area :content %>
<%= f.collection_select :board_id, Board.find_by_user_id(current_user.id), :id, :name%>
<%= f.submit %>
<% end %>
I'm trying to add a fields_for attribute to a nested rails form. Any time I try to create a new object, it returns
Message(#58819400) expected, got
Array(#18903800) ...
app/controllers/discussions_controller.rb:53:in
`create'
If I try to access nested fields_for from forms based on non-nested resources (aka "form_for #parent" instead of "form_for [#parent, #child]" it works fine. Code below - any help with this really appreciated.
Controller:
# GET /discussions/new
# GET /discussions/new.xml
def new
#forum = Forum.find(params[:forum_id])
#discussion = Discussion.new
#discussion.messages.build
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => #discussion }
end
end
def create
#forum = Forum.find_by_id(params[:forum_id])
#discussion = #forum.discussions.new(params[:discussion])
#discussion.user = current_user
respond_to do |format|
if #discussion.save
format.html { redirect_to([#forum, #discussion], :notice => 'Discussion was successfu#ly created.') }
format.xml { render :xml => [#forum, #discussion], :status => :created, :location => #discussion }
else
format.html { render :action => "new" }
format.xml { render :xml => #discussion.errors, :status => :unprocessable_entity }
end
end
end
Models:
class Forum < ActiveRecord::Base
belongs_to :user
has_many :discussions, :dependent => :destroy
validates :title, :presence => true
accepts_nested_attributes_for :discussions, :allow_destroy => true
end
class Discussion < ActiveRecord::Base
belongs_to :user
belongs_to :forum
has_many :messages, :dependent => :destroy
validates :title, :presence => true
end
class Message < ActiveRecord::Base
belongs_to :user
validates :user, :presence => true
validates :content, :presence => true
end
The view:
<%= form_for [#forum, #discussion] do |f| %>
<% if #discussion.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#discussion.errors.count, "error") %> prohibited this discussion from being saved:</h2>
<ul>
<% #discussion.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 :messages do |builder| %>
<%= builder.label :content, "Message" %>
<%= builder.text_area :content, :rows => 10 %>
<% end %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
And finally, the routing:
resources :forums do
resources :discussions do
resources :messages
end
end
Any help with this really appreciated - I'm completely stumped.
Arghhh - really sorry folks...I just realised I'd forgot the accepts_nested_attributes_for in the discussions model, & consequently forums could access discussions, but discussions couldn't get down to messages.
Thanks anyhow.
I have two models, links and tags, associated through a third, link_tags. The following code is in my Link model.
Associations:
class Link < ActiveRecord::Base
has_many :tags, :through => :link_tags
has_many :link_tags
accepts_nested_attributes_for :tags, :allow_destroy => :false,
:reject_if => proc { |attrs| attrs.all? { |k, v| v.blank? } }
end
class Tag < ActiveRecord::Base
has_many :links, :through => :link_tags
has_many :link_tags
end
class LinkTag < ActiveRecord::Base
belongs_to :link
belongs_to :tag
end
links_controller Actions:
def new
#link = #current_user.links.build
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => #link }
end
end
def create
#link = #current_user.links.build(params[:link])
respond_to do |format|
if #link.save
flash[:notice] = 'Link was successfully created.'
format.html { redirect_to links_path }
format.xml { render :xml => #link, :status => :created, :location => #link }
else
format.html { render :action => "new" }
format.xml { render :xml => #link.errors, :status => :unprocessable_entity }
end
end
end
View code from new.html.erb:
<% form_for [current_user, #link], :url => account_links_path do |f| %>
<%= render :partial => "form", :locals => { :f => f } %>
<% end %>
And the corresponding partial:
<%= f.error_messages %>
<p>
<%= f.label :uri %><br />
<%= f.text_field :uri %>
</p>
<p>
<%= f.label :title %><br />
<%= f.text_field :title %>
</p>
<h2>Tags</h2>
<% f.fields_for :tags_attributes do |tag_form| %>
<p>
<%= tag_form.label :name, 'Tag:' %>
<%= tag_form.text_field :name %>
</p>
<% unless tag_form.object.nil? || tag_form.object.new_record? %>
<p>
<%= tag_form.label :_delete, 'Remove:' %>
<%= tag_form.check_box :_delete %>
</p>
<% end %>
<% end %>
<p>
<%= f.submit 'Update' %>
</p>
The following line of code, in the create action in the Link controller throws an error:
#link = #current_user.links.build(params[:link])
The error: Tag(#-621698598) expected, got Array(#-609734898)
Are there additional steps needed in the has_many => :through case? These seem to be the only indicated changes for the basic has_many case.
Take a look at the line of your code
<% f.fields_for :tags_attributes do |tag_form| %>
You need to use just :tags instead of :tags_attributes.
This will solve your issue
Make sure that You have build links and tags in your controller like
def new
#link = #current_user.links.build
#link.tags.build
end
I found this here on stackoverflow:
Rails nested form with has_many :through, how to edit attributes of join model?
please tell me if it worked.
In order for this to work, you need to pass in the right params hash:
params = {
:link => {
:tags_attributes => [
{:tag_one_attr => ...}, {:tag_two_attr => ...}
],
:link_attr => ...
}
}
And your controller will look like:
def create
#link = Link.create(params[:link]) # this will automatically build the rest for your
end
Try this:
<% f.fields_for :tags_attributes do |tag_form| %>
In your controller in the new action (that loads the form partial), are you building a #tag through your link?
So you should see something along the lines of:
#link = Link.new
#tag = #link.tags.build
It might be best to post the contents of the new and create action of your links_controller.
try
<% f.fields_for :tags do |tag_form| %>
(ie lose the _attributes in :tag_attributes) That's how I've usually done nested forms
You need to build a tag in your controller or in the view
def new
#link = #current_user.links.build
#link.tags.build
end
#in your view you can just use the association name
<% f.fields_for :tags do |tag_form| %>