How can I nest a Rails erb <%= with in a <%= %> - ruby-on-rails

I have a partial that I am using on several pages that require an array to be passed from the views.
<div id="help-modal" class="hidden">
<%= render 'unit_setup_help', troubleshoot: "Unit Troubleshooting", message: <%= yield(:message_array) %> %>
</div>
I want message: message_array, with message_array be passed via the view.
I tried doing message: "#{yield(:message_array)}" but then I get an array with nested inside quotes. For example:
<% msg_array = ["Don't choose wrong one or you will die" ,"choose wrong one or you will die"] %>
<% content_for :message_array do %>
<%= msg_array %>
<% end %>
I get this error:
undefined method `each' for #
And this what my result looks like:
=> " ["Don't choose wrong one or you will die", "choose wrong one or you will die"]\n"

Related

Strange output from rails each do

Rails each do method is acting strangely and I do not know why.
controller
def index
#fabric_guides = FabricGuide.with_attached_image.all.order(:name)
end
index.html.erb
<div class="guide-items">
<%= #fabric_guides.each do |fabric| %>
<div class="guide-container">
<%= link_to fabric_guide_path(slug: fabric.slug) do %>
<%= image_tag fabric.image if fabric.image.attached? %>
<% end %>
<div class="guide-info">
<p class="g-name">
<%= link_to fabric.name,
fabric_guide_path(slug: fabric.slug) %>
</p>
</div>
</div>
<% end %>
</div>
I have two FabricGuide records so I expect two "guide-container" but I get three. Or more precisely I get two guide containers and a third block of text containing all the content from the last FabricGuide record.
I have almost an identical setup for articles and have never encountered this problem. I'd happily share more information if needed. Thank you!
Please remove = equal sign from your each loop of view code
like below :-
<% #fabric_guides.each do |fabric| %>
...
...
<% end %>
you have used this <%= #fabric_guides.each do |fabric| %> in your view that's why it shows all record in DOM.
The expression for erb tags is <% %>
now if we want to print that tag too then we apply <%= %>

Shows "#" instead of text

I am executing this code:
def find_all_from_id
Note.find_by_sql([%{SELECT NOTE_N FROM NOTES WHERE ORDSP_ID = #{#order.order_number}}])
end
And in ERB file, I have an output:
<div class="form-field notes-div" >
<%= service_form.label :notes, "Pakalpojuma papildinformācija:", :class => "label_for_cod", :style=>"width: 170px;" %>
<div style="float:left; width:400px;"><%#= notes %> <%= find_all_from_id %></div>
</div>
It puts the # symbol instead of text the that comes from the database (http://prntscr.com/kop3mz). Why? And how can I fix that?
Take a look at the documentation for find_by_sql: https://api.rubyonrails.org/classes/ActiveRecord/Querying.html
This method will return an array of instances. If you want to display information about those instances you need to iterate through the array and manually display the information you want to show. Erb will not display the array of instances, leading to your issue.
E.g.
<% find_all_from_id.each do |note| %>
<%= note.name %>
<%= note.id %>
<% end %>

undefined method `model_name' for NilClass:Class with Partials and Form for

