Rails show method not returning associated objects - ruby-on-rails-3

I have an object which has a reference to another using the :through approach.
When I perform the "show" method, the objects details are returned but not its associated objects. I've tried including the objects in the find like so:
#recipe = Recipe.includes(:quantities).find(params[:id])
but to no avail.
When I debug the code and do
#recipes.quantities
then I'm returned the correct set but the set isn't returned in the json by default. How I can make it so?

In your show method do something like this
def show
#recipe = Recipe.includes(:quantities).find(params[:id])
respond_to do |format|
format.html
format.json { render json: #recipe.as_json(:include => :quantities)}
end
end
This is actually kinda hidden in the Rails source, but as_json makes more sense to use as per an answer on this question.
Documentation: ActiveModel::Serializers::JSON

Related

Fetching last incomplete record or new in ActiveRecord

I have a Rails 3.2.21 app where I'm adding some basic timeclock functionality. I need to build a scope called current_clock_event that will look for the last record for a user where clock_out: nil so in essence, the record that will be fetched is the last ClockEvent record for the user that does not have a value in clock_out. This is what I want to pass to my controller/view.
class ClockEvent < ActiveRecord::Base
attr_accessible :clock_in, :clock_out, :total_hours, :user_id
scope :current_clock_event, where(clock_out: NIL).last
end
As you can see I wrote a very simple scope to pull a record where the clock_out: NIL so in theory that should pull the last incomplete record. I think this is working ok but I need to figure out how to access this in the controller and have some sort of conditional to either pull the current_clock_event or instantiate a new clock event if the last record is completed (both clock_in and clock_out are populated)
So I'm stubbing out my controller but am hitting a wall as to how to do this.
class ClockEventsController < ApplicationController
def index
#clock_event = current_user.current_clock_event # need to figure out this part to fetch the record or if the record is complete instantiate a ClockEvent.new for the user.
respond_to do |format|
format.html # index.html.erb
format.js
end
end
end
I wrote code 2 years ago that did all of this but lost the repo by accident so I have nothing to reference and am sort of brain-fogging on how to pull this off.
Any help would be appreciated. If you need more examples or further explanation, please let me know.
You might want to try something like this:
class ClockEvent
belongs_to :user
# you might want to add an order here...
scope :last_clock_event, -> { where("clock_out NULL").last }
def completed?
clock_in.present? && clock_out.present?
end
end
class User
has_many :clock_events
def current_clock_event
ce = clock_events.last_clock_event
ce.completed? ? ClockEvent.new : ce
end
end
class ClockEventsController < ApplicationController
def index
#clock_event = current_user.current_clock_event
render :index
end
end
The completed? method defined on the ClockEvent instance allows you to tell if your instance is considered completed or not.
The current_clock_event method defined at the User level allows you to define the logic to return either the last clock event record or a new one if completed.
The index method is pretty straight forward.
I played around with some code and was able to get some refactoring help to make things cleaner. In the User model I refactored current_clock_event to just clock_event and seem to have been able to make the code a bit cleaner, although it's not tested, just stubbed out for now. Let me know what you think.
class ClockEvent
belongs_to :user
scope :incomplete, -> { where(clock_out: nil) }
scope :complete, -> { where.not(clock_out: nil) }
def completed?
clock_in.present? && clock_out.present?
end
end
class User
has_many :clock_events
def clock_event
#clock_event ||= clock_events.incomplete.last || clock_events.new
end
end
class ClockEventsController < ApplicationController
def index
#clock_event = current_user.clock_event
render :index
end
end

Inherited_resources build resource as role

As an example:
def create
resource = build_resource
resource.assign_attributes(params[resource_instance_name], as: :admin)
create! do |format|
format.js {...}
end
end
The problem with above is that attributes are not being assigned with as: :admin, they are being assigned without any check and so this method is not having any effect. Is it the create! method? Attributes are being assigned to this resource elsewhere and I can't find out where it is. Appreciate any insight.
Found my answer here: https://github.com/josevalim/inherited_resources/pull/153. Had to override as_role and role_given? --
def as_role
{ as: current_user.highest_role }
end
def role_given?
true
end
This will then always apply roles to attributes for either the controller it is defined in, or all resources if you inherit from a master resources controller like I do.

using build method on association in rails 3.2 creating object in memory

I have 2 models like the following
Class Post
has_many :comments, :dependent => :destroy
end
Class Comment
validates_presence_of :post
validates_presence_of :comment
belongs_to :post
end
In Comments controller,
def create
comment = #post.comments.build(params[:comment])
if comment.save
// some code
else
// some code
end
end
When the comment is invalid as per the validation, the comment is not saved. But when the #post object is accessed in the view, it contains a comment object with nil id. This did not happen in Rails 2.3.11. We are upgraded to Rails 3.1 and then now to Rails 3.2. This comment object with nil id disappears when I do #post.reload. We are using REE.
I tried to interchange build and new methods. It had the same result as build. Similar behavior is found across our application. Is it the expected behavior or am I doing something wrong?
This seems like expected behaviour to me.
via http://guides.rubyonrails.org/association_basics.html#belongs_to-association-reference
4.1.1.3 build_association(attributes = {})
The build_association method returns a new object of the associated
type. This object will be instantiated from the passed attributes, and
the link through this object’s foreign key will be set, but the
associated object will not yet be saved.
When you call #post.comments.build(...), Rails:
Creates a new Comment object
sets comment.post_id to #post.id.
Inserts it into the comments array (in memory).
When the validation fails, it doesn't delete the comment and the comment persists in the in-memory comments array. When #post gets to your view, #post.comments still includes that badly validated comment.
As for how to deal with it, I'm not sure. Maybe you could do something like (in your controller)... (Feels pretty ugly though.)
def create
comment = #post.comments.build(params[:comment])
if comment.save
// some code
else
#bad_comment = #post.comments.pop
end
end
I had a similar problem while using rails 3.2
Firstly, you need to create two separate methods in your controller. They will be as follows:
The 'new' method that is used to build your comments using 'build_association'
def new
#post = Post.new
comment = #post.build_comments
end
The 'create' method to actually create your comments using 'create_association'
def create
#post = Post.new(params[:post])
comment = #post.create_comments(params[:post][:comment_attributes])
if comment.save
// some code
else
#bad_comment = #post.comments.pop
end
end
Note: I suggest passing 'comment' attribute as a nested attribute of 'post' through your form using 'fields_for'.
Please refer:
http://apidock.com/rails/ActionView/Helpers/FormHelper/fields_for
http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html

Rails 3 simultaneously rendering response of more than one action of a controller in another controller's view

Using Rails v 3.0.11, Ruby v 1.9.3
I have a page having link "Reports" on it, clicking on which invokes ReportsController#index
class ReportsController < ApplicationController
def index
# Renders index.html.haml
end
end
Now I have an already existing JSON API (ReportsDataController shown below) returning JSON response which I need to reuse.
A Controller returning JSON response (my JSON API)
class ReportsDataController < ApplicationController
respond_to :json
def users_events_activity
user_activity_data_obj = find_user_events_activity_per_day
respond_with user_activity_data_obj
end
def users_comments_activity
user_comments_data_obj = find_user_comments_activity_per_day
respond_with user_comments_data_obj
end
end
On my app/views/reports/index.html.haml I need to simultaneously render the data returned by
actions ReportsDataController#users_events_activity and ReportsDataController#users_comments_activity.
Is there a Rails standard way by which the above mentioned requirement can be achieved? If not can anybody please suggest me some approaches to achieve the same?
Thanks,
Jignesh
If you don't want to make two requests, you can always create another controller action and render the JSON like this:
class ReportsDataController < ApplicationController
respond_to :json
def users_combined_events_comments_activity
user_activity_data_obj = find_user_events_activity_per_day
user_comments_data_obj = find_user_comments_activity_per_day
respond_with { activities: user_activity_data_obj, comments: user_comments_data_obj }
end
end

Calling ActiveRecord::Create() from within rails user model not associating new object with user

In my rails user model, I am trying to write a method which will return a list for the current time frame, and in the absence of a list for that time frame, create one which is associated with the user and then return it:
class User < ActiveRecord::Base
def todaysList
today = Time.new
if self.lists.where(:date => today.to_date)
return self.lists.where(:date => today.to_date).first #Get the object, not the ActiveRecord::Relation
else
self.lists.create!(:date => today.to_date) #Make the list, return it!
end
end
My question is, why is it that when I call self.lists.create!(:foo => 'bar'), the user association is not populated?
I've decided to get around this a more sloppy way, by explicitly assigning the user in the create! call, as such:
self.lists.create!( :date => today.to_date, :User_ID = self.id)
however this solution just doesn't seem right.
Thanks in advance and apologies as always for stupid, redundant or badly worded questions.
I would do something like this:
def todays_list
lists.find_or_create_by_date(Date.today)
end
The method name change is just preference.