converting string to array - Ruby on Rails - ruby-on-rails

I'm trying to convert a string to an array. The method I'm using seems to be working but when I check with pry it's still a string. Let me show you my method and output and see if you can tell me what's wrong. Thank you.
Method:
def filters=(filters)
if filters.is_a?(String)
filters = filters.split(",")
end
list = Set.new
Array.wrap(filters).each do |filter|
filter.tr!(",", " ")
filter.strip!
list << filter unless filter == ""
end
super(list.to_a)
end
View
in the text field I placed hey, ohh
<%= form_for #integrations, url: url_for(:controller => :integrations, :action => :update, :id => #integrations.id) do |f| %>
<%= f.label :filters %>
<%= f.text_field :filters, class: "filter-autocomplete" %>
<%= f.submit "Save" %>
<% end %>
Controller
def update
#integrations = current_account.integrations.find(params[:id])
if #integrations.update_attributes(update_params)
flash[:success] = "Filters added"
redirect_to account_integrations_path
else
render :filters
end
end
def filters
#integrations = current_account.integrations.find(params[:id])
end
if you put a pry on the end of that it seems that it has converted to an array. but when I check the object it still remains a string.
when I look at my filters now in the console they look like this
"[\"Hey\", \"ohh\"]"
when I want it to look like:
["Hey", "ohh"]

Related

Why is my form not saving? form_for question

