Is there any way to find the current controller name inside model? - ruby-on-rails

User model can be updated using Registration controller and Password controller. Is there any way to find from which controller update method is called inside model.?
I want to find the controller name inside model. Please help me.

Model and Controller layers are separated. Model is not aware of any controller-related stuff.
The only way to get the controller's name in the model is to pass the name of the controller as an argument to some method defined in model.
I never saw a real use of knowing the controller's name in model. Such need IMHO means you designed things wrong.

I suppose an invited user is not activated yet. So how about defining your presence validation only on active users? Maybe by adding something like this:
validates_presence_of :phone_number, if :activated?
I haven't tested the code, so it's not copy-safe ;)

Possible solution is:
class User < ActiveRecord::Base
with_options :if => :phone_required do |user|
user.validates_presence_of :phone
end
end
phone_required is database column so you need to create migration for user.
In your controller you need to set
your_user.phone_required = false
or
your_user.phone_required = true
before saving.

I strongly discourage this practice as a model should be oblivious of controllers but it's not hard to accomplish if you use virtual attributes in your model
class SomeModel < ActiveRecord::Base
attr :controller
end
Now.. you can just pass in the controller when you update, such as:
class SomeModelsController < ApplicationController
def update
#some_model.update_attributes(params[:some_model].merge(controller: self))
end
end

Related

Check if a table value in one model matches a table value in a different model

This question is kind of hard to ask, but basically, I have a Class model and a User model, each Class table has a token, and so does each User one. After the user submits a sign up form, how would I set the value of the users class_id in the create action? I've tried <%= f.hidden_field :app_id, :value => App.find_by_token(params[:key]) %>, but this doesn't work. Sorry for the long and confusing question, will be glad to answer more. Thanks in advance for any answers
It sounds as though you have a "relationship" where a User belongs to a Class and a Class could have many users. If that is the case then you should use rails Associations to make it easy for yourself. This would involve adding a 'has_many :users' to your Class model and a 'belongs_to :class' call to your User model. You would then just use the rails helpers to 'build' the object and save it with the association in the corresponding controllers.
The manual way to do it would be as follows from your controller:
def create
#This would involve you sending the proper class id as a hidden form field with the form field attribute named 'class_id'. You may need to add 'attr_accessor :class_id' to your User model.
if user.create(user_params)
blahblahblah
else
sorry blah blah
end
end
private
def user_params
params.require(:user).permit(:name, :email, :class_id, :etc)
end

Rails_admin, Assigning Devise's current_user to model inside action

I have Devise Model Person which will log in and manage rails_admin app.
I have model called Model which has updater that was added by mongoid-history.
In order to set who updated my story I need to do something like this:
model = Model.new
model.updater = Person.first
model.save
According to this link to github, I can not set current_person, which created by Devise automatically. That's means that I need to set updater manually each time when something happens to my Model.
How to get current_person and set it to Model where rails_admin's action happens?
I only know that I need to write something to each action in initializers/rails_admin.rb
There's no access to current_user from the Model, because ActiveRecord models can be used independently from Rails apps, they can be used without logging in.
It is the controller that (often) requires the user to login and so has access to the user session and the current_user method. The controller must therefore do the work of setting the updater on the Model.
Perhaps you could set a callback method in the controller that acts on any action that modifies the model and sets the updater there.
I have found one solution for my question, but I don't know if it is good aproach or not.
If I want to assign my current_person in edit action I needed to write this:
config.model Model do
edit do
field :updater_id, :hidden do
visible true
def value
bindings[:view]._current_user.id
end
end
end
end
It createds hidden field which has asigned ID of current person which is logged in.
Mr.D's answer seems not to work (at least as of rails_admin 2.0.2); bindings doesn't have a :view key. The correct key is now :controller:
bindings[:controller].current_user # returns current User object
And if you not have a attribute to store this id and just need id to validate another operation, you can create a attribute to it:
config.model Model do
edit do
field :updater_id, :hidden do
visible true
def value
bindings[:view]._current_user.id
end
end
end
end
MODEL:
class TaxPlan < ApplicationRecord
attr_accessor :updater_id
validate :validate_updater_id
def validate_updater_id
yor code validation here
end
end

