Rails nested model form with has_one and has_many inside - ruby-on-rails

I am using a nested form with has_one and a has_many relation inside it. The problem is that the data in the association is not being saved.
Below are the models, controller and the view I am using
Sell Order Model
class SellOrder < ActiveRecord::Base
belongs_to :company
has_one :work_order, dependent: :destroy
accepts_nested_attributes_for :work_order, :reject_if => lambda { |a| a[:content].blank? }, :allow_destroy => true
end
Work Order Model
class WorkOrder < ActiveRecord::Base
belongs_to :sell_order
has_many :todos, dependent: :destroy
accepts_nested_attributes_for :todos, :reject_if => lambda { |a| a[:content].blank? }, :allow_destroy => true
end
Todo Model
class Todo < ActiveRecord::Base
belongs_to :work_order
end
Sell Order Controller
class SellOrdersController < ApplicationController
def new
#sell_order = SellOrder.new(user: current_user)
1.times {
#work_order = #sell_order.build_work_order
#work_order.todos.build
}
end
def create
#sell_order = current_company.sell_orders.new(sell_order_params)
if #sell_order.save
redirect_to [:edit, #sell_order]
else
1.times {
#work_order = #sell_order.build_work_order
#work_order.todos.build
}
render :new
end
end
private
def sell_order_params
params.require(:sell_order).permit(:some_other_attributes, work_order_attributes: [todos_attributes: [:comment, :price]])
end
end
View
= f.fields_for :work_order do |builder_work_order|
= builder_work_order.fields_for :todos do |builder|
= builder.text_field :comment, class: 'form-control'
= builder.text_field :price, class: 'form-control'
When I submit the form, only the Sell Order is saved. No data goes in work order and todo tables. Does anyone has a solution for this type of situation?
Rails version: 4.1.1
Thanks in advance.

Related

Rails: Structuring rental orders & order form in ecommerce-like setting

I was wondering if someone could help me out with an application that has some ecommerce characteristics.
Context: Via the application a bike shop chain ('chains') can rent out
bikes ('bikes'),
by picking out a bike type such as mountainbike, city bike etc. ('bike_types) and
bike options, such as helmets etc. ('bike_options')
which are dependent on the individual bike store ('bike_stores')
this rental of the bikes & options will all be captured in an order ('orders')
the relationship between orders and bikes is many-to-many, therefore I created a table to bridge this ('order_bikes')
Final notes:
Before the rental process, the chain owner first created his/her (i) bike_stores, (ii) bike_types, (iii) bikes and (iv) bike_options, this part of the application is working. Therefore, he/she only needs to select bike_types/bikes/options out of the existing inventory previously created.
I limit the scope of the question by leaving out the bike_options, this was mainly to provide some context in order to understand the db schema build up.
Error message: Unpermitted parameter: :bike_id
Code:
models
class Order < ApplicationRecord
belongs_to :bike_store
has_many :bike_types, through: :bike_store
has_many :order_bikes, inverse_of: :order, dependent: :destroy
accepts_nested_attributes_for :order_bikes, allow_destroy: true
end
class OrderBike < ApplicationRecord
belongs_to :bike
belongs_to :order
accepts_nested_attributes_for :bike
end
class Bike < ApplicationRecord
belongs_to :bike_type
validates :name, presence: true
has_many :order_bikes
has_many :orders, through: :order_bikes
end
class BikeType < ApplicationRecord
belongs_to :bike_store
has_many :bikes, dependent: :destroy
accepts_nested_attributes_for :bikes, allow_destroy: true
has_many :bike_options, dependent: :destroy
accepts_nested_attributes_for :bike_options, allow_destroy: true
validates :name, :bike_count, presence: true
end
class BikeStore < ApplicationRecord
has_many :bike_types, dependent: :destroy
has_many :orders, dependent: :destroy
end
Order controller
class OrdersController < ApplicationController
def new
#bike_store = BikeStore.find(params[:bike_store_id])
#order = Order.new
#order.order_bikes.build
#bike_type_list = #bike_store.bike_types
end
def create
#order = Order.new(order_params)
#bike_store = BikeStore.find(params[:bike_store_id])
#order.bike_store = #bike_store
#order.save
redirect_to root_path
end
private
def order_params
params.require(:order).permit(:arrival, :departure,
order_bikes_attributes: [:id, :bike_quantity, :_destroy,
bikes_attributes: [:id, :name,
bike_types_attributes: [:id, :name]]])
end
end
view
<%= simple_form_for [#bike_store, #order] do |f|%>
<%= f.simple_fields_for :order_bikes do |order_bike| %>
<%= order_bike.input :bike_quantity %>
<%= order_bike.association :bike %>
<% end %>
<%= f.input :arrival %>
<%= f.input :departure %>
<%= f.submit %>
<% end %>
If you check coed from simple form here, you will see what actually method association does.
def association(association, options = {}, &block)
# ... simple form code here ...
attribute = build_association_attribute(reflection, association, options)
input(attribute, options.merge(reflection: reflection))
end
We are interested in build_association_attribute method call. here
def build_association_attribute(reflection, association, options)
case reflection.macro
when :belongs_to
(reflection.respond_to?(:options) && reflection.options[:foreign_key]) || :"#{reflection.name}_id"
# ... the rest of code ...
end
end
Your order bike model has belongs_to :bike association. So when you call order_bike.association :bike it builds :bike_id attribute in your form. If you check params hash that comes to your controller, I believe you'll see that attribute coming from your view.
I added bike_id to permitted parameters. I hope it will fix your problem..
def order_params
params.require(:order).permit(:arrival, :departure,
order_bikes_attributes: [:id, :bike_id, :bike_quantity, :_destroy,
bikes_attributes: [:id, :name,
bike_types_attributes: [:id, :name]]])
end

Cannot save check_box_tag data with has_many through

I am trying to save checkbox data in project table
In Project Controller
def new
#project = Project.new
#allTags = Tag.all
#allBenefits = Benefit.all
end
def create
p params[:projectName]; # this always throws nil even there is a value
#project = Project.new(project_params)
##tagging = #project.tagging.create!(:project=>Project.id,:tag=>1)
if #project.save
redirect_to :action => 'index'
else
render :action => 'new'
end
end
def project_params
params.require(:com_a_b_c_project).permit(:projectName, :briefDesc, :whatSection, :challengers, :status, :valueProposal, :maturityLevel,:tag_ids =>[])
end
In Project new view
<h4><label for = "tags">Tags</label></h4>
<% #allTags.each do |tag| %>
<p><%= f.label tag.tagName %></p>
<%= check_box_tag :tag_ids, tag.id, #project.tags.include?(tag), :name => 'project[tag_ids][]'-%>
<%end%>
class Com::a::b::c::Project < ActiveRecord::Base
has_many :taggings
has_many :tags, :through => :taggings
accepts_nested_attributes_for :tags
end
class Com::a::b::c::Tag < ActiveRecord::Base
has_many :taggings
has_many :projects, :through => :taggings
end
class Com::a::b::c::Tagging < ActiveRecord::Base
belongs_to :project
belongs_to :tag
end
On my logs I get tag_ids parameter as below
project"=>{"tag_ids"=>["1", "2"]}
Q. Do I have to save data to Tagging table separately or does it automatically saves data because of the associations in the table?
Currently nothing get saved on the tagging table. How can I store tagging data?
if i follow correctly
class Com::a::b::c::Project < ActiveRecord::Base
has_many :taggings
has_many :tags, :through => :taggings
accepts_nested_attributes_for :tags
end
on project model should allow this to be persisted.

Rails 4 new record from different model

I am currently working on a rails based application to manage orders. (Rails 4.1.5 and ActiveAdmin)
I have these models:
class Customer < ActiveRecord::Base
has_many :estimates
has_many :orders
accepts_nested_attributes_for :estimates, :allow_destroy => true
accepts_nested_attributes_for :orders, :allow_destroy => true
end
class Order < ActiveRecord::Base
belongs_to :customer
has_many :line_items, as: :cartable
accepts_nested_attributes_for :line_items, :allow_destroy => true
end
class Estimate < ActiveRecord::Base
belongs_to :customer
has_many :line_items, as: :cartable
accepts_nested_attributes_for :line_items, :allow_destroy => true
end
What I want to do is to create a new Order based on the Estimate record. The things work if I create a new order and show the edit page with:
member_action :confirm, :method => :get do
old_estimate = Estimate.find(params[:id])
new_estimate = Order.create(old_estimate.attributes.merge({:id => nil, :created_at =>
nil,:updated_at => nil}))
old_estimate.line_items.each do |li|
new_estimate.line_items.create(li.attributes.merge({:id => nil, :created_at => nil,
:updated_at => nil}))
end
redirect_to edit_customer_order_path(new_estimate.customer, new_estimate)
end
but I would like to use the "new" action and create the record only after it has been edited and confirmed.
I tried to use
redirect_to new_customer_order_path(old_estimate.customer, old_estimate.attributes)
and it will render the new form but without any parameters in it.
The params are in the URL but I got an "Unpermitted parameters:" in the log. All the params are permitted under Active Admin(either under other.rb and estimate.rb) as:
permit_params :id, :customer_id, :title, :edd, :total,
line_items_attributes: [:id, :cartable_id, :cartable_type, :product_type, :source_lang, :dest_lang, :unit_price, :total, :_destroy]
Anyone have any suggestion?
You can override the new action to set some default value in the form:
controller do
def new
record = YourActiveRecordModel.new #or find, if you pass id
record.some_attribute = some_value
new!
end
end
The corresponding input will be filled.

Nested Forms error on unknown attribute Id in Rails 3

I'm attempting the nested forms based on Ryan Bates' #196 Railscasts Nested Forms 1. I'm using Nested_form and Simple_form gems. Maybe code is competing with gems?
The error that won't seem to go away is
ActiveRecord::UnknownAttributeError at /surveys/new
unknown attribute: customer_id
This occurs when I'm on the Survey page and submitting "New Survey".
I've got a Customer model and a Contact model which are associated to Survey.
It's referring to the last line in Survey Controller:
def new
12 #survey = Survey.new
13 3.times do
14 customer = #survey.customers.build
15 2.times { customer.contacts.build }
Solutions I tried include doing migrations adding the CustomerId to the Survey table or the Customer table. I've currently removed all references to customer_id.
Here's survey.rb
class Survey < ActiveRecord::Base
has_many :contacts
has_many :customers, :dependent => :destroy
accepts_nested_attributes_for :customers, :reject_if => lambda { |a| a[:content].blank? } :allow_destroy => true
attr_accessible :name, :customers_attributes
end
Here's customer.rb
class Customer < ActiveRecord::Base
belongs_to :survey
has_many :contacts
attr_accessible :company, :first_name, :last_name, :contacts_attributes, :customer_id
accepts_nested_attributes_for :contacts, :reject_if => lambda { |a| a[:content].blank? } :allow_destroy => true
end
here is contact.rb
class Contact < ActiveRecord::Base
attr_accessible :mobile_phone, :email
belongs_to :customer
end
and here's my form.html.haml
= simple_nested_form_for #survey do |f|
= f.error_notification
= f.input :name
= f.fields_for :customers do |builder|
= render "customer_fields", :f => builder
%p= f.submit "Submit"
Any help for a newbie? Thank you!!

Rails 3.2 Nested Form Custom Foreign Key Unable to Save

I have this Reviews Model:
class Review < ActiveRecord::Base
attr_accessible :approved, :reviewed_id, :for, :user_id, :text, :rating, :title
belongs_to :business
belongs_to :product
end
and this Product model:
class Product < ActiveRecord::Base
include ApplicationHelper
belongs_to :business
belongs_to :catalog
belongs_to :category
has_many :reviews, :foreign_key => :reviewed_id
has_many :features, :dependent => :destroy
end
and this Business model:
class Business < ActiveRecord::Base
validates_presence_of :name
validates_presence_of :category
mount_uploader :photo, PhotoUploader
has_many :catalogs, :dependent => :destroy
has_many :products, :dependent => :destroy
has_many :branches, :dependent => :destroy
has_many :reviews, :foreign_key => :reviewed_id
end
but with this create action in the Reviews controller:
def create
#business = Business.find(params[:business_id])
if params.has_key?('product_id')
#product = Product.find(params[:product_id])
#review = #product.reviews.build(params[:review])
if #review.save
flash[:notice] = 'Pending Review Submitted'
redirect_to business_product_path(#business, #product)
else
#form_resources = [#business, #product, #review]
respond_with(#business, #product, #review)
end
else
#review = #business.reviews.build(params[:review])
if #review.save
flash[:notice] = 'Pending Review Submitted'
redirect_to business_path(#business)
else
#form_resources = [#business, #review]
respond_with(#business, #review)
end
end
end
I can't save the association. simple_form says there is an error, but I can't see the error in my logs, and all the other fields are validated so I'm guessing there is a problem with the association.
SIDE QUESTION: how can you I make simple_form show all errors?
fixed it by using polymorphic associations and getting rid of for and reviewed_id in the reviews model. refer here:
http://guides.rubyonrails.org/association_basics.html#polymorphic-associations

Resources