How to define has_and_belongs_to association in rails - ruby-on-rails

I am following this video http://railscasts.com/episodes/258-token-fields-revised and i implement this also sucessfully. But now i am using namespace.
I have lends_controller inside folder employee inside asset folder.
this is my model of lend controller
class Employee::Asset::Lend
include Mongoid::Document
include Mongoid::Timestamps
field :name, type: String
field :text, type: String
field :date
field :asset_tokens
field :user_id, type: String
has_and_belongs_to_many :assets
belongs_to :tags
def asset_tokens=(tokens)
self.asset_ids = Asset.ids_from_tokens(tokens)
end
end
Now i have another model asset. There i have to define has and belongs to this lend model also I did this
class Asset
include Mongoid::Document
field :name, type: String
field :description, type: String
field :serial_number, type: String
field :status, type: Integer
field :tag_tokens
field :quantity, type: Integer
validates_presence_of :name
validates :serial_number,:uniqueness => true
has_and_belongs_to_many :employee_asset_lends
has_and_belongs_to_many :tags
def self.tokens(query)
assets = where(name: /#{Regexp.escape(query)}/i)
end
form for lend controller is
<%= f.label :asset_tokens, "Assets" %>
<%= f.text_field :asset_tokens, data: {load: #employee_asset_lend.assets}%><br>
<%= f.input :date,:input_html => { :class => "dp1"},:label=> "Lend Date"%>
inside coffescript file for lend.js.coffee
jQuery ->
$('#employee_asset_lend_asset_tokens').tokenInput '/assets.json'
theme: 'facebook'
prePopulate: $('#employee_asset_lend_asset_tokens').data('load')
But it gives error uninitialized constant EmployeeAssetLend from asset views.
and from lend view it gives error like undefined methodall_of' for Employee::Asset:Module`

pleaes check the right way to make HABTM-has_and_belongs_to_many Assosiation for more details

Related

How to change model owner in Ruby in rails?

I use Ruby on rails and mongoid.
I have two models User.rb and Project.rb. If I want to change owner of Project model, how should I do this?
User.rb
class User
include Mongoid::Document
field :name, type: String
has_many :projects, dependent: :destroy
end
Project.rb
class Project
include Mongoid::Document
field :title, type: String
validates :user_id, presence: true
belongs_to :user, touch: true
end
in form.html.erb i have select mode
<div class="form-group">
<%= f.collection_select :user_id, User.all, :id, :name, class: 'form-control' %>
</div>
you should be able to just assign it to the user field and then save it to persist it to the database
project = Project.find(project_id)
new_owner = User.find(new_owner_id)
project.user = new_owner
project.save
i did not use mongoid long time ago, but you can try running these commands on your rails console:
project.user = owner_object;
project.save
OR
project.user_id = owner_id
project.save

Rails Mongoid : Query embedded document and access to Mongoid criteria

I have an application where users can create many travels, and they can invite their facebook friends. In the travel document, there is a field "participants" that is an embedded document, Participant model embedded in Travel model.
Here are my models :
class Travel
include Mongoid::Document
include Mongoid::Timestamps
# relations
belongs_to :user
# fields
field :title, type: String
field :description, type: String
field :begin_date, type: Date
field :end_date, type: Date
field :budget, type: Integer
field :go_back, type: Boolean
field :title_namespace, type: String
# friends
embeds_many :participants
accepts_nested_attributes_for :participants
end
class Participant
include Mongoid::Document
include Mongoid::Timestamps
field :name, type: String
field :user_id, type: String
# relations
embedded_in :travel, :inverse_of => :participants
end
When I try to display travel where users have been invited, with this request :
#travel_participations = Travel.where('participants.user_id' => #user.id)
I don't have any result, even if I have this line in byebug :
#<Mongoid::Criteria
selector: {"participants.user_id"=>BSON::ObjectId('592c8da58511989ec850921e')}
options: {}
class: Travel
embedded: false>
So when I put this on my view :
<% unless #participations.nil? %>
<% #travel_participations.each do |travel_participation| %>
<p> <%= travel_participation.title %> </p>
<% end %>
<% end %>
I tried with .all, .first, .to_a, .as_json, no results ... Some one know where is the problem ?
You have this in your embedded model:
field :user_id, type: String
but your query is using a BSON::ObjectId:
Travel.where('participants.user_id' => #user.id)
as shown in the raw query:
selector: {"participants.user_id"=>BSON::ObjectId('592c8da58511989ec850921e')}
Your embedded document probably has a string field like:
"user_id": "592c8da58511989ec850921e"
rather than the ObjectId you're looking for:
"user_id": ObjectId("592c8da58511989ec850921e")
so you won't find what you're looking for due to the type mismatch.
Either fix the embedded field's type:
field :user_id, type: BSON::ObjectId
or query it as the string it is:
Travel.where('participants.user_id' => #user.id.to_s)
Changing the type will involve fix up whatever data you already have, changing the query is ugly in a different way.
Sometimes Mongoid will convert between strings and ObjectIds for you, sometimes it won't. When I used Mongoid I patched to_bson_id methods into BSON::ObjectId, String, Mongoid::Document, ... so that I could say things like:
Model.where(:some_id => some_id.to_bson_id)
and not have to constantly worry about what type some_id was. I also made sure that all ID fields were always specified as BSON::ObjectId.

Links between class rails

I'm new to rails and in my project I have 2 classes who have a relationship betwen them. The problem is they dont can list services with organs. The following is the code I have:
modelos
class Admin::Organ
include Mongoid::Document
include Mongoid::Search
include Mongoid::Pagination
field :name, type: String
field :address, type: String
field :acronym, type: String
field :phones, type: String
field :emails, type: String
field :image, type: String
field :permalink, type: String
field :schedules, type: Array
field :coordinates, type: Hash
has_many :services, class_name: "Service"
has_many :units, class_name: "Admin::Unit"
before_save :touch_permalink
search_in :name
paginates_per 10
def url
"/orgao/#{permalink}"
end
private
def touch_permalink
self.permalink = self.name.parameterize
end
end
class Service
include Mongoid::Document
include Mongoid::Search
include Mongoid::Pagination
field :name, type: String
field :acronym, type: String
field :popular_names, type: Array
field :description, type: String
field :free, type: Boolean
field :applicants, type: Array
field :estimated_time, type: Hash
field :steps, type: Array
field :permalink, type: String
field :other_informations, type: String
belongs_to :organ, class_name: "Admin::Organ"
has_and_belongs_to_many :units, class_name: "Admin::Unit"
has_and_belongs_to_many :audiences, class_name: "Admin::Audience"
has_and_belongs_to_many :categories, class_name: "Admin::Category"
before_save :touch_permalink
search_in :name, :popular_names
paginates_per 10
def organ_id
read_attribute(:organ_id).to_s
end
def url
"/servico/#{permalink}"
end
private
def touch_permalink
self.permalink = self.name.parameterize
end
end
#controlers
class ServicesController < ApplicationController
def index
#organs = Admin::Organ.all
#services = Service.page(params[:page].to_i).per(3)
end
def show
#service = Service.where(permalink: params[:permalink]).first
end
end
class OrgansController < ApplicationController
def index
#organs = Admin::Organ.page(params[:page]).per(2)
end
def show
#organ = Admin::Organ.where(permalink: params[:permalink]).first
#organs = Admin::Organ.page(params[:page]).per(1)
end
end
#call in index.html
<%= organs.services.name%>
This appears to be returning an error whenever I run it
Note: On mongo relationships when you call a relationship method (such as services in your case) all of the documents associated with it are returned. Also for the pagination plugin you are using (I'm assuming kaminari by the syntax), this will return a collection of documents as well.
If so, it could be expected that you have a view for organs that has something a little like this:
<% #organs.each do |organ| %>
<div>Name: <%= organ.name %></div>
<div>Address: <%= organ.address %></div>
<div>Services:</div>
<% organ.services.each do |service| %>
<div>Name: <%= service.name %></div>
<div>Acronym: <%= service.acronym %></div>
<% end %>
<% end %>
<%= paginate #organs %>
You'll notice that to print out the services you need to first have a handle on the current document within #organs, and then you need to iterate the services within it. If you were to call name (which is a method of a relationship) you will get the relationship name (I believe this is what you are seeing).
I hope this helps. I had to do some guessing between the lines, come back to me if you need any further help.

Rails, Active admin, nested form, dynamic label value - issue with the form object

I have three models:
class Request < ActiveRecord::Base
belongs_to :scenario
belongs_to :location
has_many :actions, :foreign_key => 'request_id'
accepts_nested_attributes_for :actions, :allow_destroy => true
end
class Action < ActiveRecord::Base
belongs_to :request
belongs_to :scenario_step
end
class ScenarioStep < ActiveRecord::Base
belongs_to :scenario
has_many :actions
end
Using Active Admin I want to update information about action taken in response to a request. To do that I am using nested form:
ActiveAdmin.register Request do
permit_params :scenario_id, :location_id,
actions_attributes: [:scenario_step_id, :description]
form(:html => {:multipart => true}) do |f|
f.inputs "Request details" do
f.input :status
panel 'Steps' do
"Text ..."
end
f.has_many :actions, heading: 'Steps to follow', allow_destroy: false, new_record: true do |ff|
ff.input :description, label: ff.object.scenario_step_id, hint: 'Text'
ff.input :scenario_step_id
end
para "Press cancel to return to the list without saving."
f.actions
end
end
end
Everything seems to be fine except of label (or hint). As a value I want to put there related data from a table scenario_steps.
As you can see I currently try to at least print the value of scenario_step_id that should be available in the object form (ff.object.scenario_step_id) but it is not working (I have such column in actions table). On the other hand, next line: ff.input :scenario_step_id loads appropriate data into input field.
Can somebody give ma a hint what am I doing wrong?
Here is what I was missing (part of formtastic documentation):
Values for labels/hints/actions are can take values: String (explicit
value), Symbol (i18n-lookup-key relative to the current "type", e.g.
actions:), true (force I18n lookup), false (force no I18n lookup).
Titles (legends) can only take: String and Symbol - true/false have no
meaning.
So small change (to_s) in line below makes huge difference :)
ff.input :description, label: ff.object.scenario_step_id.to_s, hint: 'Text'

Why doesn't mongoid add my nested attributes on new()?

I can't seem to figure out why Mongoid won't set the nested attributes for a child object when I create a new parent. I want to create a new Folio, add one child Feature, then push it on the Folios array on Profile.
I have a Profile, which embed many Folios, which embed many Features:
class Profile
include Mongoid::Document
include Mongoid::Timestamps::Updated
#regular fields here; removed for brevity
embeds_many :folios, class_name: "Folio"
end
class Folio
include Mongoid::Document
include Mongoid::Timestamps::Updated
accepts_nested_attributes_for :features
embedded_in :profile
field :name
field :desc
field :order, type: Integer, default:0
embeds_many :features
attr_accessible :name, :desc, :order
end
class Feature
include Mongoid::Document
include Mongoid::Timestamps::Updated
embedded_in :folio
belongs_to :project
field :content_type, type: Integer #ContentType
field :content_id
field :txt, type: String
field :order, type: Integer, default:0
attr_accessible :project_id, :content_type, :content_id, :txt, :order
end
Controller:
def new
#folio = Folio.new
#folio.features.build
end
def create
#folio = Folio.new(params[:folio])
##folio.features is still empty here.
#profile.folios << #folio
#profile.save
render "create_or_update.js"
end
In create, the param hash looks good:
{"folio"=>{"id"=>"new", "name"=>"new name", "desc"=>"new description", "features_attributes"=>{"0"=>{"project_id"=>"4ea0b68e291ebb44a100000a", "content_type"=>"1", "content_id"=>"4ea0b68e291ebb44a100000d", "txt"=>"note here"}}}, "commit"=>"Save", "action"=>"create", "controller"=>"folios"}
But #folio.features is still empty.
This worked fine with AR, if I remember. Strangely, there is no features_attributes=() method on Folio. I thought that was required for the nested attributes to work? What am I missing?
This is on Rails 3.1 with Mongoid 2.2.3.
have you tried enabling AutoSave true for features in Folio document
class Folio
include Mongoid::Document
include Mongoid::Timestamps::Updated
accepts_nested_attributes_for :features , :autosave => true
embedded_in :profile
end

Resources