A bit of difficulty handling multiple children associations for posting to another rails application via Httparty gem.
From the sending application:
:parent has_many :kids
:kid has_many :schools
#parent = Parent(parent_params)
#parent = HTTParty.post("http://localhost:3001/parents/import",
:body => { :parent_id => #parent.id,
:terms_accepted => #parent.terms_accepted,
:email => #parent.email,
:kids => {
#parent.kid.school.name => #parent.kid.school_name,
#parent.kid.age => #parent.kid.age
}
}.to_json,
:headers => { 'Content-Type' => 'application/json' } )
The receiving application has the same relationship
:parent has_many :kids
the combination of array of kids and the use of singular and plural in the post syntax is throwing me off...
The console is showing:
"kids_attributes" => {"0"=>{"age"=>"10", "school_id"=>"8"}, "1"=>{"age"=>"11", "school_id"=>"9"},
Parent has_many Kids, then its expected to have an array here, try the following:
:kids => #parent.kids.map {|kid| {:school_name => kid.school.name, :age => kid.school.age }}
Related
I need to create a route which is associated to a location.
class Location < ActiveRecord::Base
has_many :routes,:foreign_key => "origin_id"
end
and a route belongs to different locations:
class Route < ActiveRecord::Base
belongs_to :origin, :class_name => 'Location', :foreign_key => 'location_id'
belongs_to :destination, :class_name => 'Location', :foreign_key => 'destination_id'
validates :origin, :presence => {:message => 'origin cannot be blank'}
end
location.routes.create({
:destination => resort_location,
:destination_id => resort_location.id,
:total_distance => body['route_summary']['total_distance'],
:total_time => body['route_summary']['total_time'],
:raw => response.body
})
Records get create without origin and destination, even though I do have the presence validation.
Thanks for helping me out.
Code looks okay to me -
location.routes.create({
:destination => resort_location, #-> where is resort_location defined?
:destination_id => resort_location.id,
:total_distance => body['route_summary']['total_distance'],
:total_time => body['route_summary']['total_time'],
:raw => response.body
})
Your validates method also needs to be for a specific attribute (not a relation). In your case, it should be like this:
validates :location_id, presence: {message: 'You need an origin!'}
Do you have any errors / logs for this?
I'm trying to update an ActiveRecord, which seems like it SHOULD be easy enough. Methods I've tried in my
Controller (metadata_controller.rb):
def update_metadata_type
#metadata_type = MetadataType.find(params[:id])
if #metadata_type.update_attributes(params)
render :template => 'metadata/show_metadata_type'
else
# return error template
end
end
def update_metadata_type
if MetadataType.update(1, { :name => params[:name] })
render :template => 'metadata/show_metadata_type'
else
# return error template
end
end
def update_metadata_type
#metadata_type = MetadataType.find(params[:id])
#metadata_type.name = params[:name]
#metadata_type.save
render :template => 'metadata/show_metadata_type'
end
Model (metadata_type.rb):
class MetadataType < ActiveRecord::Base
has_many :metadata_type_attributes, :dependent => :destroy
has_many :attributes, :through => :metadata_type_attributes, :dependent => :destroy
attr_accessible :name, :attribute_type_id
validates :name, :uniqueness => true
end
Different model with same problem (attribute_type.rb):
class AttributeType < ActiveRecord::Base
belongs_to :attributes
attr_accessible :data_type
validates :data_type, :uniqueness => true
end
routes.rb:
match '/metadata_type/:id' => 'metadata#update_metadata_type', :via => [:put], :as => 'update_metadata_type'
Each time I'm sending the data using RESTClient, with the appropriate headers to send json, with the following data in a PUT command:
{
"name" : "NewName"
}
I've also used binding.pry in the controller to make sure #metadata_type is found (and not nil) and it always looks right:
[1] pry(#<MetadataController>)> #metadata_type = MetadataType.find(params[:id])
=> #<MetadataType id: 1, name: "Category", created_at: "2011-11-15 16:02:53", updated_at: "2011-11-15 16:02:53">
Params also looks right:
[7] pry(#<MetadataController>)> params
=> {"name"=>"NewName",
"controller"=>"metadata",
"action"=>"update_metadata_type",
"id"=>"1",
"metadatum"=>{"name"=>"NewName"}}
But for some reason, no matter how I try and save, I get the same error:
NoMethodError (undefined method `keys' for #<ActiveRecord::Relation:0x007fdfb7637fd8>):
app/controllers/metadata_controller.rb:50:in `update_metadata_type'
Any idea on what's causing this? All help is appreciated
Sorry I'm a little late to the party but you can't define an association with the name attributes as it ends up overriding the built in attributes accessor method defined and used by ActiveRecord itself.
Well hopefully this helps anyone else who happens to come across this obscure error.
The problem is with these lines:
has_many :metadata_type_attributes, :dependent => :destroy
has_many :attributes, :through => :metadata_type_attributes, :dependent => :destroy
I'm a little confused as to what exactly you're trying to do, but I suspect you mean:
has_many :attributes, :class_name => "MetadataTypeAttributes", :dependent => :destroy
I have a User model that has_many parents.
I want that user model to have one father and one mother.
So my class Parent belongs_to user
Currently I have
class User < ActiveRecord::Base
has_many :parents
has_one :father, :class_name => 'Parent', :foreign_key => 'user_id', :conditions => {:type => 'male'}
has_one :mother, :class_name => 'Parent', :foreign_key => 'user_id', :conditions => {:type => 'female'}
end
class Parent < ActiveRecord::Base
belongs_to :user
end
The problem is in my controller.
...
def edit
#user = User.find(params[:id])
#user.mother = Parent.new(:type => 'female')
#user.father = Parent.new(:type => 'male')
...
When I go into the edit, it creates and throws the 2 parents into the database without even having changed anything in the form. For example, when I click edit on a user, I go to the edit page. When I look into the database, they're already created.
My form looks like so:
= form_for #user do |f|
= f.fields_for :father do |father_form|
etc...
= f.fields_for :mother do |mother_form|
etc...
I've tried doing something alone the lines of this in my controller:
...
#user.parents.build(:type => 'male')
#user.parents.build(:type => 'female')
...
But the form doesn't show up.
Any help would be greatly appreciated.
Try to use
#user.build_father(:type => 'male')
#user.build_mother(:type => 'female')
instead of
#user.mother = Parent.new(:type => 'female')
#user.father = Parent.new(:type => 'male')
in your action
Here are my models:
class User < ActiveRecord::Base
...
belongs_to :picture, :foreign_key => 'picture_id',
:class_name => 'UploadedFile',
:dependent => :destroy
has_many :enrolled_groups, :through => :interests
...
end
class Group < ActiveRecord::Base
has_many :enrolled_users, :through => :interests,
:source => :user
end
I want to get an XML feed for my Groups with the enrolled users and their picture information.
The following line works fine (just with the enrolled users):
render :xml => #group.to_xml(:include => [:enrolled_users] )
How can I also include the picture info in the feed? I tried a bunch of things but can't figure it out... any idea?
If doing .to_xml(:include => [:enrolled_users, :picture]) doesn't work, then the hacky way would be to add (in User class):
def attributes
super.merge(:picture => picture)
end
You should be able to access nested resources by something like this:
render :xml => #group.to_xml(:include => [{:enrolled_users => :picture}])
I couldn't get it to work with the other proposed solutions. The way I ended up doing it was as follow:
In the controller:
render :xml => #group.to_xml(:include => {:enrolled_users => {:methods => :picture_url}})
In the model:
def picture_url
HOST+picture.public_filename(:avatar)
end
I have a users model and a book model. Users can read books (as a reader) which creates an entry in the Readings model:
id | reader_id | book_id
Users also have a list of books that they have read. These are stored in the Red (I use Red because the present and past tense of the word 'read' are the same) model which looks the same as the Reading model above.
Now when a user is reading a book, I would like to display a button which represents finishing the book.
The finish action is in the ReadingsController and looks like this:
def finish
#book = current_user.readings.find(params[:id]).book
current_user.stop_reading!(#book)
current_user.make_red! #book
redirect_to :back
end
As you can probably tell, this takes in the id of a record in the readings table, destroys it and makes a new record in the table for recording books red.
The form helper for the "Finish Reading" button currently looks like this:
<%= form_for :reading, current_user.readings.find_by_book_id(book.id), :url => { :controller => :readings, :action => "finish" }, :method => :delete do |f| %>
<div class="actions"><%= f.submit button_text %></div>
<% end %>
But for some reason this renders a form with the wrong id because "9781440506604" is not the id of a record in the readings table, it's the id of a record in the books table (the ISBN-13 of a book to be precise).
<form accept-charset="UTF-8" action="/readings/9781440506604/finish" method="post">
</form>
What is it I'm doing wrong?
EDIT to add reading.rb
class Reading < ActiveRecord::Base
attr_accessible :book_id
# one person reading a new book may cause feed_item creations in multiple users feeds
has_many :feed_items, :as => :event
has_many :comments, :as => :parent, :dependent => :destroy
scope :from_users_followed_by, lambda { |user| followed_by(user) }
# need to pass the class name here because there is no Reader model
belongs_to :reader, :class_name => "User"
belongs_to :book
validates :reader_id, :presence => true
validates :book_id, :presence => true
def self.followed_by(user)
...
end
end
# and user.rb
class User < ActiveRecord::Base
attr_accessible :name, :email, :password, :password_confirmation, :avatar, :remember_me, :avatar_url
has_many :readings, :dependent => :destroy,
:foreign_key => "reader_id"
has_many :reads, :through => :readings, :source => :book
has_many :reds, :foreign_key => "reader_id",
:dependent => :destroy
has_many :red, :through => :reds, :source => :book
def reading? book
self.readings.find_by_book_id(book)
end
def read! book
self.readings.create!(:book_id => book.id)
end
def stop_reading! book
self.readings.find_by_book_id(book).destroy
end
def red? book
self.reds.find_by_book_id(book)
end
def make_red! book
unless red? book
self.reds.create!(:book_id => book.id)
end
end
end
By the way I tried making a user who is reading book 1 and doing user.readings.find_by_book_id(1) in the console and it returns a record from the readings table.
as requested
# routes.rb
resources :readings, :only => [:create, :destroy, :show] do
member do
post :create_comment
delete :finish
end
end
Looks like you have got to_param method in your Reading model
try to call id clearly:
current_user.readings.find_by_book_id(book.id).id
UPD
remove :only => [:create, :destroy, :show] from your routes
use this <%= form_for :reading, current_user.readings.find_by_book_id(book.id), :url => { :controller => :readings, :action => "finish", :id => current_user.readings.find_by_book_id(book.id).id }, :html => {:method => :delete} do |f| %>
I'm not particularly knowledgeable about rails 3 (still using rails 2), but shouldn't you be passing more information to the :url param?
This doesn't seem to mention anything about the ID you want to post to:
:url => { :controller => :readings, :action => "finish" }
Shouldn't it be something closer to this:
:url => { :controller => :readings, :action => "finish", :id => reading_id }
(Assuming reading_id to be substituted for the actual ID)