1

I have an array that I've made to have values added and removed on client side which then get persisted in the database when update action is triggered.

Adding/removing array values works excepts that with this approach, I cannot get rid of the last value of an array. Simply removing dom elements with Javascript and submitting this does nothing to the last value of an array.

I would like to be able to empty an array so with the page reload, blank field is presented for the first value entry.

Removing array value

$(document).on "click", ".delete_step", (event) ->
  cache = $(this).closest(".step_set")
  cache.fadeOut "fast", ->
    cache.remove()
    null
  event.preventDefault()

Creating new field for new array value

$(document).on "click", "#add_step", (event) ->
  html = "<div class='step_set'>" + "<input type='button' class='delete_step' value='Delete'>" + "<input type='text' name='recipe[steps][]'>" + "</div>"
  $( "#steps" ).append html
  event.preventDefault ()

Controller

def update
  if @recipe.update_attributes!(recipe_params)
    respond_with(@recipe)
  else
    render 'edit'
  end
end

def recipe_params
  params.require(:recipe).permit(:title, :image, :serving, { steps: [] }, ingredients_attributes: [:id, :name, :_destroy])
end

View

<%= simple_form_for @recipe do |f| %>
  <button class="add" id="add_step">
    <span>+</span>Add Step
  </button>

  <fieldset id="steps"> 
    <% @recipe.steps.each_with_index do |individual_step, index| %>
      <div class="step_set" id="step_set<%= index %>">
        <a class="delete_step">Delete</a>
          <input type="text" value="<%= individual_step %>" name="recipe[steps][]">
      </div>
    <% end %>
  </fieldset>
<% end %>

After removing this element with delete and update

enter image description here

I still see this in the show page.

enter image description here

9
  • What is that "last value of array" ? How do you submit that ? Commented Feb 9, 2015 at 21:08
  • Try parents('.step_set:first') and could you give some example in jsfiddle? Commented Feb 9, 2015 at 21:23
  • I have no issue removing dom elements including the first one, the issue lies with submitting this form with no step elements present will still retain the first value of the array. Commented Feb 9, 2015 at 21:27
  • @alkuzad Hi, to be precise, it's the last value left in an array which I can't get rid of. Commented Feb 9, 2015 at 21:30
  • Please give me full example of this: recipe_params[:recipe][:steps]. steps are JSON/JSONB/HStore collection? Commented Feb 9, 2015 at 21:37

2 Answers 2

1

Ok, it seems that my hunch is correct. You're building your form with an object, @recipe. In your update action, @recipe still holds values and is carried over to your views.

How about trying to reinitialize @recipe in your update with @recipe = @recipe.new or something similar so that it's just an empty object of the class.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for your input, so you are saying reinitialise in the update action like def update @recipe = @recipe.new if @recipe.update_attributes!(recipe_params) respond_with(@recipe) else render 'edit' end end
Yes, something like that. Remember that when you build your form with an object, it retains the attributes when you render your view. Most of the time it's used to populate the fields when there's an error. But judging from your codes, you can use symbol in replace of your object -> <%= simple_form_for :recipe %>. Confirm this as I'm still vague on your code as a whole.
1
  1. As I understand, a recipe has many steps, right? So, step is a nested resource of recipe. You can check nested form tutorial here https://github.com/ryanb/nested_form#specifying-a-target-for-nested-fields. It also supports add and remove link to remove a nested field.

Because inside the model, if I understand correctly (a recipe has many steps), so if we call @recipe.steps, you expect to return an array of steps, but actually, it's the result of a query

SELECT * FROM steps WHERE recipe_id = #{id}

So when you call @recipe.update(st_here), it do not remove any step. That's why the step still appears in the next time you visit that recipe.

  1. Did you use Turbolink? If yes, move the javascript inside this ready = -> # YOUR CODE HERE $(document).ready(ready)

And why not use $(".delete_step").on("click", function() {}), it's more readable and follow the convention.

Hope this help.

2 Comments

Hi, thanks for your input. Question on your point #1 - to return an array of steps rather than the result of a query, what do I need to do?
Oh, just simply convert it to array to_a. Actually its behaviors is like an array (we can call @recipe.steps.each { # some cool thing } or first, last), and also is ActiveRecordRelation (ex: @recipe.steps.where(id: 4).order). The problem I mentioned about steps isn't a real data of a recipe, it's a result of a query (SELECT * FROM steps WHERE step.recipe_id = 1)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.