Filter on "include" - Rails 3 - ruby-on-rails

these are my associations:
class Activity < ActiveRecord::Base
has_many :infos, :dependent => :destroy
has_many :events, :dependent => :destroy
accepts_nested_attributes_for :infos
end
class Event < ActiveRecord::Base
belongs_to :activity
has_many :infos, :through => :activity
end
class Info < ActiveRecord::Base
has_one :language
belongs_to :activity
end
Now i can get an XML with all the events and their infos using:
#events = Event.all
respond_to do |format|
format.xml { render :xml => #events.to_xml(:include => [:infos ]) }
end
The problem is that i get the infos from all the language.
Is it possible to use a filter (as "where info.language.id==1"), so that only the language1 infos are displayed in the XML for each event?
Thanks
UPDATE :
Hi Mike, thanks for your answer.
Unfortunately i'm getting this error:
undefined method `eq' for nil:NilClass
Rails.root: /Users/abramo/village
Application Trace | Framework Trace |
Full Trace
app/controllers/events_controller.rb:29:in
block (2 levels) in locale'
app/controllers/events_controller.rb:28:in
locale'
and lines 28,29 are the last line of my locale method:
def locale
#events = Event.joins(:infos => :language).where("languages.id = 2")
respond_to do |format|
format.xml { render :xml => #events.to_xml(:include => [:infos ]) }
end
end
I really don't understand... what object is Nil?

Event.joins(:infos => :language).where("languages.id = 1")

Related

Rails Active Record Query and JSON

I have the following models in my Rails application:
class Transaction
belongs_to :category
has_one :group, :through => :category
class Category
belongs_to :group
has_many :transactions
class Group
has_many :categories
has_many :transactions, :through => :category
In my controller is the following:
#transactions = Transaction.includes(:category, :group).group("groups.id").sum("amount")
respond_to do |format|
format.json{
render :json => JSON.generate(#transactions.as_json(:include => [:category, :group]))
}
end
This produces the following json (A):
{"1":2000,"3":5000,"2":1000}
However, my goal is to produce something like this (B):
[{"group_id":1,"amount":2000},{"group_id":3,"amount":5000},{"group_id":2,"amount":1000}]
Any help on how I can go from A to B would be greatly appreciated.
Try:
def user_transactions
#transactions = Transaction.includes(:category, :group).group("groups.id").sum("amount")
respond_to do |format|
format.html
format.json do
render :json => custom_json_for(#transactions)
end
end
end
private
def custom_json_for(value)
list = value.map do |k,v|
{ :group_id => k,
:amount=> v
}
end
list.to_json
end
If you're doing a lot a JSON-serialization, I would recommend you to take a look at ActiveModelSerializers:
https://github.com/rails-api/active_model_serializers

Rails 3.1 build association

So I have a flow model and a page model
Each flow has_many pages and each page belongs_to a flow
Flow model
class Flow < ActiveRecord::Base
has_many :pages, :dependent => :destroy
accepts_nested_attributes_for :pages, :reject_if => lambda { |p| p[:path].blank?}, :allow_destroy => true
end
Page model
class Page < ActiveRecord::Base
belongs_to :flow
end
Then in the new flow action I have this
def new
#flow = Flow.new
3.times do
page = #flow.pages.build
end
respond_to do |format|
format.html # new.html.erb
format.json { render json: #flow }
end
end
but I keep getting the error: "unknown attribute: flow_id"?
Use generate migration add_flow_id_to_page flow_id:integer to generate the foreign key column.

'distance' field gets dropped when using Geokit with acts_as_mappable :through

We know that the distance field gets dropped when using the Geokit gem in Rails with acts_as_mappable :through model class. I wonder if there's a way to work around this to get the distance field back. I tried to follow the monkey-patching example over here:
http://www.sobyteme.com/news/2010/05/13/computers/2010/06/25/geokit-acts_as_mappable-through-with-distance-attribute/
but it didn't work for me.
Well, Steve's suggestion over on his site was accurate, I was missing calling sort_by_distance_from after doing the find. So credit goes to him for this answer.
I'm on Rails v3.0.7. Here's my code:
class Office < ActiveRecord::Base
has_many :users
acts_as_mappable :default_units => :miles,
:default_formula => :sphere,
:lat_column_name => :latitude,
:lng_column_name => :longitude
end
class User < ActiveRecord::Base
belongs_to :office
acts_as_mappable :through => :office
end
users_controller.rb:
# Monkey patching to include the 'distance' attribute
module Geokit
module Mappable
def to_lat_lng
return self if instance_of?(Geokit::LatLng) || instance_of?(Geokit::GeoLoc)
return LatLng.new(self.office.send(self.office.class.lat_column_name),
self.office.send(self.office.class.lng_column_name)) if self.class.respond_to?(:acts_as_mappable)
nil
end
end
end
class UsersController < ApplicationController
def location
#lat = params[:lat].to_f
#long = params[:long].to_f
#origin = [#lat, #long]
#users = User.find(:all,
:origin => #origin,
:conditions => "distance < 3")
# We have to add this to get the 'distance' field
#users.sort_by_distance_from(#origin)
respond_to do |format|
format.html
format.xml { render :xml => #users.to_xml(:methods => :distance)}
format.json { render :json => #users.to_json(:methods => :distance)}
end
end
...
end

Updating nested forms with existing data in inner form using rails 3

I'm trying to get a nested form view to update properly. This is however causing problems when the second form has existing data.
I'm using accepts_nested_attributes_for and nested_form_for. The second which only purpose is to dynamically add the form element using js. See github for more
The error I'm getting is:
Couldn't find Muscle with ID=3685340 for Exercise with ID=212831413
I've tried to manually do the updating but my code didnt really work and I'm under the impression that it shouldnt be needed since rails is suppose to take care of it under the hood.
The idea is that: Exercises has many Muscles through Targets
And from within the Exercise form I want to be able to add target muscles.
My models:
class Exercise < ActiveRecord::Base
has_many :targets, :dependent => :destroy
has_many :muscles, :through => :targets
accepts_nested_attributes_for :muscles, :reject_if => :all_blank
...
end
class Target < ActiveRecord::Base
belongs_to :exercise
accepts_nested_attributes_for :exercise, :update_only => true
belongs_to :muscle
end
class Muscle < ActiveRecord::Base
has_many :targets, :dependent => :destroy
has_many :exercises, :through => :targets
end
My (haml) view:
%p
%b Target(s):
= f.fields_for :muscles do |e|
= e.collection_select :id, Muscle.all, :id, :name
= e.link_to_remove "-remove"
= f.link_to_add "Add target muscle", :muscles
And finally my failing controller:
def update
#exercise = Exercise.find(params[:id])
#exercise.user = current_user
params[:exercise][:muscles_attributes].each { |id, muscle|
target = Target.where(:exercise_id => #exercise.id , :muscle_id => muscle[:id]).first
if target && !(muscle[:_destroy] == "false")
puts "!!>>>>>>>>>>>>>>>>>>destroy target #{target.exercise_id} #{target.muscle_id}"
target.destroy
else
if !target
t = #exercise.targets.build(:muscle_id => muscle[:id])
t.save
end
end
}
respond_to do |format|
if #exercise.update_attributes(params[:exercise])
format.html { redirect_to(#exercise, :notice => 'Exercise was successfully updated.') }
format.xml { head :ok }
else
format.html { render :action => "edit" }
format.xml { render :xml => #exercise.errors, :status => :unprocessable_entity }
end
end
end
Please let me know if I should expose more of my code (the final result will be opensource anyway) ill happily push to github or whatever is requested, thanks in advance.
You could achieve this by manipulating the intermediate table, here targets.
Insert in your model:
accepts_nested_attributes_for :targets
And in your html, append this line with javascript:
<input name="exercise[targets_attributes][0][muscle_id]" value="the_muscle_id_goes_here" type="hidden">

Rails many to many token fields help

I am having that problem that my model dont want to save. I have a token field input for tags.
I have followed this guide for the token input: http://railscasts.com/episodes/258-token-fields
I get this error when I try to create a new konkurrancer:
NoMethodError in Admin/konkurrancersController#create
undefined method `class_name' for nil:NilClass
Rails.root: C:/Rails/konkurranceportalen
Application Trace | Framework Trace | Full Trace
app/models/konkurrancer.rb:15:in `tag_tokens='
app/controllers/admin/konkurrancers_controller.rb:48:in `new'
app/controllers/admin/konkurrancers_controller.rb:48:in `create'
http://pastie.org/1834194
Request
Parameters:
{"utf8"=>"✓",
"authenticity_token"=>"yo7wcAQl81tx3zZpPP44ENPYzYRZLpgyYKY+HK3yFKM=",
"konkurrancer"=>{"name"=>"Vind en rejse",
"banner2"=>"asdasd",
"tracking"=>"sadasd",
"vaerdi"=>"12222",
"tid"=>"1 min",
"tag_tokens"=>"1",
"bedom"=>"2",
"kategori_id"=>"9",
"form"=>"Nyhedsbrev",
"partner"=>"Iqmedier",
"udtraekkes(3i)"=>"30",
"udtraekkes(2i)"=>"4",
"udtraekkes(1i)"=>"2011",
"udtraekkes(4i)"=>"08",
"udtraekkes(5i)"=>"26",
"arrangeor"=>"",
"note"=>""},
"commit"=>"Opret konkurrence"}
My konkurrancer model:
class Konkurrancer < ActiveRecord::Base
attr_accessible :name, :tag_tokens
has_many :tagsmenus
has_many :tags, :through => :tagsmenus
attr_reader :tag_tokens
def tag_tokens=(ids)
self.tag_ids = ids.split(",")
end
end
My tag model:
class Tag < ActiveRecord::Base
has_many :tagsmenus
has_many :konkurrancers, :through => :tagsmenus
has_friendly_id :name, :use_slug => true
before_save :assign_cached_slug, :unless => :cached_slug?
protected
def assign_cached_slug
self.cached_slug = self.name.gsub(/\s+/, '_').gsub(/[^\w\-]/, '')
end
end
My tagmenu model:
class Tagsmenu < ActiveRecord::Base
end
My controller:
def new
#konkurrancer = Konkurrancer.new
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => #konkurrancer }
end
end
# POST /konkurrancers
# POST /konkurrancers.xml
def create
#konkurrancer = Konkurrancer.new(params[:konkurrancer])
respond_to do |format|
if #konkurrancer.save
format.html { redirect_to(:admin_konkurrancers, :notice => 'Konkurrancer was successfully created.') }
format.xml { render :xml => :admin_konkurrancers, :status => :created, :location => #konkurrancer }
else
format.html { render :action => "new" }
format.xml { render :xml => #konkurrancer.errors, :status => :unprocessable_entity }
end
end
end
I have created the join table and the model and also added the relation to my tag model.
Your model has some conflicting statements. You first define:
attr_accessor ... :tag_tokens
then later have:
attr_reader :tag_tokens
which is not necessary given the first line or vice versa given that later you have a deinition for the setter:
def tag_tokens(ids)
self.tag_ids = ids.split(',')
end
I don't see tag_ids defined either given it is not a column in your table. You should probably remove the attr_accessor definition for the tag_tokens and then define the tag_ids method for starters.
class Tagsmenu < ActiveRecord::Base
belongs_to :konkurrancer
belongs_to :tag
end

Resources