I am trying to validate that the "Never" radio button is selected, or "Date" (with datepicker) is selected with a date, hence :expiry_date.
:expires is a string type.
:expiry_date is a date type.
f.input :expires, as: :radio, :collection => ["Never", "Date"]
f.input :expiry_date, as: :string, :wrapper_html => { :class => "date_picker"}
This is my validations so far.
validates :expires,
inclusion: { in: ["Never", "Date"],
presence: { message: "none selected"}}
validates :expiry_date, presence: true
You can use a custom validation:
class Food < ActiveRecord::Base
validate :has_expiry_date
def has_expiry_date
if expires == "Date" && !expiry_date.present?
errors.add(:expiry_date, 'needs to be present if food expires')
end
end
end
I have form fields from one model status_history that I am including in my member edit. I am wanting to make it so that if the fields for status_history are empty, then it will not save. Currently it is saving blank items to status_history when I save a members edit.
My member form looks like this
form(:html => { :multipart => true }) do |f|
f.semantic_errors *f.object.errors.keys
columns do
column do
...
end
column do
f.inputs "Status" do
f.semantic_fields_for :status_histories, StatusHistory.new do |sh|
sh.inputs :class => "" do
sh.input :status, as: :select, collection: {Active: "active", Inactive: "inactive", Separated: "separated"}
sh.input :date, :as => :datepicker
sh.input :reason
end
end
table_for member.status_histories do
column "status" do |status_histories|
status_histories.status
end
column "date" do |status_histories|
status_histories.date
end
column "reason" do |status_histories|
status_histories.reason
end
end
end
...
end
end
f.actions
end
models/status_histories
class StatusHistory < ActiveRecord::Base
belongs_to :member
STATUS_TYPES = [ "active", "inactive", "separated" ]
validates :status, inclusion: STATUS_TYPES
validates :date, :presence => true
validates :reason, :presence => true
end
Even adding a button that would toggle the semantic_fields_for would work but currently if I leave them blank I get validates errors.
How would I override the save method to check if status and date are present and if so save the status_history and if not, do not save the status_history but save the rest of the member fields?
Try this:
in Member ActiveRecord model
accept_nested_attributes_for :status_histories, reject_if: :all_blank
http://apidock.com/rails/ActiveRecord/NestedAttributes/ClassMethods/accepts_nested_attributes_for
Let me explain first my model structure:
i have a status model:
class Status
include Mongoid::Document
include Mongoid::Search
include Mongoid::Timestamps
field :status_code, type: Integer
field :status_description, type: String
validates :status_code, :status_description, :transactiontype, :presence => true
belongs_to :transactiontype, :class_name => 'Transactiontype'
has_many :transactions, :class_name => 'Transaction', autosave: false
search_in :status_code, :status_description, :transactiontype => :transaction
def self.getStatus(transactiontype)
statuses = Status.where(:transactiontype_id => transactiontype).all
stats = []
puts "DATE DASHBOARD: #{Time.now.beginning_of_day} to #{Time.now.end_of_day}"
statuses.each do |status|
transactions = status.transactions.dateRange(Date.today.beginning_of_day, Date.today.end_of_day)
if transactions.length > 0
status.transactions = transactions
stats.push(status)
end
end
puts "SIZE : #{stats.size}"
stats
end
etc..
end
then i have another model called transactions:
class Transaction
include Mongoid::Document
include Mongoid::Search
include Mongoid::Timestamps
field :ref_no, type: String
field :trans_date, type: DateTime
belongs_to :status, :class_name => 'Status'
belongs_to :transactiontype, :class_name => 'Transactiontype'
validates :ref_no, :trans_date, :status, :presence => true
def self.dateRange(startdate,enddate)
puts "DATE : #{startdate} to #{enddate}"
if !startdate.blank?
where(:created_at => {"$gt" => startdate.beginning_of_day, "$lt" => enddate.end_of_day})
# where(:trans_date.gte => startdate.beginning_of_day, :trans_date.lte => enddate.end_of_day)
end
end
etc..
end
the weird part is that:
when im trying to execute:
Status.getStatus(params[:transactiontype_id])
i received the correct output but the transactions associated with the Status is being updated and each records before the filtered date is being updated with null status_id.
i already tried to add autosave: false but nothing works
can someone help me with this?
the solution is to convert the active record to json first
def self.getStatus(transactiontype)
statuses = Status.where(:transactiontype_id => transactiontype).all
stats = []
puts "DATE DASHBOARD: #{Time.now.beginning_of_day} to #{Time.now.end_of_day}"
statuses.each do |status|
ar_status = status.as_json
ar_status['transactions'] = status.transactions.dateRange(Date.today.beginning_of_day, Date.today.end_of_day)
if ar_status['transactions'].length > 0
stats.push(ar_status)
end
end
puts "SIZE : #{stats.size}"
stats
end
for some reason.. its auto saving the records.
I am trying to use a select tag to save multiple nested children in a parent.
This is the error I'm looking at
Couldn't find all UserLocations with IDs (1, 2) (found 0 results, but was looking for 2)
I have the following setup under Rails 4 and Devise:
User
class User < ActiveRecord::Base
has_many :user_locations
accepts_nested_attributes_for :user_locations, :allow_destroy => true
end
UserLocation (locations that the user has)
class UserLocation < ActiveRecord::Base
belongs_to :user
belongs_to :location
end
Location (predefined list of locations the user can choose upon)
class Location < ActiveRecord::Base
has_many :user_locations
has_many :users, through: :user_locations
end
However, when trying to save the selected UserLocations, they won't be saved.
Rails Select Tag (You can choose multiple items)
<%= f.select :user_location_ids, options_for_select(Location.all.collect { |l| [ l.name, l.id ] }, #user.user_locations.collect{ |l| l.id }), {}, { multiple: true } %>
I have put the user_location_ids in my application_controller as user_location_ids: []
Cheers
Solved
The solution is to overwrite the default setter method for multiple nested models model_ids=(value). Do not use the plural of the model, e.g. models_ids=(value), because that is wrong!
def user_location_ids=(value)
for slot in value do
unless slot == ""
location = Location.find_by(id: slot.to_i)
unless location.nil?
self.user_locations << UserLocation.create(user_id: self.id, location_id: location.id)
end
end
end
end
I'm having trouble with embeds in a mongoid4-based rails 4 app. I've been looking for an answer everywhere for the past 2 days. So here is the code.
This is a church management app, with a Service model, embedding a team and a band. Each team/band has several roles such as "presidence", "communion" that refer to a user.
My models :
class Service
include Mongoid::Document
...
embeds_one :team, autobuild: true
embeds_one :band, autobuild: true
...
accepts_nested_attributes_for :team, :band
end
class Team
include Mongoid::Document
embedded_in :service
has_one :presidence, :class_name => 'User', autosave: true
has_one :message, :class_name => 'User', autosave: true
...
end
class Band
include Mongoid::Document
has_one :lead, :class_name => 'User', autosave: true
has_one :guitar, :class_name => 'User', autosave: true
...
embedded_in :service
end
class User
include Mongoid::Document
embeds_one :profile
belongs_to :team, :inverse_of => :presidence
belongs_to :team, :inverse_of => :message
belongs_to :band, :inverse_of => :lead
belongs_to :band, :inverse_of => :guitar
def fullname
"#{profile.firstname} #{profile.lastname}"
end
def self.find_by_talent(talent)
self.where("profile.talents.name" => talent)
end
end
The services controller :
# POST /services
# POST /services.json
def create
#service = Service.new(service_params)
respond_to do |format|
if #service.save
format.html { redirect_to #service, notice: 'Service was successfully created.' }
format.json { render action: 'show', status: :created, location: #service }
else
format.html { render action: 'new' }
format.json { render json: #service.errors, status: :unprocessable_entity }
end
end
end
...
def service_params
params.require(:service).permit(:date, :time, :place, :name, :theme, :team => [:id, :precedence, :message ], :band => [:id, :lead, :guitar ])
end
And the form in _form.html.erb :
<%= form_for(#service) do |f| %>
...
<%= f.fields_for #service.team do |tf| %>
<%= tf.collection_select :presidence, User.find_by_talent(:presidence), :_id, :fullname, {:include_blank => "select a person"} %>
<%= tf.collection_select :message, User.find_by_talent(:message), :id, :fullname, {:include_blank => "select a person"} %>
<% end %>
<%= f.fields_for #service.band do |bf| %>
<%= bf.collection_select :lead, User.find_by_talent(:lead), :id, :fullname, {:include_blank => "select a person"} %>
<%= bf.collection_select :guitar, User.find_by_talent(:guitar), :id, :fullname, {:include_blank => "select a person"} %>
<% end %>
...
<% end %>
When creating a service, everything seems to run fine, but this is what I get in the console :
2.0.0-p195 :001 > s = Service.last
=> #<Service _id: 52ea18834d61631e7e020000, date: "2014-02-02", time: "10:00", place: "Where it's at", name: "My great name", theme: "The service's theme">
2.0.0-p195 :002 > s.team
=> #<Team _id: 52ea18834d61631e7e030000, >
2.0.0-p195 :003 > s.team.presidence
=> nil
Why is s.team.presidence not created ? s.team looks weird, too, with an ending comma...
Here is the content of my rails log :
Started POST "/services" for 127.0.0.1 at 2014-01-30 10:16:51 +0100
Processing by ServicesController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"Ph6lbdHC2FbiANn/fGSzHWprenj3fWKXM40Hrsc5+AM=", "service"=>{"date"=>"2014-02-02", "name"=>"My great name", "theme"=>"The service's theme", "time"=>"10:00", "place"=>"Where it's at", "team"=>{"presidence"=>"52ea18324d61631e81010000", "message"=>"52ea18324d61631e81010000"}, "band"=>{"lead"=>"52ea18324d61631e81010000", "guitar"=>"52ea18324d61631e81010000"}}, "commit"=>"Create Service"}
MOPED: 127.0.0.1:27017 COMMAND database=admin command={:ismaster=>1} runtime: 0.6610ms
MOPED: 127.0.0.1:27017 UPDATE database=service_boot_camp_development collection=users selector={"band_id"=>BSON::ObjectId('52ea18834d61631e7e010000'), "_id"=>{"$nin"=>[]}} update={"$set"=>{"band_id"=>nil}} flags=[:multi]
COMMAND database=service_boot_camp_development command={:getlasterror=>1, :w=>1} runtime: 0.5800ms
MOPED: 127.0.0.1:27017 INSERT database=service_boot_camp_development collection=services documents=[{"_id"=>BSON::ObjectId('52ea18834d61631e7e020000'), "date"=>"2014-02-02", "time"=>"10:00", "place"=>"Where it's at", "name"=>"My great name", "theme"=>"The service's theme", "team"=>{"_id"=>BSON::ObjectId('52ea18834d61631e7e030000')}, "band"=>{"_id"=>BSON::ObjectId('52ea18834d61631e7e010000')}}] flags=[]
COMMAND database=service_boot_camp_development command={:getlasterror=>1, :w=>1} runtime: 2.7460ms
I guess I'm doing something wrong, but I have no clue if it is in the database model or in the form... or anything else...
You will not be able to do it this way. When you create an embedded document, its _id and all of its data are embedded directly within the parent document. This is in contrast to an association, where the document with the belongs_to gets a foreign key which points to its associated parent document. So here, your User documents each have a team_id and band_id, but when the database tries to get the documents, it can't find them, since you can't query directly for embedded documents; you need the parent document first. For more, see the Mongoid documentation.
Another potential issue is that you have multiple belongs_to definitions in the User models. This will also cause an issue, because for each one of those, Mongoid will attempt to create a team_id and band_id. You should name them separately and specify a class name; perhaps names like :presiding_team and :message_team, :lead_band and :guitar_band, etc. This answer should show you what that would look like.
I would recommend making the Team and Band separate referenced documents instead of embedded documents, since you won't be able to reference users effectively while they're embedded.
Hope this helps.