Nested Attributes for Mongoid has_one relationship - ruby

I am trying to create a contact which is a has_one relation to a client. I am doing this with nested attributes. I am properly building the contact within the "new" view/controller. When I go to save the contact it is telling me the contact must be present. So for some reason it is not creating the contact.
ERROR:
Validation failed - Contact can't be blank.
Params:
{
"utf8"=>"✓",
"authenticity_token"=>"ep6es356WY5dja7D7C5Kj8Qc0Yvuh3IN2Z1iGG08J7c=",
"client"=>{
"contact_attributes"=>{
"first_name"=>"Scott",
"last_name"=>"Baute"
},
"commit"=>"Create Client"
}
Models:
class Client
include Mongoid::Document
include Mongoid::Timestamps
attr_accessible :role, :contact_id, :contact_attributes
# Relationships
belongs_to :firm, validate: true
has_one :contact, validate: true, autosave: true
# Matters is custom relationship
has_many :client_roles
# Nested Attr
accepts_nested_attributes_for :contact
validates :contact_id, presence: true
# Fields
field :contact_id
field :test
end
class Contact
include Mongoid::Document
include Mongoid::Timestamps
include Mongoid::MultiParameterAttributes
#Relationships
belongs_to :client
field :first_name
field :last_name
end
Controller:
# GET /clients/new
# GET /clients/new.json
def new
#client = current_firm.clients.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #client }
end
end
# POST /clients
# POST /clients.json
def create
#client = current_firm.clients.new(params[:client])
respond_to do |format|
if #client.save!
format.html { redirect_to client_path(#client.contact.id), notice: 'Client was successfully created.' }
format.json { render json: #client, status: :created, location: #client }
else
format.html { render action: "new" }
format.json { render json: #client.errors, status: :unprocessable_entity }
end
end
end
View:
- #client.build_contact unless #client_contact
= semantic_form_for #client, html: { class: "form-horizontal"} do |f|
.control-group
= render "contact_fields", f: builder
.form-actions
= f.submit class: "btn btn-primary"

I think you need delete your reference to contact_id in your Client model. The has_one association do the foreign_key in your contact. Not in your client. So when you create a contact from client, only a client_id is define in your contact no contact_id in your client.
So delete line :
validates :contact_id, presence: true
# Fields
field :contact_id
in your Client model.

Related

Rails Paperclip - Duplicating the attachment file name in another field

I've got the following table:
create_table "documents", force: true do |t|
t.string "title"
t.integer "subject_id"
t.datetime "created_at"
t.datetime "updated_at"
t.string "attachment_file_name"
t.string "attachment_content_type"
t.integer "attachment_file_size"
t.datetime "attachment_updated_at"
end
Whenever I upload a file (using Paperclip), I want to duplicate the param of 'attachment_file_name' to 'title'.
This app is an API, but I'm using a debugs_controller to test it.
DebugsController
class DebugsController < ApplicationController
def index
#document = Document.new
#documents = Document.all
#subject = Subject.new
end
end
debugs/index.html.erb
<form action="http://0.0.0.0:3000/documents" method="POST" enctype="multipart/form-data">
<input name="document[title]" type="text" placeholder="doc naam">
<input name='document[attachment]' type="file">
<input name="document[subject_id]" type="text" placeholder="Subject id">
<input type="submit">
</form>
DocumentsController
class DocumentsController < ApplicationController
before_action :set_document, only: [:show, :update, :destroy]
skip_before_action :verify_authenticity_token
respond_to :json
def index
#documents = Document.all
end
def new
#document = Document.new
#documents = Document.all
end
def show
end
def create
#document = Document.new(document_params)
#document.title = params[:attachment].original_filename
if #document.save
respond_with(#document, status: :created)
else
respond_with(#document, status: 403)
end
end
def update
if #document.update(document_params)
respond_with(#document)
else
respond_with(#document.errors, status: :unprocessable_entity)
end
end
def destroy
#document.destroy
respond_with(#document, status: :destroyed)
end
private
def set_document
#document = Document.find(params[:id])
end
def document_params
params.require(:document).permit(:title, :attachment, :subject_id)
end
end
Document.rb
class Document < ActiveRecord::Base
belongs_to :subject
has_many :notes
has_attached_file :attachment, url: '/system/:attachment/:id_partition/:basename.:extension'
validates_attachment :attachment, presence: {
message: 'You have to upload a file!' }, content_type: {
content_type: %w( application/pdf ), message: 'PDF files only.' }, size: {
in: 0..10.megabytes, message: 'The maximum file-size is 10MB.' }
validates :subject_id, presence: { message: 'Assign your document to a case!' }
end
This outputs 'undefined method `original_filename' for nil:NilClass' for me.
Params:
{"document"=>{"title"=>"",
"attachment"=>#<ActionDispatch::Http::UploadedFile:0x007fbcea87c518 #tempfile=#<Tempfile:/var/folders/sy/9v_t59x974qg_m2nvmcyvkjr0000gn/T/RackMultipart20141202-14285-z5aj46>,
#original_filename="Teamsweet.pdf",
#content_type="application/pdf",
#headers="Content-Disposition: form-data; name=\"document[attachment]\"; filename=\"Teamsweet.pdf\"\r\nContent-Type: application/pdf\r\n">,
"subject_id"=>"1"},
"format"=>:json}
Does anyone know how I can duplicate the contents of the 'attachment_file_name' to the 'title' field of Documents? Also; is it possible to remove the extention of the uploaded file in the process of duplicating the file name?
You can do that in the model instead of in the controller.
class Document < ActiveRecord::Base
before_save :set_title
def set_title
self.title = self.attachment_file_name
end
...
end

Ruby on Rails : Tricky Many to Many relationship does not work

I am designing a "Lists" mapping feature in my application for transcoding purposes.
So that my mappins_list object points to a source_list object and a target_list object, both being of an instance values_list class.
The design looks classical, but it does not behave as expected:
<td><%= link_to #mappings_list.source_list.name, #mappings_list.source_list%>
raises a
undefined method `source_list' for #<ActiveRecord::Relation::ActiveRecord_Relation_MappingsList:0x00000004217718>
in the index view.
(note that one record was crated with correct attributes, it should be displayed there)
Here is the code:
# == Schema Information
#
# Table name: values_lists
#
# id :integer not null, primary key
# playground_id :integer
# code :string(255)
# name :string(255)
# description :text
# created_by :string(255)
# updated_by :string(255)
# owner_id :integer
# table_name :string(255)
# created_at :datetime
# updated_at :datetime
# software_id :integer
# software_name :string(255)
#
class ValuesList < ActiveRecord::Base
### scope
scope :pgnd, ->(my_pgnd) { where "playground_id=?", my_pgnd }
### before filter
before_create :set_code
### validation
validates :code, length: { maximum: 100 }
validates :name, presence: true, uniqueness: true, length: { maximum: 100 }
validates :description, length: { maximum: 1000 }
validates :created_by , presence: true
validates :updated_by, presence: true
validates :playground_id, presence: true
belongs_to :playground
validates :playground, presence: true # validates that the playground exists
belongs_to :owner, :class_name => "User", :foreign_key => "owner_id" # helps retrieving the owner name
belongs_to :software, :class_name => "Parameter", :foreign_key => "software_id" # helps retrieving the software name
has_many :values
has_many :mappings_lists
### private functions definitions
private
### before filters
def set_code
self.code = name.gsub(/[^0-9A-Za-z]/, '_').upcase
end
end
.
# == Schema Information
#
# Table name: mappings_lists
#
# id :integer not null, primary key
# playground_id :integer
# code :string(255)
# name :string(255)
# description :text
# created_by :string(255)
# updated_by :string(255)
# owner_id :integer
# source_list_id :integer
# target_list_id :integer
# created_at :datetime
# updated_at :datetime
#
class MappingsList < ActiveRecord::Base
### scope
scope :pgnd, ->(my_pgnd) { where "playground_id=?", my_pgnd }
### before filter
before_create :set_code
### validation
validates :name, presence: true, uniqueness: true, length: { maximum: 100 }
validates :description, length: { maximum: 1000 }
validates :created_by , presence: true
validates :updated_by, presence: true
validates :playground_id, presence: true
belongs_to :playground
validates :playground, presence: true # validates that the playground exists
belongs_to :owner, :class_name => "User", :foreign_key => "owner_id" # helps retrieving the owner name
belongs_to :source_list, :class_name => "ValuesList", :foreign_key => "source_list_id" # helps retrieving the source list name
belongs_to :target_list, :class_name => "ValuesList", :foreign_key => "target_list_id" # helps retrieving the target list name
has_many :mappings
### private functions definitions
private
### before filters
def set_code
self.code = "#{source_list.code}_TO_#{target_list.code}"
end
end
routes contains this:
resources :values_lists do
resources :values
resources :mappings_lists
end
The controller is here:
class MappingsListsController < ApplicationController
# Check for active session
before_action :signed_in_user
# Retrieve current current mapping
before_action :set_mappings_list, only: [:show, :edit, :update, :destroy]
# Retrieve all lists of values
before_action :set_values_lists
# GET /mappings_list
# GET /mappings_list.json
def index
#mappings_list = MappingsList.pgnd(current_playground).order("name")
end
# GET /mappings_list/1
# GET /mappings_list/1.json
def show
### Retrieved by Callback function
end
# GET /mappings_list/new
def new
#mappings_list = MappingsList.new
end
# GET /mappings_list/1/edit
def edit
### Retrieved by Callback function
end
# POST /mappings_list
# POST /mappings_list.json
def create
#mappings_list = MappingsList.new(mappings_list_params)
#mappings_list.updated_by = current_user.login
#mappings_list.created_by = current_user.login
#mappings_list.playground_id = current_user.current_playground_id
#mappings_list.owner_id = current_user.id
respond_to do |format|
if #mappings_list.save
format.html { redirect_to #mappings_list, notice: 'List of mappings was successfully created.' }
format.json { render action: 'show', status: :created, location: #mappings_list }
else
format.html { render action: 'new' }
format.json { render json: #mappings_list.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /mappings_list/1
# PATCH/PUT /mappings_list/1.json
def update
### Retrieved by Callback function
#mappings_list.updated_by = current_user.login
respond_to do |format|
if #mappings_list.update(mappings_list_params)
format.html { redirect_to #mappings_list, notice: 'List of mappings was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #mappings_list.errors, status: :unprocessable_entity }
end
end
end
# DELETE /mappings_list/1
# DELETE /mappings_list/1.json
def destroy
### Retrieved by Callback function
#mappings_list.destroy
respond_to do |format|
format.html { redirect_to mappings_lists_url }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
# Check for active session
def signed_in_user
redirect_to signin_url, notice: "You must log in to access this page." unless signed_in?
end
def set_mappings_list
#mappings_list = MappingsList.pgnd(current_playground).find(params[:id])
end
# retrieve the list of values lists
def set_values_lists
#lists_of_values = ValuesList.all
end
# Never trust mappings from the scary internet, only allow the white list through.
def mappings_list_params
params.require(:mappings_list).permit(:name, :description, :source_list_id, :target_list_id)
end
end
Would the double reference to values_list turn my application into trouble ?
Thanks for your help,
Best regards,
Fred
In the class MappingsList < ActiveRecord::Base model
you have MappingList belonging to source_list.
which I believe is backwards:
class Order < ActiveRecord::Base
belongs_to :customer
end
#order = #customer.orders
OK, I got it !!!
In the index view, I cannot refer to one instance variable such as #mappings_list as I work on a list of instances.
The code works fine with :
<td><%= link_to mappings_list.source_list.name, mappings_list.source_list%>
Being a beginner at RoR, I hope my interpretation is right ...
Thanks for your help,
Best regards,
Fred

Rails 4 ActiveModel::MissingAttributeError in OrdersController#create

I m trying to build a shopping cart for a website. I have the cart working so you can add to the cart. The problem I am having is when I try and checkout items in the cart and try to submit my order. I am getting the following error:
ActiveModel::MissingAttributeError in OrdersController#create
along with
can't write unknown attribute `order_id'
The problem is highlighting this piece of code in my orders_controller.rb file
respond_to do |format|
if #order.save
Cart.destroy(session[:cart_id]) session[:cart_id] = nil
I just cant seem to fix this error.
Below is the create method in my orders_controller.rb file
def create
#order = Order.new(order_params)
#order.add_line_items_from_cart(#cart)
respond_to do |format|
if #order.save
Cart.destroy(session[:cart_id])
session[:cart_id] = nil
format.html { redirect_to store_url,
notice: 'Thank you for your order.' }
format.json { render action: 'show', status: :created, location: #order }
else
format.html { render action: 'new' }
format.json { render json: #order.errors, status: :unprocessable_entity }
end
end
end
my migration file
class AddOrderToLineItem < ActiveRecord::Migration
def change
add_column :line_items, :order, :reference
end
end
my order.rb model
class Order < ActiveRecord::Base
has_many :line_items, dependent: :destroy
validates :name, :address, :email, presence: true
PAYMENT_TYPES = [ "Check", "Credit card", "Purchase order" ]
validates :pay_type, inclusion: PAYMENT_TYPES
def add_line_items_from_cart(cart)
cart.line_items.each do |item|
item.cart_id = nil
line_items << item
end
end
end
migration order table
class CreateOrders < ActiveRecord::Migration
def change
create_table :orders do |t|
t.string :name
t.text :address
t.string :email
t.string :pay_type
t.timestamps
end
end
end
Ok, I think I see the problem. Your migration for orders in line items probably didn't create the order_id column you expected, it probably created an orders column or something.
Verify that this is the case in the database. If so, undo your previous migration and try this instead:
class AddOrderToLineItem < ActiveRecord::Migration
def change
add_column :line_items, :order_id, :int
end
end
If not, please respond to this answer.

how to use sunspot_mongo

In my application i have created a model under mongoDB, then i reindexed it to solr using sunspot_mongo. I want to search from solr,
My model is,
`require 'sunspot_mongo'
class Post
include Mongoid::Document
include Sunspot::Mongo
field :title
field :content
field :author, type: String
searchable do
text :title, :stored => true
text :content
end
end`
and my controller index method is,
def index
##posts = Post.all
search=Post.search do
fulltext 'hello'
end
#posts = search.results
respond_to do |format|
format.html # index.html.erb
format.json { render json: #posts }
end
end
but it showing error as,
uninitialized constant Sunspot::Mongo::DataAccessor::BSON
i couldn't fix this error
i used this in gem file
gem "sunspot_mongo", :git => "git://github.com/balexand/sunspot_mongo.git", :branch => "fix_rake_sunspot_reindex"
your model looks fine
change your controller code as below
def index
search=Post.solr_search do
fulltext params[:search]
end
#posts = search.results
respond_to do |format|
format.html # index.html.erb
format.json { render json: #posts }
end
end

Mongoid _destroy is not deleted embedded document using nested_form gem

I am on Rails 3.1, Mongoid 2.3.3, and using the nested_form gem. In my form, I have the nested_form link_to_add and link_to_remove set up to add and remove an embedded document in my model. The link_to_add helper method works great, but the link_to_remove help method changes are not persisted in MongoDB. In the rails output, I can see the JSON parameter passed to Mongoid has the _destroy: 1 value set but the change is not saved to MongoDB.
Here is the Model:
class MenuItem
include Mongoid::Document
include Mongoid::Timestamps
field :name
attr_accessible :name
embeds_many :ingredient_infos
accepts_nested_attributes_for :ingredient_infos, :allow_destory => true
attr_accessible :ingredient_infos_attributes
end
Here is the Controller's update method:
def update
#menu_item = MenuItem.find(params[:id])
respond_to do |format|
if #menu_item.update_attributes(params[:menu_item])
format.html { redirect_to #menu_item, notice: 'Menu item was successfully updated.' }
format.json { head :ok }
else
format.html { render action: "edit" }
format.json { render json: #menu_item.errors, status: :unprocessable_entity }
end
end
end
Here is the parameters sent to the controller:
{
"utf8"=>"✓",
"authenticity_token"=>"5abAWfFCr7hkzYXBEss75qlq8DMQ0pW5ltGmrgHwPjQ=",
"menu_item"=>
{
"name"=>"Bowl",
"ingredient_infos_attributes"=>
{
"0"=>
{
"ingredient"=>"Rice",
"_destroy"=>"false",
"id"=>"4eb1b0b118d72f1a26000022"
},
"1"=>
{
"ingredient"=>"Chicken",
"_destroy"=>"1",
"id"=>"4eb1b0b118d72f1a26000025"
}
}
},
"commit"=>"Update Menu item",
"id"=>"4eb1b0b118d72f1a2600001f"
}
In MongoDB, the Chicken document still exists; that document also shows up in the view online (the page pulls all the items in the embedded document).
I'm sure I missed something, but I haven't been able to figure out why the embedded document isn't removed.
yes, your :allow_destory should be :allow_destroy
I am experiencing the same issue -
RESOLVED with
accepts_nested_attributes_for :phones, :allow_destroy => true

Resources