I've been working on this issue for about two days now. I've posted more task specific questions, got great answers, only to figure out the approach I was taking wouldn't work.
Basically, I want a user to be able to upload images in a form and see a preview of the image they upload before submitting the form. The images and the parent form have a has_many relationship. The images are nested in the parent form using fields_for.
I tried using a client side approach, but ran into cross browser and security issues. My current approach I'm trying is to save the images, reload the div portion of the page, and then assign the parent_id to the image after the partent form is submitted (since I will not have a id for the partent form until it is created).
Is it possible to use ajax to submit the fields_for portion of a form and not the entire parent form? Has anyone attempted to do something similar?
Of course you can submit only the fields of that image by using jQuery to select only the fields that you want to send, serialize them and send them as data of the ajax request.
Be careful, you need to send the authtoken, that's why I have type=hidden in the selector
var data = form.find('[name*=image],[type=hidden]').not('[name*=items]').serialize();
$.ajax({url: this.form.attr('action'), context: this, type: 'POST', data: data
The next step with the image I once implemented as storing the in their own database table, returning the client the id to that who then adds it to the form.
Related
I have a form that allows the user to upload several images to a server. This form also allows the user to edit the form as well depending upon qs parameters. As additional information, I am using redux-saga with react, just to provide more background.
I am able to upload the image and allow the user to preview the image after they make their selection and before they upload it. However, upon reviewing the documentation, I do not see a way to populate the react-dropzone field when the user edits the other form items. I saw a way to do a preview onDrop but not with data coming from the server. I also found this article on Stackoverflow because am not sure if it could be applied to my case within the redux-saga scenario: How to add the URL of an image already uploaded, to Dropzone?.
Can this be done and if so how can it be achieved?
I have two models in the following releationship: Client has_many products, and Product belong_to client. In the client show view I present a form to create new products, that automatically belong to the current client. The show method in the client controller
def show
#client = Client.find(params[:id])
#products = #client.products.paginate(page: params[:page])
#product = #client.products.new
#product.client_id = #client.id
end
and the show view renders a partial
<h1>New Product:</h1>
<%= render 'shared/product_form' %>
That works, products are correctly created.
When an validation error occurs I set a flash in the product create method and redirect_to the client show page. There I loose the data that has been filled in correctly. I tried save the #product instance variable, which has all the data (including the wrong fields) doing
render client_path(client)
from the product controller, but that produces an error
Missing template /clients/17
with the address being
http://localhost:3000/products
Am I calling this wrong? I know that render ususally renders action of the same controller. Can I somehow render Client::show from the product controller? Is there another way to save the data the user has typed in?
If a validation error occurs you should redirect back to the page that generated the validation error. Ie: if the user is at products/new when they submit the form, then your products#create action should end with render :new to present the products form again.
If your products#create action is receiving the form from clients#show, then you do want to render clients#show with validation errors. In that case, all the information that was completed in the form will be available at params[:product], just like it is coming in to products#create.
You might want to take a look at another answer I wrote recently to understand the flow between controllers.
Specifically, the misunderstanding in your case is as follows:
When you have a validation error the record will not save, so you cannot "go back to that data" because your app has not kept it anywhere. The only copy of the data that was submitted is in the request.
If you REDIRECT you are not forwarding a request, you are responding to the initial POST request (which includes all the form information as params[:product]) by making a new request to a different url. This is why you want to use RENDER.
However, if you try to render clients_path(client), what happens is Ruby will first evaluate clients_path(client) to the string clients/(client.id), or in the example you gave, clients/17.
Then render tries to call render 'clients/17', which you don't have a template for. It's looking for a file called clients/17.html.erb. That's why you get the error you're getting.
So, again, to sum up - your products#create action receives the information that was sent from the form as params[:products]. That information is not available outside of this controller action. So, if there is a validation error, instead of creating the product, this controller action should render the same page that the user came from originally (normally products/new) so that they can see the form they just had (with the information filled back into it if you're using a form builder) and also see the error that prevented saving.
I hope that makes sense, feel free to ask follow-up questions.
Yes, you were calling it wrong.
There are three problems:
render should render a template name, say client/new, shared/form etc. The argument could not be a path or variable. The variable is passed by controller to view, nothing to do with render.
You should not use render for a saving fail. Even if you use a template name as #1 mentioned, you'll end up with a wrong URL like products/create with the client page. That's not acceptable.
My suggestion is to always use redirect for saving fail.
Minor problem. In controller, if you've used #product = #client.products.new, the #product object will have every attributes empty but with a valid client id. So you don't need to assign client id again by #product.client_id = #client.id. But this doesn't hurt the result.
Andrew's great answer plus this:
Where to render comments controller in Rails on model validations failure?
makes the solution more clear.
Your specific example: Just watch out that your create action in the ProductsController has all instance variables it needs to render 'clients/show' from it.
I have a view to show the details of a resource that is saved in the database. Some of the details belong to the Resource model itself, and some details belongs to associated models.
In the view I use fragment caching for the details.
When the user presses a button on the view, a part of the view is replaced by a form, so the user can edit the details witout loading a new page. When the form is opened, the cache is expired (it actually is, I have checked). When the user submits the form (using :remote => true), the form is hidden, and the original content is reloaded using jQuery and render partial.
So far everything work just fine. The original content is reloaded correctly with the new values, from code inside <% cache ... do %> and <% end %>.
The strange thing is when I reload the page, some of the new values are gone. Instead some old values are shown (those that should have been cached after the last submit). And the thing that is even stranger is that some of the values are updated, even if they are in the same new cache file as the wrong values.
As far as I can see, values in associated models are correct, while values in the Resource model are wrong (old). I have wondered if it had something to do with sql caching, but I don't think that's the case, because I think the sql cache should be emptied when reloading the page.
If I open the form and submit again, the data is updated, and everything is fine. That is the data from the last submit is coming into the cache. If I change the data in the form before submitting, it is still the data from the last submit that is included in the cache-file. So it seems that data submitted for the Resource model is delayed by one submit, even if the other fields are updated correctly.
If I turn off caching in development.rb, everything works as expected. All data are updated every time.
I do, by the way, have the same problem on my server.
Anyone that has a clue?
Not sure if this will help, but in the last couple of days I have implemented a cache-key based fragment cache scheme on my own site with some success.
I implemented a get_cache_key function in all my models
def get_cache_key(prefix=nil)
cache_key = []
cache_key << prefix if prefix
cache_key << self
child_objects.in_sort_order.each do |child_object|
cache_key << child_object.get_cache_key
end
return cache_key.flatten
end
In my views I then used
<% cache(#home_page.get_cache_key('some_name_for_fragment')) do %>
...Render View
<% end %>
The models now produce a cache key that will invalidate the cache if parent model or any of its children are changed.
The full write up is here, on my website.
Rails caching strategy using key-based approach
It seems like the data are cached a bit to soon after they are updated. My solution so far is to drop caching in the view if it is less then two minutes since the resource was updated. The fragment is uncached until someone updates the page a bit later. This is not a very good solution, while each resource (30 resources) on the page must be queried for update time each time the page is viewed.
I have an application that has 3 level of data depth:
list of presentations
presentation detail
presentation slides
Right now when user came to the app he's presented with list loaded from JSONP store. He click on one item and the callback function receives the record. It pushes it into new view - the detail and displays it. User can disclose presentation slides from there - data record is passed from detail again.
Problem is when user refreshes the page or came from URL. If he came to url like /presentations/slides/1, he wants to see the slides for presentation id:1. Problem is that as long as he wasn't at the list, data was not loaded and because it was not loaded, it was not passed to the detail and the detail didn't pass it along to the slides view. So I have no data.
But I still have the ID! Comming from the PHP's Zend Framework, I would call something like: this.store.find(1), but I can't find any way to do this.
How do I load something from the store based on it's record.data.id?
To add more, store.load() seems to work asyncronously, so when I do:
store.load();
store.each(function(rec){console.log(rec);});
It wouldn't work with JSONP store, because the data is not loaded yet. But when I use Chrome Debuger and pause the execution to let the data load, it works :(
You are correct the load is asyncronously so all you have to do is use the callback function of the store. You can find an example here How to get data from extjs 4 store
I would like to collect emails of prospective users of my app. I've created a page with a simple form. My first question is that since I'm not using a db, do I need a model? And secondly, how do I use "form_for" for form generation if I don't need to use a model. Thank you
I've done this. First I created a simple form with an email field and submit button in my views (app/views/home.html.erb). I use form tag helper to easily create the form rather than writing my own html: http://guides.rubyonrails.org/form_helpers.html. I made sure route the form action to the correct action in my controller. In the controller I use hominid to do the subscription, then redirect to the index using redirect_to (':action => home'). That's all it took.