I am new to Ruby and Rails. I'm try to create a "Team" object that has a leader id and an array of users attached.
Problems
I am unable to attach the array of users to the team object
I am unable to define leader object, only store its id
Any help greatly appreciated
My Rails Models:
class Team
include Mongoid::Document
include Mongoid::Timestamps::Created
include Mongoid::Timestamps::Created
field :name
field :slug
field :description
field :leader
field :users, type: Array
field :holiday_days_per_year, type: Integer
field :hours_per_day, type: Integer
field :organisation_id, type: Integer
embeds_many :users
validates :name, :holiday_days_per_year, :presence => true
validates :holiday_days_per_year, :hours_per_day, :numericality => true
before_save :set_slug
def set_slug
self.slug = "#{name.parameterize}"
end
end
class User
include Mongoid::Document
include Mongoid::Timestamps::Created
include Mongoid::Timestamps::Created
field :slug
field :first_name
field :last_name
field :birth_date, type: Date
field :job_title
field :job_start_date, type: Date
field :job_probation_ends, type: Date
field :work_email
field :work_address
field :work_phone_number
field :personal_email
field :personal_address
field :personal_phone_number
field :organisation_id, type: Integer
# emails should be unique
validates_uniqueness_of :work_email, :personal_email
validates :first_name, :last_name, :birth_date,
:job_title, :job_start_date, :job_probation_ends,
:work_address, :work_phone_number,
:personal_address, :personal_phone_number,
:presence => true
# validates emails
validates_format_of :work_email, :personal_email, :with => /\A([^#\s]+)#((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i
belongs_to :team, :inverse_of => :users
before_save :set_slug
def set_slug
self.slug = "#{first_name.parameterize}-#{last_name.parameterize}"
end
end
controller action
# POST /teams
# POST /teams.json
def create
new_params = params.permit(
:name, :holiday_days_per_year, :hours_per_day, :leader, :users)
#team = Team.new(new_params)
if #team.save
render json: #team, status: :created, location: #team
else
render json: #team.errors, status: :unprocessable_entity
end
end
JSON Sent
{
holiday_days_per_year: 20
hours_per_day: 8
leader: "522cf27114bc38307a000004"
name: "Tester"
users: [
0: "522cf27114bc38307a000004"
1: "522d966214bc38659300000d"
2: "522dd21214bc38ac6b000011"
]
}
The object is created, but users and leader dont get saved, the object comes back as
{
_id: "522df8c714bc38ef3e000022",
created_at: "2013-09-09T16:35:19.405Z",
description: null,
holiday_days_per_year: 20,
hours_per_day: 8,
leader: "522d966214bc38659300000d",
name: "Tester",
organisation_id: null,
slug: "tester",
users: [ ]
}
In your model, redefine your "as_json" method with the following
class Team < ActiveRecord::Base
..
has_many :users
def as_json(options)
{ :name=>self.name, :leader=>self.leader, :users=>self.users }
end
end
Related
I'd like to update or create the data array through the polymorphic.
class Freelancer < ActiveRecord
has_one :address, :as => :addressable
end
class Client < ActiveRecord
has_one :address, :as => :addressable
end
class Address < ActiveRecord
belongs_to :addressable, :polymorphic => true
accepts_nested_attributes_for :addressable
end
I'd like to use this kind of params on the other controller
class UserController < ApplicationController
...
def new params
params.require(:user).permit([
...
addresses_attributes: [
:id, :position, :addressable_type, :addressable_id,
addressable_attributes: [:id, :first_name, :last_name, :email]
]
])
end
end
The data from frontend is
user: {
addresses_attributes: [{
id: 1, position:0, addressable_type: 'Client', addressable_id:12,
addressable_attributes: {id: 1, first_name: 'Jone', last_name: 'Doe', email: 'jonedoe#gmail.com'}
},{
id:'', position:1, addressable_type: 'Freelancer', addressable_id:'',
addressable_attributes: {id: '', first_name: 'Jone1', last_name: 'Doe1', email: 'jonedoe1#gmail.com'}
}]
}
From this kind of data, I'd like to update it, if one of the attributes in the array has its id, and create it if it doesn't have on all tables.
How do I have to handle this?
I'm writing a recipe rails api with my database being Mongodb. I am having trouble creating POSTING a JSON post that models a recipe for example:
{
"recipe": {
"name" : "Chicken",
"serving" : "3",
"macro" : {
"protein": "3",
"carb": "10",
"fat" : "5"
},
"user_id" : "587d5dccb3e9664e280a1199",
"ingredients" : [{
"name" : "Chicken Breast",
"value" : "3.123"
}]
}
}
Ingredients is a has_many relation, and i am embedding using accepts_nested_attributes_for. It is wanting the _id of ingredients before it has been created. Its giving me this error when posting:
"#<NoMethodError: undefined method `_id' for {\"name\"=>\"Chicken Breast\", \"value\"=>\"3.123\"}:ActiveSupport::HashWithIndifferentAccess>"
Here are my models for my app:
Recipe Model:
class Recipe
include Mongoid::Document
field :name, type: String
field :serving, type: Integer
embeds_one :macro # Stores object id of macro model in recipe
has_many :ingredients, inverse_of: :recipe #Stores object id of ingredient model in an array
# has_one :preperation # Properation steps are stored as an array so one to one relationship is needed
belongs_to :user # Recipe has one user that posted a recipe
accepts_nested_attributes_for :macro
accepts_nested_attributes_for :ingredients
validates :name, :serving, presence: true
end
Macro Model:
class Macro
include Mongoid::Document
field :protein, type: Integer
field :carb, type: Integer
field :fat, type: Integer
embedded_in :recipe
validates :protein, :carb, :fat, presence: true
end
Ingredient Model:
class Ingredient
include Mongoid::Document
field :name, type: String
field :value, type: String
belongs_to :recipe, inverse_of: :ingredients
validates :name, :value, presence: true
end
This is my controller for recipes:
class Api::V1::RecipeController < ApiController
def index
#recipes = Recipe.all
render json: #recipes
end
def create
#recipe = Recipe.new(recipe_params)
if #recipe.save
render json: #recipe
else
render :json => { :errors => #recipe.errors }, :status => 422
end
end
def show
#recipe = Recipe.find(params[:id])
render json: #recipe
end
def destroy
#recipe = Recipe.find(params[:id])
#recipe.destroy
render :nothing, status: :no_content
end
private
def recipe_params
params.require(:recipe).permit(:name, :serving, :user_id, macro: [:protein, :carb, :fat], ingredients: [:name, :value])
end
end
I cant figure out why its giving me the error when posting. Thanks for some help!
I have a embedded model, Document in the embedded model can only be created by the admin, but users can select in form the value that they want
class User
include Mongoid::Document
embeds_one :state_model, class_name: "state_model", cascade_callbacks: true
accepts_nested_attributes_for :state_model
attr_accessor :current_password, :job_title_str, :state_model_id
convert_id_to_object :state_model_id, :state_model
end
class UsersController << ApplicationController
def update_params
params.require(:user).permit(:state_model_id)
end
end
module ConvertIdToObject
extend ActiveSupport::Concern
module ClassMethods
def convert_id_to_object(id, object)
id, object = id, object
if StateModel.by_id(id).present?
object = StateModel.by_id(id)
else
end
end
end
end
class StateModel
include Mongoid::Document
field :name, type: String, localize: true
field :value, type: String
scope :by_value, -> (value){ where({:value => value}) unless value == ''}
scope :by_id, -> (id){ where({:id => id}) unless id == ''}
embedded_in :user
validates :name, presence: true, uniqueness: true
validates :value, presence: true, uniqueness: true
end
= simple_form_for user do |f|
= f.input :state_model_id , collection: state_collection
= f.button :submit
Post:
{"utf8"=>"✓",
"_method"=>"patch",
"authenticity_token"=>"3/pmSUHrKRx56ycbraKYL+mEuAiS9QlwWt/bTglgsio=",
"user"=>{"state_model_id"=>"5612cb074d6f722582050000"},
"commit"=>"Update User",
"id"=>"bowtch"}
End I have a Notimplemented error raised by my usercontroller Like if don't accept state_model_id as a param ... I'm stuck here ...
I'm trying to configure the nested model's fields in :has_many association, but nothing's happening. I'm on Rails 4.2.3, mongoid 4.0.2, rails_admin 0.6.8.
Property has many Characteristics, Product has and belongs to many Characteristics:
/app/models/property.rb
class Property
include Mongoid::Document
include Mongoid::Timestamps
field :handle
field :title, localize: true
has_many :characteristics, inverse_of: :property
accepts_nested_attributes_for :characteristics, allow_destroy: true
validates :handle, presence: true
validates :title, presence: true
end
/app/models/characteristic.rb
class Characteristic
include Mongoid::Document
include Mongoid::Timestamps
field :handle
field :title, localize: true
belongs_to :property, inverse_of: :characteristics
has_and_belongs_to_many :products
validates :property, presence: true
validates :handle, presence: true
validates :title, presence: true
end
/app/models/product.rb
class Product
include Mongoid::Document
include Mongoid::Timestamps
field :handle
field :title, localize: true
field :page_title, localize: true
field :description, localize: true
field :short_description, localize: true
field :meta_description, localize: true
field :meta_keywords, localize: true
has_and_belongs_to_many :characteristics
validates :handle, presence: true
validates :title, presence: true
end
/config/initializers/rails_admin.rb
require 'i18n'
I18n.available_locales = [:ru, :en]
I18n.default_locale = :ru
RailsAdmin.config do |config|
config.main_app_name = Proc.new { |controller| [ "Babylon", "BackOffice - #{controller.params[:action].try(:titleize)}" ] }
config.actions do
dashboard
index
nestable
new
export
bulk_delete
# show
edit
delete
show_in_app
## With an audit adapter, you can add:
# history_index
# history_show
end
config.model Characteristic do
visible false
label I18n.t(:characteristic).capitalize
label_plural I18n.t(:characteristics).capitalize
object_label_method do
:i18n_characteristic
end
create do
field :title do
label I18n.t(:title)
end
end
update do
field :title do
label I18n.t(:title)
end
end
end
config.model Property do
visible true
label I18n.t(:property).capitalize
label_plural I18n.t(:properties).capitalize
object_label_method do
:i18n_property
end
list do
field :title do
label I18n.t(:title).capitalize
formatted_value do
bindings[:view].link_to value[I18n.locale], bindings[:view].rails_admin.edit_path(model_name: 'property', id: bindings[:object]._id.to_s)
end
end
field :handle do
label I18n.t(:handle).capitalize
end
end
create do
field :title do
label I18n.t(:title)
end
group I18n.t(:seo).upcase! do
field :handle do
label I18n.t(:handle)
end
end
group I18n.t(:characteristics).capitalize do
field :characteristics do
label I18n.t(:characteristics)
associated_model_config do
field :title do
label I18n.t(:title).capitalize
end
end
end
end
end
update do
field :title do
label I18n.t(:title)
end
group I18n.t(:seo).upcase! do
field :handle do
label I18n.t(:handle)
end
end
group I18n.t(:characteristics).capitalize do
field :characteristics do
label I18n.t(:characteristics)
associated_model_config do
field :title do
label I18n.t(:title).capitalize
end
end
end
end
end
end
...
end
def i18n_property
title_translations[I18n.locale]
end
def i18n_characteristic
title_translations[I18n.locale]
end
So as you see, I tried to configure fields of Characteristic model in 2 places to show only :title field, but it still shows automatically all it can grab from the model, and doesn't even translate:
Please help find a solution to display nested fields right! Thank you.
Ok, it's all because of the wrong order. To make all work properly, the order should be Property first, and only then Characteristic. I wish it was mentioned in official readme.
class Order
include Mongoid::Document
include Mongoid::Timestamps
#relationships
embeds_one :user_detail
#fields
field :description
#validations
validates :user_detail, presence: true
end
This the embedded object in order:
class UserDetail
include Mongoid::Document
include Mongoid::Timestamps
#fields
field :name, :type => String
field :zip_code, :type => String
field :email, :type => String
# Relationships
embedded_in :order
#validations
validates_presence_of :name, :zip_code, :email
end
I want save/persist on mongodb order object with user_detail object embedded_in order object.
I have tried with:
order = Order.new(description: "checking description")
order.user_detail = Order.new(:name => "John", :zip_code => "26545", :email => "john#john.com")
order.save!
but I get validation fail:
o.save!
Mongoid::Errors::Validations:
Problem:
Validation of Order failed.
Summary:
The following errors were found: User detail is invalid
Resolution:
Try persisting the document with valid data or remove the validations....
How can I fix this problem? I'm using mongoid 3.x
Should be:
order = Order.new(description: "checking description")
order.user_detail = UserDetail.new(:name => "John", :zip_code => "26545", :email => "john#john.com")
order.save!
You had Order.new for OrderDetail.new
You do not need to manually create user_detail using
order.user_detail = UserDetail.new...
order.save!
The embedded user_detail will be created automatically if u add autobuild attribute
embeds_one :user_detail autobuild: true
If u wanna persist user_detail in database as well, do not forget to add
validates_presence_of :user_detail
or you will not see the persisted user_detail in mongo db.