I have this form. I am new to rails and I am trying to write a simple ecommerce site. This is the only part not working. (It worked 2 days ago I sear)
<%= form_tag line_items_path do%>
<%binding.pry%>
<%= hidden_field_tag :lite_item, :order_id, #order.id%>
<%= hidden_field_tag :line_item, :menu_item_id, #menu_item.id%>
<%= number_field_tag :line_item, :quantity, 1 %>
<%= submit_tag "Add to Cart"%>
<% end %>
It gives params that look like:
#<ActionController::Parameters {"authenticity_token"=>"VECKnS5SBot1rCyekepPXZa7TyTYkfFi0KdNRTB617ZnelmQo8Lkz_cJmQ8nAmCHUdDlPu1mpkhrPvMKysfjew", "order_id"=>"1", "menu_item_id"=>"1", "quantity"=>"1", "commit"=>"Add to Cart", "controller"=>"line_items", "action"=>"create"} permitted: false>
The controller for the view looks like this:
class MenusController < ApplicationController
def index
#menu_items = MenuItem.all
end
def show
#menu_item = MenuItem.find(params[:id])
#line_items = current_order.line_items.build
end
end
The form is really going through the line_items controller
def create
binding.pry
#line_item = LineItem.create(line_item_params)
if #line_item.save
#order.line_item_id = #line_item.id
#order.save
redirect_to cart_path(#current_cart), notice: "Item added to cart."
else
redirect_to menu_path(#menu_item), alert: "Item did not add to cart."
end
end
With strong params like this
def line_item_params
params.require(:line_item).permit(:menu_item_id, :quantity, :order_id)
end
It should use the line_items_path POST>
If anything else is needed just ask. Thanks in advance.
There are a lot of problems here.
The signature is hidden_field_tag(name, value = nil, options = {}). So the parameters you would actually be creating with that form is:
{
"lite_item" => "order_id", # check your spelling...
"line_item" => "quantity"
}
Oops. And that not even going to happen as <%= number_field_tag :line_item, :quantity, 1 %> will raise since you're passing an integer where the method expects a hash.
If you really have to create the inputs manually you would want:
<%= hidden_field_tag "line_item[order_id]", #order.id %>
But since you actually have a model there is no reason why you should be using form_tag instead of form_for(#line_item) or form_with(model: #line_item).
<%= form_for(#line_item) do |form| %>
<%= form.hidden_field :order_id %>
<%= form.hidden_field :menu_item_id %>
<%= form.number_field :quantity %>
<%= form.submit_tag "Add to Cart"%>
<% end %>
The controller should also use the correct pluralization for the instance variable:
def show
#menu_item = MenuItem.find(params[:id])
#line_item = current_order.line_items.build
end
Your create method is also pretty questionable. All you should need is:
def create
# use .new not .create
#line_item = LineItem.new(line_item_params)
if #line_item.save
redirect_to cart_path(#current_cart), notice: "Item added to cart."
else
redirect_to menu_path(#menu_item), alert: "Item did not add to cart."
end
end
I have no idea why you think you need to update #order here. Your controller should just really be adding a row to what is essentially a join table.

Rails double the records on update_attributes

My update function double the records for nested items in model on submit.
The one, which is NOT in the fields_for works as expecting, but every record in fields_for is doubling.
What am I missing? Any help will be highly appreciated
def edit
#printer = Printer.find(params[:id])
end
def update
#printer = Printer.find(params[:id])
if #printer.update_attributes(printer_params)
redirect_to #printer
else
render 'edit'
end
end
def printer_params
params.require(:printer).permit(:model, colors_attributes: [:color], materials_attributes: [:material], printer_photos_attributes: [:image_url] )
end
edit.html.erb
<%= form_for #printer, html: { multipart: true }, :url => url_for(:controller => 'printers', :action => 'update') do |p|%>
<%= p.text_field :model %>
<%= p.fields_for :colors do |color|%>
<%= color.text_field :color %>
<% end %>
<%= p.submit "Edit" %>
<% end %>
You are missing :id in printer_params. Without :id each your update for nested params is considered to be a new record. It should be as following for your colors_attributes:
def printer_params
params.require(:printer).permit(:model, colors_attributes: [:id, :color], materials_attributes: [:material], printer_photos_attributes: [:image_url] )
end
I guess, you should also correct your other nested attributes in this method.

Edit page to display all category names with edit inputs on each

I have categories nested inside of guides. I'm building an app to learn rails better and I'm trying to make a page that will display all categories that belong to a guide and have edit inputs under them and a save button next to it so the user can edit the names of the categories they want to change.
Bit stuck on how exactly how get this done.
here is the category_item_keys controller
def edit
#guide = Guide.friendly.find(params[:guide_id])
#category = Category.friendly.find(params[:category_id])
#key = #category.category_item_keys
end
def update
#guide = Guide.friendly.find(params[:guide_id])
#category = Category.friendly.find(params[:category_id])
#key = #category.category_item_keys.friendly.find(key_params) # no idea what to make this equal because it isn't one set key being edited on the page
if #key = #category.category_item_keys.update_attributes(key_params)
flash[:success] = "Key updated"
redirect_to #guide
else
render 'edit'
end
end
private
def key_params
params.require(:category_item_key).permit(:key, :slug)
end
routes
match '/guides/:guide_id/:category_id/keys/edit' => 'category_item_keys#edit', :via => :get
match '/guides/:guide_id/:category_id/keys/' => 'category_item_keys#update', :via => :post, as: :category_item_keys_update
edit.html.erb
<ul>
<% #key.each do |key| %>
<li><%= key.key #just shows key name %><br>
<%= form_for([#category, #keys], url: category_item_keys_create_path) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<%= f.label :key, "Key name" %>
<%= f.text_field :key %>
<%= f.submit "Save" %>
<% end %>
</li>
<% end %>
</ul>
This just gives me an error of:
undefined method `to_key' for #<CategoryItemKey::ActiveRecord_Associations_CollectionProxy:0x007fe20a86b480>
Later I plan on using an in-place editor gem but i would like to learn how this can be done fist.
EDIT:
Fixed the error ( changed form_for([#category, #keys] to form_for([#category, key] and turns out this way works for displaying and allowing all categories to be edited... to an extent.
I get another error when i submit a form
undefined method 'update_attribute'
EDIT 2
slowly getting there. I Changed the update #key variable to #key = #category.category_item_keys.all to fix the error. But this line is now giving me problems
if #key = #category.category_item_keys.update_attributes(key_params)'
THIRD EDIT
ERROR
Couldn't find CategoryItemKey without an ID
on line
#key = #category.category_item_keys.find params[:id]
paramaters:
{"utf8"=>"✓", "_method"=>"patch", "authenticity_token"=>"egj/OebdSbxxaoaTkr46WVIOIIu4Ezijzu45kqxLT0krjFWHqi67SRJDSgV7bcL6SeoGpUSYsrolspylCXBu9g==",
"category_item_key"=>{"name"=>"def1111"},
"commit"=>"Save",
"guide_id"=>"dbz",
"category_id"=>"characters"}
Here's how to clean up the code:
#config/routes.rb
resources :guides do
resources :categories, path: "" do
resources :category_item_keys, path: "keys", only: [:update] do
get :edit, on: :collection #-> url.com/guides/:guide_id/:category_id/keys/edit
end
end
end
#app/controllers/keys_controller.rb
class KeysController < ApplicationController
def edit
#guide = Guide.find params[:guide_id]
#category = Category.find params[:category_id]
#keys = #category.category_item_keys
end
def update
#guide = Guide.find params[:guide_id]
#category = Category.find params[:category_id]
#key = #category.category_item_keys.find params[:id]
if #key.update key_params
redirect_to #guide, success: "Key Updated"
else
render 'edit'
end
end
private
def key_params
params.require(:category_item_key).permit(:key)
end
end
#app/views/keys/edit.html.erb
<% #keys.each do |key| %>
<%= form_for [#guide, #category, key] do |f| %>
<%= f.text_field :key %>
<%= f.submit %>
<% end %>
<% end %>
If you wanted to use an in-place editor gem, I'd recommend looking at X-Editable, as we've applied it here (its only a demo app, just sign up for free and go to profile):
Looks like you are trying to do update_attributes on a collection instead of an object. Try to first fetch the key object
#key = #category.category_item_keys.friendly.find(params[:id])
and then try to update its attributes
if #key.update_attributes(key_params)
...
end
use nested forms available in rails 4.

Rails accessing custom method instance variable

What I am trying to do is add a simple search to a 'show' view in my rails app. I've watched the rails cast about simple search and it's given me some good direction but I can't seem to get it to work with my situation. I just have a list of FAQs and want to have a search filter for the 'question(s)'.
Here's my views/guests/show.html.erb
<%= form_tag faq_search_guests_path, method: :get, remote: true, :id => "faq_search_form" do %>
<p>
<%= text_field_tag :search, params[:search] %>
<%= submit_tag "Search", :name => nil %>
</p>
<% end %>
<div id="faq-search-test"></div>
<% #faqs.each do |f| %>
<h4>Question</h4>
<%= f.question %>
<h4>Answer</h4>
<%= f.answer %>
<% end %>
Here's the controller/guests_controller.rb method that originally sets #faqs
def show
#guest = Guest.find(params[:id])
#hotel = Hotel.find(params[:hotel_id])
#faqs = Faq.where(hotel_id: #hotel.id)
#template = Template.where( hotel: #hotel.id )
#visit = Visit.where("hotel_id = ? AND guest_id = ?", #hotel.id, #guest.id).last
#visit = Visit.find(params[:visit_id]) if params[:visit_id] && (#visit.hotel_id == #hotel.id)
unless current_user.hotels.include?(#hotel)
render :file => "public/401.html", :status => :unauthorized
end
end
Here's my controllers/guests_controller.rb custom method my form is calling
def faq_search
#faq_result = Faq.search(params[:search])
render :nothing => true
end
Here's my routes.rb for that
resources :guests do
get 'faq_search', :on => :collection
end
resources :faqs
Here's my models/faq.rb
def self.search(search)
if search
where('question LIKE ?', '%#{search}%')
else
scoped
end
end
So from here, I am having trouble displaying #faq_result in show.html.erb. I guess I have no idea how to access an instance variable from a custom controller method from a view.
Any help would be much appreiciated :)!

Incorrect param submitting

I have a form for casting your vote for your favourite image.
<%= form_for(#imagevote) do |f| %>
<% #miniature.collections(:photo).each do |collection| %>
<% if collection.photo.exists? %>
<td><div class="photo1">
<%= link_to image_tag(collection.photo.url(:thumb), :retina => true), collection.photo.url(:original), :retina => true, :class => "image-popup-no-margins" %>
<%= f.radio_button(:collection_id, collection.id) %>
<%= f.hidden_field :voter_id, :value => current_user.id %>
<%= f.hidden_field :voted_id, :value => collection.user_id %>
<%= f.hidden_field :miniature_id, :value => #miniature.id %>
<p>Painted by <%= link_to collection.user.name, collection.user %></p>
</div></td>
<% end %>
<% end %>
<%= f.submit "Vote" %>
<% end %>
Everything submits correctly except for the hidden_field :voted_id which for some reason duplicates the current_user.id.
UPDATE
I've tried logging in as another user and it seems that :voted_id is not duplicating current_user.id but rather that it is always "7" which was the :user_id I was using to test it before. Now logged in as user number 4 it is still entering the :voted_id as 7. I'm lost.
The link to the imagevotes view is as follows:
<%= link_to "See more and change your vote.", edit_imagevote_path(:miniature_id => #miniature, :voter_id => current_user.id) %>
Here is my image votes controller
class ImagevotesController < ApplicationController
respond_to :html, :js
def new
#imagevote = Imagevote.new
#miniature = Miniature.find(params[:miniature_id])
end
def edit
#imagevote = Imagevote.find_by_miniature_id_and_voter_id(params[:miniature_id],params[:voter_id])
#miniature = Miniature.find(params[:miniature_id])
end
def create
#imagevote = Imagevote.new(imagevote_params)
if #imagevote.save
flash[:success] = "Vote registered"
redirect_to :back
else
flash[:success] = "Vote not registered"
redirect_to :back
end
end
def update
#imagevote = Imagevote.find(params[:id])
if #imagevote.update_attributes(imagevote_params)
flash[:success] = "Vote changed."
redirect_to :back
else
redirect_to :back
end
end
private
def imagevote_params
params.require(:imagevote).permit(:collection_id, :voter_id, :voted_id, :miniature_id)
end
end
You only have one #imagevote object, but you are outputting the hidden fields inside your collection loop so you will have multiple fields in the form referencing the same attribute on the model: if you check the html that is generated, you should see multiple hidden fields with the same name attribute.
The way that browsers handle multiple inputs with the same name means that the param that comes through for :voted_id will always be the :user_id from the last collection.
It's difficult to say because you didn't provide your model and your loop code stripped.
I would guess that you loop over collection that belongs to the current_user. And in this case you will have current_user.id always be the same as collection.user_id. May be you wanted to see collection.photo_id?

Resources