In my rails app, I want to have a sortable list as part of an object creation. The best practice suggested in Railscast adds the acts_as_list plugin and then initiates AJAX calls to update item position. However, AJAX calls won't work on an unsaved model, which is the situation with new.
One solution would be to save the model immediately on new and redirect to edit. This would have a nice side effect of persisting any change so the user could resume work should he be interrupted.
However, this solution adds the unwanted complexity of saving an invalid model, compromising rails' validation processes. Is there any better way to allow AJAX + validations without going into too much work?
Your new action has the same access to parameters that any other action has. You could pass parameters for the unsaved object back to the new action and an object re-initialized with attributes set could be returned back to the view. For instance:
controller:
class WidgetsController < ApplicationController
def new
#widget = params.has_key?(:widget) ? Widget.new(params[:widget]) : Widget.new
end
..
end
Then in your view you'd have to send params to the new action via a link or a form post.
you can temporary store unsaved object in a 'session'.
like (this code must be in controller)
my_model = MyModel.new(params[:my_model])
session[:my_model_tmp] = my_model
Related
Learning Rails, the point at which a controller gets instantiated is unclear to me whereas, the point at which a model gets instantiated is somewhat recognizable as for example, when a user enters data in a from and clicks the submit button is sort of a trigger that leads to a creation of an object model.
Done some research and I'm visualizing in my head that when a HTTP request is sent via the browser, the routing to a controller becomes the trigger to instantiate a certain controller object from a controller class.
Is this somewhat correct?
When the HTTP request enters your application server (puma, webrick, etc), the request passes through a stack of middleware (defined in rails gem), which converts the HTTP request into an instance of ActionDispatch::Request class which is used to determine the correct route to dispatch to appropriate controller class in your rails app based on the route definitions defined in config/routes.rb.
The generated request object is then dispatched to the corresponding controller and action method which instantiates the Controller class and invokes an action method on it's instance with an argument of params object (instance of ActionController::Parameters).
This is just a general overview of how Controllers are instantiated. The request object passes through a series of middleware classes and modules before a request object is generated.
Here's a good article if you want to read it in detail.
As we define the routes in routes.rb, than the control goes to that controller action at that time the controller get's initiated to work
It is more related to object oriented programming, The object is always instantiated when you call new on class
2.0.0-p648 :001 > Class.new
=> #<Class:0x007fee8e99d9a8>
2.0.0-p648 :002 >
Here the object is instantiated, and similarly in rails when you call any action lets say
def new
#article = Article.new
end
new object gets initiated, when you click on save, you are actually calling create action, and pass the current object.
def create
#article = Article.create(article_params)
#article.save
end
here .create method filled object with article_params and .save method saves object in database.
I need to make new Footprint on every action user makes in database. How can I initiate Footprint.new() on other controller also giving automatic statement with it.
For example when User deletes entity.
entity_controller action delete will pass such statement as "user"+ "{ #user.name }" + "deleted entity "{ #entity.name }" to footprint.description.
Also it should pass current user id to footprint.user_id
Don't know how to do it!
I was not clear on your question , but what i felt was that you want to delete an entity and then wanna pass deleted entity name to another action which is , in some other controller .
def delete
entity = Entity.find(params[:id]
entity_name = entity.name
entity.destroy!
footprint_path(entity_name)
end
you can use path helpers when you have defined resources in your routes.rb , which in this case is , resource "footprint"
Update
To track user's activity you can use paper_trail or Userstamping
I guess you need a user activity feed on your application. You can make use of the Public Activity gem for achieving this functionality. There is also a nice Railscast about the gem.
Here's my fairly simple scenario: I have a basic MVC setup, and in my view, I have a drop-down list that it supposed to enable users to select different databases to connect to. So, by default, the page loads and my controller establishes a connection to the default db, call it DB_Foo (which actually extends ActiveRecord::Base), and my view renders a table using the data from DB_Foo. It looks something like this:
class MyController < ApplicationController
def index
#db_to_use = params[:db].nil? ? DB_Foo : params[:db]
# imagine some code to establish_connection
#table_data = #db_to_use.all
end
end
Then, in my view, I can render the data by looping over #table_data.to_a.
Now, I go to select a different database, say DB_Bar from the drop-down, and I trigger a jQuery.get() call (shorthand for Ajax GET) to the same controller, passing in DB_Bar as a parameter. I can verify that upon this new request getting routed to my controller, it sees the DB_Bar parameter I passed, and is able to establish the connection to DB_Bar. I've verified that #table_data now contains the new data from DB_Bar, by the end of the index method.
What I want is basically for Rails to re-render the same view using the same controller, but with a different set of data from DB_Bar instead of DB_Foo. But, nothing gets updated in my browser, which to me, means that no rendering of my view is happening (if it did, it would use the new data in #table_data and I would see it).
Am I horribly off-track with this design? Must I use a jQuery callback on the .get() to modify the HTML elements manually? Shouldn't Rails just render my page again with the new data?
I am following this tutorial http://guides.rubyonrails.org/v3.2.13/getting_started.html to build my rails app in version 3.2.13 . If you go to the section 6.9 you will find controller and view for creating new posts . Here I do not get how #post variable is passed from new action to create action and where is create function called ? Also , I faced the same problem while working on edit and update actions . Please guide me through this .
It's not passed to create action, it's instantiated again with params you pass from the form displayed with new action.
create action is called with POST request to the path specified in config/routes.rb, leading to specific controller and action.
#post is not passed from new to create the params hash is passed into the create method #post is then set using the new method of the model not the controller. create calls new and then save and returns the object. new returns the object without saving and then save returns the validity of the object. That is why the create method in the controller calls new and then has a conditional statement for save. It is basically saying initialize this object then if it is a valid object do one thing if it is not do another. The create action is not called because of this check.
#this will return true if valid or false if invalid
Post.new(params[:post]).save
#this will always return the Post object which conditionally is true in Ruby
Post.create(params[:post])
#To use the create in a conditional statement it would be
Post.create(params[:post]).valid? || Post.create(param[:post]).save
The last line is unnecessarily redundant and thus why the example uses new followed by save.
create method for a Model is more succinct but probably best to use when you know the object is valid.
Hope this gives you a better understanding but if you are still confused please let me know and I will try to explain further.
I'm creating an API and I want that the outside can only has access to update method to actualize a report. But in case there is no report I want to create it. I know that the easy way to do it is just create it inside update method, but as soon I have already a create method build I was wondering if is it possible to call it sending it also some params.
I looked around like here Rails 3: Call functions inside controllers or the API but I didn't found any good solution.
Does anyone has a better one?
Thank you very much in advance.
You should not call an action of your controller from another action.
Why? Because every action of a controller is defined to respond to a request, which has several attributes (such as IP, params, session, HTTP headers, etc.). Imagine how "weird" it would be to call an action from another in the Controller.
If you want to do "extra logic" which would not be related to the update action (for example, create), you should call a protected (accessible only via the Controller & its children) method of this controller.
In your case, you could do something like this:
class ReportsController < ApplicationController
def update
#report = Report.where(id: params[:report_id]).first
if #report.nil?
create_report(params)
else
# etc.
end
end
protected
def create_report(params)
Report.create(params)
end
end