Rails: Better understanding dynamic scopes - ruby-on-rails-3

This is my "dynamic" scope:
def all_games(conditions = {})
scope = games.includes(:stats).scoped {}
scope = scope.where sport_position_id: conditions[:sport_position_id] unless conditions[:sport_position_id].nil?
scope = scope.where sport_id: conditions[:sport_id] unless conditions[:sport_id].nil?
scope = scope.where team: conditions[:team]
scope.order(:date)
end
The method above is in a module that is included with my User model.
So you would access this in code, like so:
u = User.find(1)
u.all_games(sport_position_id: params[:sport_position_id], sport_id: current_sport.id, team: params[:team])
When doing some Google searching for dynamic scopes, I came across Ryan Bate's RailsCast on anonymous scopes (http://railscasts.com/episodes/112-anonymous-scopes). I modified it since I am using Rails 3, but was wondering, if I was on the right path when it comes to writing dynamic scopes?
I find myself sometimes writing dynamic scopes because of the nature of some complex API's I am writing.

Related

TastyPie: Consulting and updating fields from other models within a resource

I have a Profile model with a OneToOne relationship with a User. For such Profile model I use the following class, which uses two additional fields coming directly from the User:
class ProfileResource(ModelResource):
username = fields.CharField(attribute='user__username')
email = fields.CharField(attribute='user__email')
class Meta:
# Base data
queryset = Profile.objects.all()
# Allowed methods
list_allowed_methods = ['get']
detail_allowed_methods = ['get', 'put', 'patch']
# Security setup (FEEBLE)
authorization = Authorization()
authentication = BasicAuthentication()
Such resource works fine when consulting profiles. It retrieves the username and email perfectly, and is capable of filtering and ordering by such parameters.
However, I cannot manage to update such fields on the User model in a, say, elegant fashion. All I have come up with is this:
def obj_update(self, bundle, skip_errors=False, **kwargs):
bundle = super().obj_update(bundle, skip_errors=skip_errors, **kwargs)
if 'username' in bundle.data: bundle.obj.user.username = bundle.data['username']
if 'email' in bundle.data: bundle.obj.user.email = bundle.data['email']
bundle.obj.user.save()
return bundle
Which works fine but doesn't seem the best of solutions.
Does anybody know a better way to work out this kind of field-only relationship between a resource and a related model?

In Rails 3, is there a difference between = and assign_attributes?

Let's say you're in your user controller and you want to change the name a #user based on some params you have available to you.
I want to know if there is any difference between the following:
#user.name = params[:user][:name]
or
#user.assign_attributes({:name=> params[:user][:name]})
Thanks in advance!
A great way to figure out questions like this is to dive into the source. I found the method in activerecord/lib/active_record/attribute_assignment.rbCheck it out here.
The assign_attributes method will actually just loop through the parameters given and sends the :name= message to your model. However, because you are possibly assigning many attributes, it takes into account mass-assignment precautions. (ie. make sure that the attribute is listed as attr_accessible).
The = (e.g. #user.name = params[:user][:name]) directly calls the attribute setter with no security check. The assign_attributes checks security for the values passed in.
From the Rails API for assign_attributes:
Allows you to set all the attributes for a particular mass-assignment
security role by passing in a hash of attributes with keys matching
the attribute names (which again matches the column names) and the
role name using the :as option.
Source for assign_attributes

how do I separate user params vs Action Pack params?

I have a Rails application where user parameters are all provided via a RESTful API with JSON parameters. Specifically, there is no client-side HTML form from which the user posts data: it's raw JSON.
So to create a new Car entry, the user might:
POST www.mysite.com/api/car
model=Ford&year=2012
In my app, by the time I receive this, the Action Pack values are intermingled with the user values in the params[] hash, so I get:
params = {:model=>"Ford", :year=>"2012", :format=>"json", :action=>"create", :controller=>"api/cars"}
What's the best way to separate the user-generated parameters from parameters generated by Action Pack? The best I can think of is to delete the latter:
car_params = params.reject {|k,v| [:format, :action, :controller].member?(k)}
car = car.new(car_params)
but that doesn't smell right. Is there a better way? (For example, can I get Action Pack to encapsulate the user supplied params into a single hash and pass that as a single element of params[]?)
Don't know if it can help, but I'd just create a method in application_controller :
def user_params
return params.reject {|k,v| [:format, :action, :controller].member?(k)}
end
So throughout the code, you can just use user_params when you don't want ActionPack params

Best way to scope a has_many relationship when find()'ing the parent object

I'm struggling a bit with understanding default scopes and named scopes with my quiz application. I'm on rails 3.0.
I have a Question model that has_many UserResponse models.
Question has the question text and possible answer_ids. UserResponse ties user_id to a question_id and answer_id.
When I find() a Question to display to the user, I don't want to also pull every single UserResponse. By default, I'd like to only pull the UserResponse for the current user_id to see if they have already answered this question.
How can I create a scope on either the Question or UserResponse to accomplish this?
Not sure about the scope but I would start out just using the model relationships with something like this query perhaps:
(given question and user)
responses = question(question).user_responses(user)
Then once working ok I would move onto scopes (if needed) and have:
a scope on the user model for response
(Rails3 syntax) scope :responses_by_user, labmda { join(:responses) }
a scope on the question model for responses
(Rails3 syntax) scope :responses_by_question, labmda { join(:responses) }
Note: I leaning more towards these 'join' approaches in the thought that they will only do 'inner' joins, i.e. only return rows where response records do exist. I am doing this as opposed to a syntax more like lambda { where ('user_id = ?', User.id) }
Then you could also chain them together. Something like
Question.responses_by_question(question).responses_by_user(user)`

How do I make an ActiveRecord scope that doesn't affect the query in Rails 3 using Arel (presumably)?

Essentially I am looking for a no-op type of relation to apply to a chain of scopes.
Lets say I have a chain of scopes:
Post.approved.published.all
Now, for debugging purposes, I wish to make the published scope do nothing at all, so that the chain will only return approved posts, regardless of whether they are published or not.
What would I return in the following method:
def self.published
# what to return?
end
Make published an alias for all, or use scoped to return a relation to which additional conditions can be chainged:
def self.published
all
#or
scoped
end
I would use a scope, returning all...
scope :published, all
or, make it an alias for scoped:
scope :published, scoped