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
Related
I'm getting the following error when I attempt to submit my nested form.
Cannot modify association 'Appointment#addresses' because the source reflection class 'Address' is associated to 'User' via :has_many
I'm not entirely sure which part of my setup is wrong. To briefly explain, I have Users that have multiple Appointments and multiple Addresses. Each Appointment can happen at a different Address, which is why I'm doing a :has_many association through user (which is correct, right?). Why am I getting this error?
Here are my models:
class User < ActiveRecord::Base
has_many :addresses, dependent: :destroy
has_many :appointments, dependent: :destroy
end
class Appointment < ActiveRecord::Base
belongs_to :user
has_many :addresses, :through => :user
accepts_nested_attributes_for :addresses
end
class Address < ActiveRecord::Base
belongs_to :user
end
And this is the create method from my Appointments controller:
class AppointmentsController < ApplicationController
...
def create
#appointment = current_user.appointments.build(appointment_params)
#address = #appointment.addresses.build(appointment_params[:addresses_attributes]["0"])
respond_to do |format|
if #appointment.save
format.html { redirect_to current_user, notice: 'Appointment was successfully created.' }
format.json { render :show, status: :created, location: current_user }
else
format.html { render :new }
format.json { render json: #appointment.errors, status: :unprocessable_entity }
end
end
end
...
private
def appointment_params
params.require(:appointment).permit(:appointment_date, :appointment_start_time, :appointment_end_time, :comments, :phone_number, addresses_attributes: [:user_id, :street_address, :street_address_optional, :city, :state, :zip_code, :primary])
end
end
And finally, this is my form in my view:
<%= form_for(#appointment, :url => {:controller => "appointments", :action => "create"}, :html => {"data-abide" => ""}) do |f| %>
<label>
Appointment Date
</label>
<%= f.date_select :appointment_date %>
<label>
Appointment Timeframe Start
</label>
<%= f.time_select :appointment_start_time %>
<label>
Appointment Timeframe End
</label>
<%= f.time_select :appointment_end_time %>
<%= f.fields_for :addresses do |builder| %>
<%= builder.hidden_field :user_id, :value => current_user.id %>
<label>
Street Address
<%= builder.text_field :street_address %>
</label>
<label>
Street Address (Optional)
<%= builder.text_field :street_address_optional %>
</label>
<label>
City
<%= builder.text_field :city %>
</label>
<label>
State
<%= builder.text_field :state %>
</label>
<label>
Zip Code
<%= builder.number_field :zip_code %>
</label>
<%= builder.check_box :primary %><%= builder.label :primary %>
<% end %>
<label>
Special Instructions
<%= f.text_area :comments %>
</label>
<%= f.submit "Sign Up", :class => "button expand"%>
<% end %>
Thanks in advance for the help :)
A user can have many appointments, but each one is in one address. (unless he can multilocate himself).
So you should do:
class User
has_many :appointments
class Appointment
has_one :address
class Address
belongs_to :appointments
If you want to retrieve the addresses in which the user has appointments you have to do:
#addresses = current_user.appointments.map {|app| app.address}
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 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 %>
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
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.