Access a child "current" object in rabl - ruby-on-rails

I want to get the object the child node is referering to, so I can make a query.
My code looks like this:
child #course_types => :course_types do |course_type|
attributes :id, :name, :deleted
child CourseTypeCategory.where(course_type: course_type, active: true) => :category_position do
attributes :category_id, :position
end
end
The result of this query CourseTypeCategory.where(course_type: course_type, active: true) is always returning the same result as if course_type was always the same each type it is rendered (in this case I suspect is always the first object of #course_types). Is there a way to get the "current object" of the child and make a query like if you were doing a loop (like an each do)?
Thanks in advance and sorry if the question is confusing.

Try this.
child #course_types => :course_type do
attributes :id, :name, :deleted
node(:course_type_category) do |course_type|
CourseTypeCategory.where(course_type: course_type, active: true).collect do |category|
{category_id: category.id, position: category.position }
end
end
end
Sorry for so little information on this, I'm kind in a hurry.

Related

mutliple select dropdown company and save perk and respective company

here is my code:
Perk not save on multiple select,when multiple true/false. perk save and habtm working.
class Perk < ActiveRecord::Base
has_and_belongs_to_many :companies
end
class Company < ActiveRecord::Base
has_and_belongs_to_many :perks
end
view perk/new.html.erb
<%= select_tag "company_id", options_from_collection_for_select(Company.all, 'id', 'name',#perk.companies.map{ |j| j.id }), :multiple => true %>
<%= f.text_field :name %>
Controller's code:
def new
#perk = Perk.new
respond_with(#perk)
end
def create
#perk = Perk.new(perk_params)
#companies = Company.where(:id => params[:company_id])
#perk << #companies
respond_with(#perk)
end
Your select_tag should return an array of company_ids:
<%= select_tag "company_ids[]", options_from_collection_for_select(Company.all, 'id', 'name',#perk.companies.map{ |j| j.id }), :multiple => true %>
http://apidock.com/rails/ActionView/Helpers/FormTagHelper/select_tag#691-sending-an-array-of-multiple-options
Then, in your controller, reference the company_ids param:
#companies = Company.where(:id => params[:company_ids])
(I assume that you've intentionally left out the #perk.save call in your create action... Otherwise, that should be included as well. Model.new doesn't store the record.)
It sounds like you may not have included company_id in the perk_params method in your controller. Rails four uses strong pramas this means you need to state the params you are allowing to be set.However it is difficult to say for sure without seeing more of the code.
In your controller you should see a method like this (there may be more options that just :name):
def perk_params
params.require(:perk).permit(:name)
end
You should try adding :company_id to it so it looks something like this:
def perk_params
params.require(:perk).permit(:name, :company_id)
end
if there are other params int your method leave them in and just added :company_id
EDIT to original answer
The above will only work on a one-to-many or one-to-one because you are using has_and_belongs_to_many you will need to add companies: [] to the end of your params list like this
def perk_params
params.require(:perk).permit(:name, companies: [] )
end
or like this
def perk_params
params.require(:perk).permit(:name, companies_ids: [] )
end
See these links for more details:
http://edgeapi.rubyonrails.org/classes/ActionController/StrongParameters.html
http://edgeguides.rubyonrails.org/action_controller_overview.html#strong-parameters

Getting rails3-autocomplete-jquery gem to work nicely with Simple_Form with multiple inputs

So I am trying to implement multiple autocomplete using this gem and simple_form and am getting an error.
I tried this:
<%= f.input_field :neighborhood_id, collection: Neighborhood.order(:name), :url => autocomplete_neighborhood_name_searches_path, :as => :autocomplete, 'data-delimiter' => ',', :multiple => true, :class => "span8" %>
This is the error I get:
undefined method `to_i' for ["Alley Park, Madison"]:Array
In my params, it is sending this in neighborhood_id:
"search"=>{"neighborhood_id"=>["Alley Park, Madison"],
So it isn't even using the IDs for those values.
Does anyone have any ideas?
Edit 1:
In response to #jvnill's question, I am not explicitly doing anything with params[:search] in the controller. A search creates a new record, and is searching listings.
In my Searches Controller, create action, I am simply doing this:
#search = Search.create!(params[:search])
Then my search.rb (i.e. search model) has this:
def listings
#listings ||= find_listings
end
private
def find_listings
key = "%#{keywords}%"
listings = Listing.order(:headline)
listings = listings.includes(:neighborhood).where("listings.headline like ? or neighborhoods.name like ?", key, key) if keywords.present?
listings = listings.where(neighborhood_id: neighborhood_id) if neighborhood_id.present?
#truncated for brevity
listings
end
First of all, this would be easier if the form is returning the ids instead of the name of the neighborhood. I haven't used the gem yet so I'm not familiar how it works. Reading on the readme says that it will return ids but i don't know why you're only getting names. I'm sure once you figure out how to return the ids, you'll be able to change the code below to suit that.
You need to create a join table between a neighborhood and a search. Let's call that search_neighborhoods.
rails g model search_neighborhood neighborhood_id:integer search_id:integer
# dont forget to add indexes in the migration
After that, you'd want to setup your models.
# search.rb
has_many :search_neighborhoods
has_many :neighborhoods, through: :search_neighborhoods
# search_neighborhood.rb
belongs_to :search
belongs_to :neighborhood
# neighborhood.rb
has_many :search_neighborhoods
has_many :searches, through: :search_neighborhoods
Now that we've setup the associations, we need to setup the setters and the attributes
# search.rb
attr_accessible :neighborhood_names
# this will return a list of neighborhood names which is usefull with prepopulating
def neighborhood_names
neighborhoods.map(&:name).join(',')
end
# we will use this to find the ids of the neighborhoods given their names
# this will be called when you call create!
def neighborhood_names=(names)
names.split(',').each do |name|
next if name.blank?
if neighborhood = Neighborhood.find_by_name(name)
search_neighborhoods.build neighborhood_id: neighborhood.id
end
end
end
# view
# you need to change your autocomplete to use the getter method
<%= f.input :neighborhood_names, url: autocomplete_neighborhood_name_searches_path, as: :autocomplete, input_html: { data: { delimiter: ',', multiple: true, class: "span8" } %>
last but not the least is to update find_listings
def find_listings
key = "%#{keywords}%"
listings = Listing.order(:headline).includes(:neighborhood)
if keywords.present?
listings = listings.where("listings.headline LIKE :key OR neighborhoods.name LIKE :key", { key: "#{keywords}")
end
if neighborhoods.exists?
listings = listings.where(neighborhood_id: neighborhood_ids)
end
listings
end
And that's it :)
UPDATE: using f.input_field
# view
<%= f.input_field :neighborhood_names, url: autocomplete_neighborhood_name_searches_path, as: :autocomplete, data: { delimiter: ',' }, multiple: true, class: "span8" %>
# model
# we need to put [0] because it returns an array with a single element containing
# the string of comma separated neighborhoods
def neighborhood_names=(names)
names[0].split(',').each do |name|
next if name.blank?
if neighborhood = Neighborhood.find_by_name(name)
search_neighborhoods.build neighborhood_id: neighborhood.id
end
end
end
Your problem is how you're collecting values from the neighborhood Model
Neighborhood.order(:name)
will return an array of names, you need to also collect the id, but just display the names
use collect and pass a block, I beleive this might owrk for you
Neighborhood.collect {|n| [n.name, n.id]}
Declare a scope on the Neighborhood class to order it by name if you like to get theat functionality back, as that behavior also belongs in the model anyhow.
edit>
To add a scope/class method to neighborhood model, you'd typically do soemthing like this
scope :desc, where("name DESC")
Than you can write something like:
Neighborhood.desc.all
which will return an array, thus allowing the .collect but there are other way to get those name and id attributes recognized by the select option.

Rails: .create nullifies a custom value for :id

When I execute a Model.create method, if I specify a value for :id, it later gets nullified. Example:
Model.create (
:id => 50,
:name => Joe,
:enabled => yes
)
Instead what I have to do is use a .new and store it in a class variable, store my id value via the class variable, and then finally call a save:
m = Model.new (
:name => Joe,
:enabled => yes
)
m.id = 50
m.save
I am trying to execute this code in a seeds.rb, and this is NOT very DRY code. How can I do this better and achieve the same results?
id is just attr_protected. To prevent that, you can override the list of default protected attributes. Be careful doing this anywhere that attribute information can come from the outside. The id field is default protected for a reason.
class Model < ActiveRecord::Base
private
def attributes_protected_by_default
[]
end
end
or go with #Leo answer
This might be an answer for you. Model.create is basically a Model.new followed by a Model.save and since you are changing the id and saving again you might as well do
m = Model.new {
:name => Joe,
:enabled => yes
}
m.id = 50
m.save!
That will rid you of doing two saves.

Outputting a serialized object in Rails

In Rails 2.3.6 I'm storing some serialized data in a database field.
My "feed_event.data" field in my database is stored as text and is (for example) equal to:
{:post=>{:pic=>"http://s3.amazonaws.com/criticalcity/datas/3524/big_thumb/send-a-letter.jpg", :name=>"Un’istruzione perfetta", :id=>1995, :authors=>"Delilah"}, :user=>{:pic=>"http://s3.amazonaws.com/criticalcity/avatars/537/thumb/DSCN2744.JPG", :name=>"Luci!", :id=>537}}
Now I need to output this field as a string (exactly as it is in the database), but when I ask:
puts feed_event.data
outputs:
postpichttp://s3.amazonaws.com/criticalcity/datas/3524/big_thumb/send-a-letter.jpgnameUn’istruzione perfettaid1995authorsDelilahuserpichttp://s3.amazonaws.com/criticalcity/avatars/537/thumb/DSCN2744.JPGnameLuci!
Why?
How can I output it as a yaml string?
UPDATE
In order to create it I have this in my FeedEvent model:
class FeedEvent < ActiveRecord::Base
has_many :user_feed_events, :dependent => :destroy
has_many :users, :through => :user_feed_events
serialize :data
end
And in order to create a new FeedEvent element I do:
feed = FeedEvent.create(:event_type => "comment #{commentable_type}", :type_id => id, :data => {:user => {:id => user.id, :name => user.name, :pic => user.avatar.url(:thumb)}, :comment => {:id => id, :body => body, :commentable_id => commentable_id, :commentable_type => :commentable_type, :commentable_name => commentable.name}})
UPDATE #2
following nzifnab's hint I used the .to_yaml method, but what Rails outputs in this case is:
data: "--- \n:post: \n :pic: http://s3.amazonaws.com/criticalcity/datas/3524/big_thumb/send-a-letter.jpg\n :authors: Delilah\n :name: \"Un\\xE2\\x80\\x99istruzione perfetta\"\n :id: 1995\n:user: \n :pic: http://s3.amazonaws.com/criticalcity/avatars/537/thumb/DSCN2744.JPG\n :name: Luci!\n :id: 537\n"
Also commenting "serialize :data" in the model outputs the same.
Thanks,
Augusto
When you call feed_data.data rails has automatically de-serialized your string. You could print it out like this:
feed_data.data.inspect to get the ruby hash representation as a string, but since it's already de-serialized it for you do you need to do anything else?
you can call everything on it like feed_data.data[:post][:pic]
I'm not sure what method you can use to grab the raw serialized string from the record, but usually you don't need to.
By default, serialization is made in a Hash.
Simply loop it to display it's content:
<% feed_event.data.each do |key, value| %>
<%= "#{key}: #{value}" %>
<% end %>
I'm just unsure about nesting level here but you've got the idea.
as you mentioned in your Update, the right way to do this is to put "serialize :data" in your model.
Then, you can access the data attribute as a Hash, that's the default, and it gets automatically persisted when you save your object.
Important Note:
One important thing for this to work is that you define the database field as text or string -- not as a binary field -- otherwise this will not work correctly!

Can't save collection_select to object

I'm going crazy here.
I have:
class Course
belongs_to :commune
end
and
class Commune
has_many :courses
end
In the new view for Course I have a drop down where the user selects commune:
f.collection_select(:commune, get_commune_list, :id, :commune, { :prompt => true })
(The get_commune_list is a helper method that returns a list of Commune objects)
But when I try to save it I either get this error:
Commune(#2176182100) expected, got String(#2148246520)
or the Commune isn't saved on the Course object at all.
The parameters look like this:
{"course"=>{"price"=>"6000",
"title"=>"Some title",
"commune"=>"10",
...
}
I just can'† figure out why this won't work!
Shouldn't it be?
f.collection_select (:commune, :commune_id, get_commune_list, :id, :commune, { :prompt => true })

Resources