I am having a weird issue where my rails application seemingly isn't reading the local variable passed to the partial, but only inside of form_for.
I have a set up a button where a user can bookmark an object, let's call it zoo.
The code looks like this:
Zoo Listing View:
<li><%= render 'directory/bookmarks', zoo: zoo %></i></li>
Then the directory/bookmarks partial:
<% if user_signed_in? %>
<% if current_user.has_zoo_bookmarked_already? %>
<%= form_for(current_user.bookmarks.find_by_zoo_id(zoo.id), html: { method: :delete }, remote: true) do |f| %>
<%= button_tag do %>
<button class="btn btn-lg btn-block btn-primary">remove bookmark
<% end %>
<% end %>
<% else %>
<%= form_for(current_user.bookmarks.build(zoo_id: zoo.id)) do |f| %>
<%= f.hidden_field :zoo_id, value: zoo.id %>
<%= button_tag do %>
<button class="btn btn-lg btn-block btn-primary">bookmark
<% end %>
<% end %>
<% end %>
<% else %>
<% end %>
Anyway, the problem is the zoo.id on the 3rd line is not being evaluated. I get this error.
undefined method `model_name' for NilClass:Class
The weird part is that locals are being read on the page.
If I place this code snippet <%= zoo.id %> anywhere on the page, I get the id. Then, the find_by_zoo_id is being evaluated also...if I put 255 a hardcoded number, it works. Or if I set it to a variable, #id = 255 and then pass in the #id, it works.
The zoo.id only does not work inside of the form_for for some reason. If I set it to an instance variable on the page, #id = zoo.id, that doesn't work either.
Any ideas? I'm sure it is something minor.
EDITED:
The relationship is has_many :through. Forgot to mention, I use this code for a different association in the same application and it works fine.
That error you're getting suggests current_user.bookmarks.find_by_zoo_id(zoo.id) is nil. find_by_zoo_id might be returning you nothing
Of course it was -- I was iterating through a list of zoos with bookmarks, but not all of them would be bookmarked by the user. I just had to add an additional condition.
<% if user_signed_in? %>
<% if current_user.has_zoo_bookmarked_already? && current_user.bookmarks.find_by_zoo_id(zoo.id) %>
#....

Rails local variable order in erb causing errors

So I have the following erb that works:
<ul class="list-group">
<%- #user_skills.each do |user_skill| %>
<li class="list-group-item"><%= user_skill.skill.name %></li>
<% end %>
</ul>
<%= semantic_form_for current_user.user_skills.new do |f| %>
<%= f.inputs %>
<%= f.actions %>
<% end %>
In my controller, I have a #user_skills = current_user.user_skills.
Once I swap the two blocks:
<%= semantic_form_for current_user.user_skills.new do |f| %>
<%= f.inputs %>
<%= f.actions %>
<% end %>
<ul class="list-group">
<%- #user_skills.each do |user_skill| %>
<li class="list-group-item"><%= user_skill.skill.name %></li>
<% end %>
</ul>
It raises an error like this: undefined methodname' for nil:NilClass`. So I'm guessing the form builder is somehow overwriting the user_skill inside the ul block. But why and how do I resolve the problem? It doesn't seem to be a formtastic issue, since I also used the native form builder.
UPDATE:
So I found out that the #user_skills array actually contains the just created user_skill, which hasn't been persisted and do not have a #skill_id or #skill.name! And if I do UserSkill.new at the start of the form, then the #user_skills array will be ok. Maybe there is a caching layer in activerecord that will automatically include just created objects into the query. Or is this a bug?
The call current_user.user_skills.new adds a blank user_skill to the has_many association of current_user. Since #user_skills is simply a reference to current_user.user_skills, the blank instance is included in the the unordered list when iterating after initializing the new user_skill record.
You'd be better off simply initializing a new user_skill in the form:
<%= semantic_form_for UserSkill.new do |f| %>
<%= f.inputs %>
<%= f.actions %>
<% end %>
Then, in the create action of your UserSkillsController, associate the user_skill attributes with the current_user. A bare-bones version could look something like:
def create
#user_skill = current_user.user_skills.create(params[:user_skill])
respond_with #user_skill
end

Error Handling Multi-Model Form

I have a multi-model form and I cannot seem to capture the errors related to the nested models. This is the hierarchy of the form Project->Team->Roles->Role_skill_relationship. I am able to capture errors related the project model instance #project but I have been unsuccessful at capturing validations related to the Role and Skills models. The errors are directly returned in the browser page rather than redirecting and flashing to the screen. One example of an error if I intentionally fill out a role portion of the form incorrectly is
NoMethodError in Roles#create
Showing
C:/Users/Dstile/Documents/GitHub/creunity_app/app/views/skills/_form.html.erb
where line #8 raised:
undefined method `map' for nil:NilClass Extracted source (around line #8)
7: <%= skill_form.label :skill %>
8: <%= skill_form.collection_select :skill_id, #skills, :id, :name, :prompt => "Select a > skill" %>
Here is a portion of the code
<%= render 'shared/project_error_messages' %>
<%= project_form.label :title %>
<%= project_form.text_field :title %>
<%= project_form.label :category, "Category" %>
<%= project_form.select(:category, Project::CATEGORY_TYPES) %>
<%= project_form.label :description %>
<%= project_form.text_area :description %>
<%= project_form.label :goal_1, "Goal 1:" %>
<%= project_form.text_field :goal_1 %>
<h2>Your Team</h2>
<%= project_form.fields_for :team do |f| %>
<%= render 'teams/form', :team_form => f %>
<% end %>`
Here is the error render code
'<% if #project.errors.any? %>
<div id="error_explanation">
<div class="alert alert-error">
The form contains <%= pluralize(#project.errors.count, "error") %>.
</div>
<ul>
<% #project.errors.full_messages.each do |msg| %>
<li>* <%= msg %></li>
<% end %>
</ul>
</div>
<% end %>'
The role form is nested within the team form in the same manner team is nested in project. From all of the other threads I have read my understanding is that the errors for project and all of its children models (team, roles, role_skill_relationships) should be captured by the #parent object.
Is there a config setting or piece of code I am missing that should force the browser to ignore the errors? My thinking is that the errors may be in #project but that this process is interrupted.
It appears #skills has not been set. #collection_select runs #map on the passed-in collection (#skills in this case), and will show that error if the collection is nil (which is the default value for undefined instance variables).
Remember that, in the case of validation errors, the #create method in your controller will simply be rendering a template - it does not run the corresponding action method for that template. So if you're defining #skills in your #new action, then you need to also define it in your #create action (or, better yet, in a before_filter).

Resources