how to run a one-time database change on a single user

I have Customer and each customer has_many Properties. Customers belong to a Company.
I'm trying to add a certain Property to each one of a single Company's Customers. I only want this change to happen once.
I'm thinking about using a migration but it doesn't seem right to create a migration for a change that I only ever want to happen once, and only on one of my users.
Is there a right way to do this?
You can just use rails console.
In rails c:
Company.where(conditions).last.customers.each do |customer|
customer.properties << Property.where(condition)
customer.save!
end
Validation
Depending on how you're changing the Customer model, I'd include a simple vaidation on the before_update callback to see if the attribute is populated or not:
#app/models/Customer.rb
class Customer < ActiveRecord::Base
before_update :is_valid?
private
def is_valid?
return if self.attribute.present?
end
end
This will basically check if the model has the attribute populated. If it does, it means you'll then be able to update it, else it will break
--
Strong_Params
An alternative will be to set the strong_params so that the attribute you want to remain constant will not be changed when you update / create the element:
#app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
...
private
def strong_params
params.require(:model).permit(:only, :attributes, :to, :update)
end
end
It would be much more helpful if you explained the context as to why you need this type of functionality - that will give people the ability to create a real solution, instead of proposing ideas

How to handle optional belongs_to association

USECASE:
Consider the following example.
Class Foo < ActiveRecord::Base
belongs_to :user
attr_accessible :title
end
Class User < ActiveRecord::Base
has_many :foo
attr_accessible :name
end
If a logged-in user creates Foo, it will be associated to its user record. If a not logged-in user creates Foo, it wont be associated to any user. This is just an example and I have a lot of similar use cases in my application.
PROBLEM:
The problem is my view code gets cluttered with a lot of if conditions and ternary operations like,
<% foo.user ? foo.user.name : "not set"%>
CURRENT SOLUTION:
To overcome this, I am using the null object design pattern. The User class defines a NullUser object (whose name will be set to "not set"). If a foo object does not have user object, it will return a NullUser object. I have overridden the user method in Foo class which does the nil check.
QUESTION:
Is there a better solution to this?
Is there a gem which facilitates
the null object pattern for rails active record models.
This sounds like the perfect case for a decorator that wraps your user object. All the logic about what to display goes in there; all your view cares about is that it can spit out the object's name.
Draper works well for decorators in Rails.
And a Railscast for good measure.
One potential solution would be to set a default value and associate it with a guest user. That way it would be overridden when a user was present, but would mean there would always be a value when you call .user.name

Proper way to initialize nested fields in Rails forms

I'd like to understand what's the "proper" way to initialize the nested fields of a model.
Let's say you have some nested fields for a model:
class User
has_one :address
accepts_nested_attributes_for :address
end
And you need to initialize those attributes (address in this case) to use them in a fields_for call.
So far I've thought of three ways to do this.
First, after_initialize hook on the model:
class User
after_initialize :init_address
protected
def init_address
address ||= build_address
end
Then we have initialization in the controller:
class UsersController
def new
#user = User.new
#user.build_address
end
end
And finally, we can have a helper method to do it for us:
module FormHelpers
def setup_user(user)
user.address ||= user.build_address
user
end
end
# view
<%= form_for setup_user(#user)... %>
Is there anything resembling a standard or a "best practice" for this scenario? How do you do it and why?
I think that if the nested attribute doesn't make sense at all without the parent model, building and initialization of these nested models should be the responsibility of the parent model.
I don't see why the UsersController should care about how the #user.addresses are built or initialized. For me, giving the controller this responsibility, would probably imply that on create he should be the one that parsed and built the nested attributes (which, happens in the model).
I would go for the first approach.
i believe that build_address is already built in for rails after u declare a has_one association, so you don't need to write that bit urself.
and if the form is called only from the new action, what u really need is only the controller bit, and nothing else

Resources