Assuming I have
#post.rb
class Post < ActiveRecord::Base
default_scope includes(:user)
what do I do when I don't want to include the user when I fetch a post?
for instance, when I delete a post
You can use the unscoped scope. Method reference: http://apidock.com/rails/ActiveRecord/Scoping/Default/ClassMethods/unscoped
For example, when trying to delete the Post object :
def destroy
#post = Post.unscoped.find(params[:id])
# destroy code here
end
This will search in your database without any scope.
Related
Whenever a User object is created, I want a UserInfo object to be created too, and linked to it.
Unfortunately this does not create any UserInfo:
class User < ActiveRecord::Base
has_one :user_info
...
def init
self.user_info = user_info
self.save!
end
Why is the init method not called? How to reach my goal?
sombe's technique is right, but his details aren't ideal. In fact, since create_user_info is already a method on User instances, all you want is something like:
class User < ActiveRecord::Base
has_one :user_info
before_create :create_user_info
end
Edit: init doesn't do anything particularly magical under Rails (I... don't think it does under basic Ruby either - are you thinking of initialize? I'll assume you are). initialize is fired off when an instance of the Ruby class is created in memory. That's divorced by quite some margin from an instance of the model being created in the database; a new class instance could be due to you calling build (and not saving yet), or even due to reading an instance out of the database.
If you want to step in on database operations, you need to make use of the ActiveRecord callbacks. You might find my answer to this question useful.
before_save callback triggers on create and update.
I'd suggest to use after_create because before_create can return errors
class User < ActiveRecord::Base
has_one :user_info
...
after_create do
create_user_info
end
In your User model, use a before_save filter instead of init like this:
before_save :create_user_info
...
private
def create_user_info
user_info = UserInfo.new
if user_info.save
self.user_info_id = user_info.id
end
end
Is there a hook or callback that I can implement so that right after the user is created, I would like to invoke some custom code ?
I tried after_confirmation hook in the user model but that didn't work.
Use the standard after_create callback provided by Rails.
class User < ActiveRecord::Base
after_create :do_something
def do_something
puts "Doing something"
end
end
Using a callback is perfectly legit if you're dealing with the internal state of the model you created.
After creating a User, I needed to create default a Team. It's preferable to avoid using callbacks to deal with other objects.
“after_*” callbacks are primarily used in relation to saving or persisting the object. Once the object is saved, the purpose (i.e. responsibility) of the object has been fulfilled, and so what we usually see are callbacks reaching outside of its area of responsibility, and that’s when we run into problems.
From this awesome blog post.
In this case it's better to act on the controller, where you can add your functionality directly, or delegate to a service for an even cleaner solution:
# shell
rails g devise:controllers users
# config/routes.rb
devise_for :users, controllers: { registrations: "users/registrations" }
# app/controllers/users/registrations_controller.rb
class Users::RegistrationsController < Devise::RegistrationsController
after_action :create_default_team, only: :create
private
def create_default_team
Team.create_default(#user) if #user.persisted?
end
end
I'm using Rails 4 with Devise 3.5 with confirmable and had to do this due to various surprises.
class User < ActiveRecord::Base
# don't use after_create, see https://github.com/plataformatec/devise/issues/2615
after_commit :do_something, on: :create
private
def do_something
# don't do self.save, see http://stackoverflow.com/questions/22567358/
self.update_column(:my_column, "foo")
end
end
I am trying to achieve a subsequent form submission. To clarify things -
I submit a form for #post
then once that #post is created I would immediately (under the hood) like to submit the form for #associations.
The catch is, this second form submission would require the post_id field from the newly created #post.
What would be the best way to achieve this? Would nested forms help me pull the newly created #post.id? Kindly help me with this.
If this is something that should happen whenever you create a Post, then you should use active callbacks to achieve that :
class Post < ActiveRecord::Base
after_create do |post|
# create your association using post.id
end
end
or, you can write it like that also :
class Post < ActiveRecord::Base
after_create :after_create_post
def after_create_post
# create your association using self.id
end
end
Otherwise, if this is something specific to a controller action, you should simple do something like this :
class PostsController < ApplicationController
def create
#post = current_user.posts.build(params[:post])
# then use the #post.id to build your association. something like
#post.associations.build(:prop1 => 'value1', :prop2 => 'value2')
end
end
Hope this helps!
assume we the following setup:
class Post < ActiveRecord::Base
belongs_to :user
end
class User < ActiveRecord::Base
has_many :posts
end
assume further the user has a boolean attribute 'admin', which indicates if he is a global admin or not.
I want to write a method (or a scope?) for the User class, called 'visible_posts'. If the user is no admin, it should return just its own posts. If he IS admin the method should return all posts in the system.
My first attempt was something like this:
class User < ActiveRecord::Base
[...]
def visible_posts
if admin?
Post.all
else
posts
end
end
end
Problem here is that Post.all returns an Array, but I would rather like to have an ActiveRecord::Relation like I get from posts to work with it later on.
Is it somehow possible to get an ActiveRecord::Relation that represents ALL posts ?
You can do Post.scoped i guess in Rails
And later on this you can call .all to fetch the results
Just start to develop with devise for my app authentication, however running into trouble with accessing current_user from a model. I have no problem accessing this from a controller.
For my scenario I need to get the current user id to keep track who has edit the blog post, which I save the user id with before_save filter.
Appreciate your help!
Thanks
You can only pass it down in a parameter.
class SomeModel
def my_nifty_method(user)
end
end
in controller:
class SomeModelsController < ApplicationController
def some_method
sm = SomeModel.new
sm.my_nifty_method(current_user)
end
end
You should be able to do this in your model. 'c' here being the model object and setting it's user_id attribute before create, or save in your case.
before_create {|c| c.user_id = Authorization.current_user.id}
I'm somewhat new to RoR so be warned.
Why are you trying to access to that method in the model?
You can access to the ID attributes via self.id (within the model)