Should I avoid overriding a rails model method when possible? - ruby-on-rails

More specifically, if I have two options: do a check in the controller or override an association method in the model, which one should I prefer?
Edit:
class Book < ApplicationRecord
belongs_to :author
def author
super || build_author
end
end
Is the code above ok or should I prefer another solution like the one below?
class BooksController < ApplicationController
def update
set_author
if #book.update_attributes(params[:book])
#redirect
else
#render show page - unprocessable entity
end
end
def set_author
a = Author.where(fields)
#book.author = a || #book.build_author
end
end

Related

Include model associations from within the model

I need to clean up my code from using:
# class ProjectsController < ApiController
def show
render json: Project.find_by(id: params[:id]).as_json(include: :user)
end
to:
render json: Project.find_by(id: params[:id]) // should include the association
Is there a way to put this logic in the model? Im using Rails 5 API
class Project < ApplicationRecord
belongs_to :user, include: :project // I thought this would work
def self.foo
self.includes(:user)
end
end
# in controller
render json: Project.foo.find_by(id: params[:id]) // nothing
What if Project belongs to many models and to need to include it by only calling Project.find(1), I will have some nested includes in my controller. Could I put all this logic in the model then Project.find(1) would show all the associations in json format?
In your Project model, override as_json method to include association user:
def as_json(options = {})
super(include: :user)
end

Rails: one-to-many params

I'm making a website for my sports team where players can make blog posts.
class Player < ApplicationRecord
has_many :blogs, dependent: :destroy
end
class Blog < ApplicationRecord
belongs_to :player
end
My question is:
What is the difference between setting up the route/controller action with the following two params? They are both giving me the exact same thing.
1)
route:
get "players/:player_id/posts" => "blogs#show", as: "player_posts"
controller action:
class BlogsController < ApplicationController
def show
#player = Player.find(params[:player_id])
#blogs = #player.blogs
end
end
2)
route:
get "players/:id/posts" => "blogs#show", as: "player_posts"
controller action:
class BlogsController < ApplicationController
def show
#player = Player.find(params[:id])
#blogs = #player.blogs
end
end
What is the difference between setting up the route/controller action
with the following two params?
There is no difference between those two named routes, except you are using different keys(:player_id & :id). I suggest the first route since you fetching players instance in the blogs controller.
get "players/:player_id/posts" => "blogs#show", as: "player_posts"
#controller action:
class BlogsController < ApplicationController
def show
#player = Player.find(params[:player_id]) #players instance
#blogs = #player.blogs
end
end

Ruby on Rails to_json function add parameter to methods for render in favorites or not?

How do I add parameters to methods for rendering the current place in favorites?
I tried this:
class Place < ActiveRecord::Base
has_and_belongs_to_many :users
def in_fav(user)
if user.places.include?Place.find(id)
return true
else
return false
end
end
end
class User < ActiveRecord::Base
has_and_belongs_to_many :places
end
class PlacesController < ApplicationController
places = Place.all
user = User.first
render json: {desc:true, status:1; data: places}.to_json(:methods => :in_fav(user))
end
I find same problem here
attr_accessor :current_user
def is_favorited_by_user?(user=nil)
user ||= current_user
end
#drops.current_user = current_user
render :json => #drops.to_json(:methods => :is_favorited_by_user?)
I don't understand current_user - it's assocciations? and how to use method current_user for collection #drops

Submit two forms at once with rails

Basically my idea is very simple - I want to create a new cart for each new user. The form itself is generated with scaffold and we're talking rails 4.0.1 here.
Is there a way to do that and if so - how? Maybe you can link me some live examples?
You do not need multiple forms to create multiple objects in Rails controller. Assuming that you have relationships like this:
class User < ActiveRecord::Base
has_many :carts #or has_one :cart
end
class Cart < ActiveRecord::Base
belongs_to :user
end
Then it's perfectly acceptable to do this:
class UsersController < ApplicationController
def new
#user = User.new
end
def create
#user = User.new user_params
if #user.save
#user.carts.create # or #user.create_cart
redirect_to user_path
else
render action: :new
end
end
private
def user_params
params.require(:user).permit(...)
end
end
If the new user form happens to include some cart-specific details, then use fields_for to make them available in the form:
= form_for :user do |f|
... f.blah for user fields ...
= fields_for :cart do |cart_fld|
... cart_fld.blah for cart fields ...
and add cart_params to your controller.

Rails 3.2 Security

In my rails app I have a User Model where I have an attribute: points
class User < ActiveRecord::Base
attr_accessible :points
has_many :answers
end
Is there a way to make the attribute updated only from specific controller actions?
class AnswersController < ApplicationController
....
def create
#user = current_user
#answer = #user.answers.build(params[:answer])
if #answer.save
#user.points += 10 # <-- I want to make points updatable only from this action
#user.save
else
...
end
...
end

Resources