I have two models Employee and Company. In the Employee model i have a before_create callback, but when doing #company.employees.create(params), the callback is not fired. What are my options for making the callback work? I use the before_create because i only wan't it to fire the first time, the object is created.
Related
I'm launching multiple ajax calls to various MVC controllers to load different parts of my page. However it seems that when this gets to the controller only one runs at a time. I'm guessing this is because by default ASP.Net MVC controllers are synchronous? I've also tested loading a page on 2 browser tabs and the second tab always waits for the first.
To get round this I've attempted to make the controller methods in question asynchronous. I've done this by doing the following
Append Async to controller method name
Make the controller methods return async Task
Used the Task.Factory.StartNew method to do the body of work in the method in a separate thread.
For example the controller methods in question now look like this...
public async Task<JsonResult> GetUser(int userId)
{
var result = await Task.Factory.StartNew(() => Task.Run(() =>
{
return userService.GetUser(userId);
})).Result;
return new JsonResult()
{
Data = result,
JsonRequestBehavior = JsonRequestBehavior.AllowGet
};
}
However it still seems to be synchronous. Am I missing something or going about this completely the wrong way? I've not really used the Task Library much so may be missing something big?
No, your assumptions are most likely wrong. Your problem is likely one (or both) of two problems.
First, most web browsers have request limits that only allow a certain number of request to the same server at a time.
Second, you are probably running into a limitation of the Session object that causes multiple requests that use session to be serialized, because Session is not, itself, multi-threaded.
See http://tech-journals.com/jonow/2011/10/22/the-downsides-of-asp-net-session-state
The short answer is that if you don't use session in your action method, simply add this to the method...
[SessionState(SessionStateBehavior.Disabled)]
public class AjaxTestController : Controller
{
//...As above
}
If you only need to read the session, then do this:
[SessionState(SessionStateBehavior.ReadOnly)]
public class AjaxTestController : Controller
{
//...As above
}
There's not much you can do about the browser limitations though, since different browsers have specific request limits. These can be changed with registry (or browser config) entries (usually), but you can't force your users to do that in most cases.
One of the important feature introduced in MVC 4.0 was of Asynchronous controllers which enables to write the asynchronous action methods. Asynchronous controller allows an operation to get performed without making the working thread idle.
When an asynchronous action is invoked, the following steps occur:
The Web server gets a thread from the thread pool (the worker thread) and schedules it to handle an incoming request. This worker thread initiates an asynchronous operation. The worker thread is returned to the thread pool to service another Web request. When the asynchronous operation is complete, it notifies ASP.NET. The Web server gets a worker thread from the thread pool (which might be a different thread from the thread that started the asynchronous operation) to process the remainder of the request, including rendering the response.
Converting Synchronous Action Methods to Asynchronous Action Methods
Following is the example of synchronous action method and the its asynchronous equivalent version.
Synchronous Controller:
public class TestController : Controller
{
public ActionResult Index()
{
return View();
}
}
Asynchronous variant of above operation:
public class TestController : AsyncController
{
public void IndexAsync()
{
return View();
}
public ActionResult IndexCompleted()
{
return View();
}
}
Steps:
Synchronous Controllers are the classes derived from the Controller
class to implement an AsyncController instead of deriving the
controller from Controller, derive it from AsyncController class.
Controllers that derive from AsyncController enable ASP.NET to
process asynchronous requests, and they can still service synchronous
action methods.
Corresponding to the synchronous action method in Synchronous
controller you need to create two methods for the action in
asynchronous controller.First method that initiates the asynchronous
process must have a name that consists of the action and the suffix
"Async". The other method that is invoked when the asynchronous
process finishes (the callback method) must have a name that consists
of the action and the suffix "Completed".
In the above sample example, the Index action has been turned into two methods in asynchronous controller: IndexAsync and IndexCompleted.
The IndexAsync method returns void while the IndexCompleted method returns an ActionResult instance. Although the action consists of two methods, it is accessed using the same URL as for a synchronous action method (for example, Controller/Index).
Note the following about asynchronous action methods:
If the action name is Sample, the framework will look for
SampleAsync and SampleCompleted methods.
View pages should be named Sample.aspx rather than SampleAsync.aspx
or SampleCompleted.aspx. (The action name is Sample, not
SampleAsync)
A controller cannot contain an asynchronous method named SampleAsync
and a synchronous method named Sample. If it does, an
AmbiguousMatchException exception is thrown because the SampleAsync
action method and the Sample action method have the same request
signature.
For more details click here : http://www.counsellingbyabhi.com/2014/05/asynchronous-controllers-in-aspnet-mvc.html
mvc controllers are async in nature, how did you determine it's synchronous? The only reason could only be some lock implemented within your userService.
You can try by making a couple of hundreds of ajax calls to your web services using jquery
It seems that Spine's Model.updateAttributes only updates attributes, and does not create new ones in case you supply any.
In my usecase, I have a controller that creates part of the attributes. Then through an Ajax request the server responds with the full object, and I want to update the model instance living in Spine with the additional variables.
For example, I have a model with attributes: name, date_created. Through the controller a user instantiates an object providing only the name. An Ajax request notifies the server which in turn responds with a name and a date_created. This date_created should then be added to the user's model.
Model.updateAttributes doesn't work, and I wouldn't be too fond of deleting the object and creating a new one - that just seems as too much overhead. I could provide default values for variables that are not set upon creation, but that also has a negative side. I guess what I'm looking for is a method that could be called Model.createOrUpdateAttributes. Can anybody recommend a way to achieve this? Thanks!
I might haven't fully understood your usecase, but I'll try to answer.
You need to declare whatever attributes a type of a model has with the configure class method. This declaration helps various model function to do their job later.
After you declare all the attributes you need, you can create model instances with any of the previously declared attributes.
You don't have to provide values for all the declared attributes.
After the ajax call returns, the date_created will be set on your model instance. Until this happens it will be just undefined.
If this solution still can't work for you, please describe why, and I'll gladly try to help.
I have a few business classes that represents logic of my application, I want to write logs from this classes, just like in a controller, how do I achieve reference to the logger.
If you want to tell me send it in constructor please don't.
When you know that your object will be in the Rails environment-- a service object, for example, instantiated and called from a controller --then you can use Rails.logger to get the same logger referenced by the logger method from within a controller or model.
For example, from app/services/payments.rb:
rescue Stripe::CardError => e
error = e.message
Rails.logger.error "Stripe card error for account #{#account}, error #{e}"
I am confused...I just use e.g.
logger.info("in model")
or
logger.info("in controller")
in my models and controllers all the time, this being rails 3.2/ruby 1.9.3. Of course I might be misunderstanding something completely.
cancan did not work with a controller that did not have a class. So I created the userhome.rb model:
class Userhome
end
There is an action in the userhome controller that accesses a page in another directory/class. An attempt to access it yields the following error:
undefined method `find' for Userhome:Class
Is the best thing for me to do...:
delete the userhome model, and
remove "load_and_authorize_resource" from the userhome controller, and
just lock the application down with cancan in every other area possible?
Or is there a workaround to deal with this error?
Take a look at the CanCan documentation on non-RESTful controllers.
A "resource" is the "thing" that your controller is responsible for listing, creating, updating, etc. It often is a model, but need not be (e.g. you might have a "search results" resource that doesn't have a corresponding model).
If your controller really isn't dealing with a resource, then you may want to just use authorize! as appropriate within the controller, but if the controller is dealing with a resource but there is no corresponding model (which sounds like it may describe your situation) then you may want to use authorize_resource and specify that there is no corresponding class. This lets you "pretend" that you have a resource (i.e. you can specify abilities based on actions on a resource) without actually having a model that represents that resource.
What is the best practice to switch a boolean attribute e.g., un-/publish an article?
For the Model side, I saw Object.update_attribute(:only_one_field, 'my_value') is best for this job, instead of update_attributes.
What about
the View (use a link, a submit button in a form, other ideas?) and
the Controller side?
Views usually use forms for updating models. The form_for helper makes this pretty straightforward.
If you are using a standard update action (your controller inherits from InheritedResources::Base) then your update! method in your controller should handle this fine.
I would actually advise against using Model.update_attribute(:published, value) unless you are aware that this call bypasses your model's validations. This is generally why forms just post to the update or create methods in the controller - those by default go through the entire ActiveRecord lifecycle, calling your validations as well. If you have a reason to bypass them, then by all means use update_attribute.