Store several text_field strings to array Rails 3 - arrays

I'm trying to store some strings from a couple of text_fields that i have into an array, and then save it to the DB.
I have a column named "opening_hours" wich I've tried to separate into 2 different attributes using virtual attributes like this:
Model
class Venue < ActiveRecord::Base
attr_accessible :opening_hours, :start_time, :end_time
attr_writer :start_time, :end_time
def start_time
#start_time.nil? ? #start_time : opening_hours.to_s.split("-").first
end
def end_time
#end_time.nil? ? #end_time : opening_hours.to_s.split("-").last
end
end
The idea is that you type in a start_time and an end_time like this:
View
<%= form_for #venue do |v| %>
<p><%= v.label "Monday" %><%= v.text_field :start_time %>-<%= v.text_field :end_time %><p/>
<p><%= v.label "Tuesday" %><%= v.text_field :start_time %>-<%= v.text_field :end_time %><p/>
<p><%= v.label "Wednesday" %><%= v.text_field :start_time %>-<%= v.text_field :end_time %><p/>
<% end %>
The array should look something like this in the DB:
{08-12|09-14|07-13}
With the "|" separating the different days of the week.
I've tried a couple of things in the controller like:
Controller
class VenuesController < ApplicationController
def new
#venue = Venue.new
end
def create
#venue = Venue.new(params[:venue])
#total_time = params[:venue][:start_time]+"-"+params[:venue][:end_time]
#venue.opening_hours = #total_time.map {|t| [t.start_time, t.end_time]}
if #venue.save
redirect_to venue_path(#venue), :notice => "Success!"
else
render 'new'
end
end
But nothing seems to work... either it just saves start_time and end_time from the last day, or nothing gets saved at all.

I perhaps may have misunderstood, but...
In your create action, there is no #venue.save - this could be why you are not seeing anything saved.
class VenuesController < ApplicationController
def new
#venue = Venue.new
end
def create
#venue = Venue.new(params[:venue])
#total_time = params[:venue][:start_time]+"-"+params[:venue][:end_time]
#venue.opening_hours = #total_time.map {|t| [t.start_time, t.end_time]}
#venue.save
end
end

Your solution will not work, since you place three text-fields each pointing to the same field. Rails will just take the last value.
Rails will use the name of the input field to construct the parameters hash you receive at the server. Since the fields have the same name, only one value will remain.
The solution is pretty simple: using the same rails standards, we can change the name of the input fields so rails will handle it as a hash.
<p>
<%= v.label "Monday" %>
<%= text_field :venue, 'start_time[][monday]', :value => '07' %>
<%= text_field :venue, 'end_time[][monday]', :value => '21' %>
<p/>
<p>
<%= v.label "Tuesday" %>
<%= text_field :venue, 'start_time[][tuesday]', :value => '07' %>
<%= text_field :venue, 'end_time[][tuesday]', :value => '09' %>
<p/>
Since end_time and start_time is not a array, I have to fake it a bit, so I use a manual text_field, use as object-name venue so it will be grouped with the rest of the parameters for your venue. Then I build the name, so rails will compose a hash with the values entered. Note, you have to explicitly define a value, or this will not work.
Then, in the controller, you will have to add some code to
when editing, convert the array-string to values in your form
when saving, convert the recevied hash to a string you can save.
Note: if you do not, it will save the serialized hash, which might just be enough already.

Related

Ruby - Fail statement/Guard Condition returning nil

I'm trying to improve the release_bike method.
I have gone into irb, and the first guard condition works, and the release_working_bikes work, but the second guard condition keeps on return nil in irb, even when I run a feature test and know that there is only a broken bike available.
Is there something wrong with the way I'm phrasing my second fail line, or is there a flaw in broken_bikes ?
The release_bike method should work as follows;
if there are no bikes in the docking station, then there should be a warning saying - No bikes available
if there are bikes in the docking station, but they are ALL broken, then there should be a warning saying - No working bikes available
if there are some working bikes, then release_bike should release one of the workign bikes.
Below are the two classes, that are involved;
require_relative 'bike'
class DockingStation
DEFAULT_CAPACITY = 20
attr_reader :capacity, :bikes
def initialize(capacity = DEFAULT_CAPACITY)
#bikes = []
#capacity = capacity
end
def release_bike
fail 'No bikes available' if empty?
fail 'No working bikes available' unless broken_bikes
release_working_bikes
end
def dock(bike)
fail 'Docking Station Full' if full?
#bikes << bike
end
private
def working_bikes
#bikes.each { |bike| return bike unless bike.broken? }
end
def broken_bikes
not_working = []
not_working << #bikes.each { |bike| return bike if bike.broken? }
not_working.empty?
end
def release_working_bikes
bike = working_bikes
#bikes.delete(bike)
end
def full?
#bikes.count >= #capacity
end
def empty?
#bikes.empty?
end
end
class Bike
attr_accessor :broken
def initialize
#broken = false
end
def working?
#working
end
def report_broken
#broken = true
end
def broken?
#broken
end
end
As already pointed out in comments, you're trying to check if all bikes are broken, so why not name your method all_bikes_broken? . See comments in code.
require_relative 'bike'
class DockingStation
DEFAULT_CAPACITY = 20
attr_reader :capacity, :bikes
def initialize(capacity = DEFAULT_CAPACITY)
#bikes = []
#capacity = capacity
end
def release_bike
fail 'No bikes available' if empty?
fail 'No working bikes available' unless all_bikes_broken?
release_working_bikes
end
def dock(bike)
fail 'Docking Station Full' if full?
#bikes << bike
end
private
def working_bikes
#this will select only bikes which are NOT broken
#bikes.reject{ |bike| bike.broken? }
end
def all_bikes_broken?
#this is shorthand for #bikes.all?{ |bike| bike.broken? }
#it says send :broken? method to each instance of bike.
#.all? returns true only if all instances return true, otherwise false.
#bikes.all?(&:broken?)
end
def release_working_bikes
bike = working_bikes
#bikes.delete(working_bikes.first)
#or you could do .last but order probably doesn't matter here.
end
def full?
#bikes.count >= #capacity
end
def empty?
#bikes.empty?
end
end
class Bike
attr_accessor :broken
def initialize
#broken = false
end
def working?
#working
end
def report_broken
#broken = true
end
def broken?
#broken
end
end

Elixir/Ecto not recognizing Foreign Key in Model

I am trying to retrieve and print an item in a one to many relationship (in this case I want to print an Article with all it's comments), in elixir/ecto.
I am getting the following error -
[error] GenServer #PID<0.398.0> terminating
** (Ecto.QueryError) deps/ecto/lib/ecto/association.ex:516: field `articles_id` in `where` does not exist in schema Newsly.Comments in query:
from c in Newsly.Comments,
where: c.articles_id == ^1,
order_by: [asc: c.articles_id],
select: {c.articles_id, c}
(elixir) lib/enum.ex:1826: Enum."-reduce/3-lists^foldl/2-0-"/3
(elixir) lib/enum.ex:1372: Enum."-map_reduce/3-lists^mapfoldl/2-0-"/3
(elixir) lib/enum.ex:1826: Enum."-reduce/3-lists^foldl/2-0-"/3
(ecto) lib/ecto/repo/queryable.ex:124: Ecto.Repo.Queryable.execute/5
(ecto) lib/ecto/repo/queryable.ex:37: Ecto.Repo.Queryable.all/4
(elixir) lib/enum.ex:1270: Enum."-map/2-lists^map/1-0-"/2
Last message: %Phoenix.Socket.Message{event: "addComment", join_ref: "43", payload: %{"articleid" => 1, "message" => "asdfasdfsasdfasdferqweasdfas", "user" => "peter"}, ref: "45", topic: "room:lobby"}
State: %Phoenix.Socket{assigns: %{}, channel: Newsly.RoomChannel, channel_pid: #PID<0.398.0>, endpoint: Newsly.Endpoint, handler: Newsly.UserSocket, id: nil, join_ref: "43", joined: true, private: %{log_handle_in: :debug, log_join: :info}, pubsub_server: Newsly.PubSub, ref: nil, serializer: Phoenix.Transports.V2.WebSocketSerializer, topic: "room:lobby", transport: Phoenix.Transports.WebSocket, transport_name: :websocket, transport_pid: #PID<0.389.0>, vsn: "2.0.0"}
What is strange about this error is that it says that it cannot find articles_id, but I am calling article_id when I make the preload of the comments, and throughout the rest of my code.
Here is where I call the Repo
defmodule Newsly.CommentController do
alias Newsly.{Repo, Articles, Comments}
def addComment(articleid, message, user) do
IO.puts "inside addComment() in CommentController"
article = Repo.get(Articles, articleid)
|> Repo.preload(:comments) #this line is giving the error - when I take it out the error goes away (although comments are not preloaded)
IO.puts "article"
IO.inspect article
end
end
Here is my model -
defmodule Newsly.Comments do
use Newsly.Web, :model
schema "comment" do
field :body, :string
field :user, :string
field :upvotes, :integer
field :downvotes, :integer
field :flaggedcount, :integer
belongs_to :article, Newsly.Articles, foreign_key: :article_id #I don't call articles_id here!!! only article_id (singular). Ecto is seeing in the database a relationship that does not exist!
timestamps()
end
#doc """
Builds a changeset based on the `struct` and `params`.
"""
def changeset(struct, params \\ %{}) do
struct
|> cast(params, [:body, :user, :upvotes, :downvotes, :flaggedcount])
|> validate_required([:body, :user, :upvotes, :downvotes, :flaggedcount])
end
end
And just to doublecheck....
Here is the postgres database association I have locally - notice that article_id exists (not articles_id)
newsly_dev=# table comment;
id | body | user | upvotes | downvotes | flaggedcount | article_id | inserted_at | updated_at
----+------+------+---------+-----------+--------------+------------+-------------+------------
(0 rows)
I'm completely lost. Anyone have any ideas?
Since you're first fetching an article and then fetching its comments, Ecto will use the has_many declaration of Articles model and you're most likely missing the custom foreign_key in that.
has_many :comments, Newsly.Comments, foreign_key: :article_id
^^^^^^^^^^^^^^^^^^^^^^^^

Do..end loop just returning main array

Can anyone help me to find problem here?
#deals.each.with_index(1) do |deal, i|
binding.pry
puts "#{deal.title} - #{deal.price} - Rating: #{deal.deal_rating}"
# puts "Available for #{deal.price}"
# puts "Rating: #{deal.deal_rating}"
# puts "#{deal.title}"
# puts "Available at "
end
If I do binding.pry, and try to check the value of deal here, it is returning me complete #deals array rather than one deal.
Thank you so much in advance for your help.
Use just each_with_index which will give you the object and the index inside the total of elements being iterated:
<% #deals.each_with_index do |deal, i| %>
<% binding.pry %>
<%= "#{deal.title} - #{deal.price} - Rating: #{deal.deal_rating}" %>
<% end %>
This way inspecting with pry you take the first element from #deals:
[1] pry(#<#<Class:0x007fe0cd161ee8>>)> #deals.first
=> #<Deal:0x007fe0cb2751d8
id: 1,
title: "Deal-0",
price: 764,
deal_rating: 93,
created_at: Sat, 01 Apr 2017 15:00:29 UTC +00:00,
updated_at: Sat, 01 Apr 2017 15:00:29 UTC +00:00>
If you want to do it in your views then use unless to check for the first element using the index:
<% #deals.each_with_index do |deal, i| %>
<% unless !i.zero? %>
<%= "#{deal.title} - #{deal.price} - Rating: #{deal.deal_rating}" %>
<% end %>
<% end %>
The difference is that with with_index you can use an optional parameter to offset the starting index, so you're specifying the index from where to start with with_index(1) not trying to get the first element, see this:
<% #deals.each.with_index(2) do |deal, index| %>
<%= "#{index}: #{deal}" %><br>
<% end %>
2: #<Deal:0x007fe0cb55ca90>
3: #<Deal:0x007fe0cb55c950>
4: #<Deal:0x007fe0cb55c810>
...
This starts from the index 2, and the other one from 0.
<% #deals.each_with_index do |deal, index| %>
<%= "#{index}: #{deal}" %><br>
<% end %>
0: #<Deal:0x007fe0cb55ca90>
1: #<Deal:0x007fe0cb55c950>
2: #<Deal:0x007fe0cb55c810>
3: #<Deal:0x007fe0cb55c6d0>
4: #<Deal:0x007fe0cb55c590>

Rails 4 Nested Attributes with fields_for Don't Save to Database

I want to create records on two different tables (venue and parking) via one form using accepts_nested_attributes_for. I want a user to be able to create a new venue, and also specify the parking options available to that venue via checkboxes. When I submit the form, the record for the containing model (venue) is created, but nothing happens with the nested model (parking). When I check the response from the server, I see that I'm encountering "Unpermitted parameters: parking_attributes," although I'm not sure why.
I've watched Railscast #196 Nested Model Form, and tried the suggestions from multiple stackoverflow posts (Rails 4 nested attributes not saving, Rails 4: fields_for in fields_for, and Rails 4 - Nested models(2 levels) not saving). If anybody can help me out, I'd greatly appreciate it.
I've included the two models, the venues controller, the venues/new view, and the response from the server.
venue.rb
class Venue < ActiveRecord::Base
has_many :parkings
accepts_nested_attributes_for :parkings
end
parking.rb
class Parking < ActiveRecord::Base
belongs_to :venue
end
venues_controller.rb
class VenuesController < ApplicationController
def index
#venues = Venue.all
end
def new
#venue = Venue.new
end
def create
#venue = Venue.new(venue_params)
if #venue.save
redirect_to #venue, flash: { success: "Venue successfully created" }
else
render :new
end
end
def show
#venue = Venue.find(params[:id])
end
def edit
#venue = Venue.find(params[:id])
end
def update
#venue = Venue.find(params[:id])
if #venue.update(venue_params)
redirect_to #venue
else
render "edit"
end
end
def destroy
#venue = Venue.find(params[:id])
if #venue.destroy
redirect_to venues_path, flash: { success: "Venue successfully destroyed" }
else
render "show", flash: { error: "Venue was not successfully destroyed" }
end
end
private
def venue_params
params.require(:venue).permit(
:name,:address,:city,:state,:zip,
parking_attributes: [:id, :venue_id, :none, :street_free])
end
end
/venues/new.haml
%h1 Add a new venue
= form_for #venue do |f|
= f.label :name
= f.text_field :name
= f.label :address
= f.text_field :address
= f.label :city
= f.text_field :city
= f.label :state
= f.text_field :state
= f.label :zip
= f.text_field :zip
= f.fields_for :parkings do |p|
= p.label :none
= p.check_box :none
= p.label :street_free
= p.check_box :street_free
= f.submit
Server response
Started POST "/venues" for 127.0.0.1 at 2014-04-29 14:02:54 -0500
Processing by VenuesController#create as HTML
Parameters: {"utf8"=>"✓",
"authenticity_token"=>"kMcVVwXq7f22rIGm1rQ6+QzC80ScmXrVA2IE8TGbN7w=",
"venue"=>{"name"=>"The Five O'Clock Lounge",
"address"=>"11904 Detroit Ave",
"city"=>"Lakewood",
"state"=>"OH",
"zip"=>"44107",
"parkings_attributes"=>
{"0"=>
{"none"=>"1",
"street_free"=>"0"
}
}
},
"commit"=>"Create Venue"}
Unpermitted parameters: parkings_attributes
(0.2ms) BEGIN
SQL (107.0ms) INSERT INTO "venues" (
"address",
"city",
"created_at",
"name", "state",
"updated_at", "zip"
) VALUES ($1, $2, $3, $4, $5, $6, $7) RETURNING "id"
[
["address", "11904 Detroit Ave"],
["city", "Lakewood"],
["created_at", Tue, 29 Apr 2014 19:02:54 UTC +00:00],
["name", "The Five O'Clock Lounge"],
["state", "OH"],
["updated_at", Tue, 29 Apr 2014 19:02:54 UTC +00:00],
["zip", 44107]
]
SQL (47.5ms) INSERT INTO "parkings" (
"created_at",
"updated_at",
"venue_id") VALUES ($1, $2, $3) RETURNING "id"
[
["created_at", Tue, 29 Apr 2014 19:02:54 UTC +00:00],
["updated_at", Tue, 29 Apr 2014 19:02:54 UTC +00:00],
["venue_id", 10]
]
(0.6ms) COMMIT
Redirected to http://localhost:3000/venues/10
Completed 302 Found in 165ms (ActiveRecord: 155.2ms)
UPDATE: SOLVED
Following the advice of Kirti, I was able to get past the unpermitted parameters error.
Update venue_params method as below:
def venue_params
params.require(:venue).permit(
:name,:address,:city,:state,:zip,
parkings_attributes: [:id, :venue_id, :none, :street_free])
end
Notice parkings_attributes(plural parkings) and not parking_attributes(singular parking).
As you have 1-M relationship between Venue and Parking model you would receive parkings_attributes(plural parkings) in params hash BUT in your current code for venue_params you whitelisted parking_attributes(singular parking). This is causing the warning Unpermitted parameters: parkings_attributes

Server.Execute Duplicates Dynamic Content

I created a page in ASP that loads dynamic content with code similar to this:
<%
var1 = int(rnd * 5) + 1
var2 = int(rnd * 10) + 1
%>
<html>
<body>
what variable 1 is: <%=var1%>
what variable 2 is: <%=var2%>
</body>
</html>
Then I have another page that uses Server.Execute to execute the previous file mentioned 2+ times using a loop. The code looks like this:
<% filename = request.querystring("page") %>
<table class="domtable">
<% for j = 1 to 2%> <%qnumb = qnumb + 1%>
<tr>
<td align="left">
<%server.execute (filename)%>
<% If qnumb < 2 then%>
<br/><hr><br/>
<%end if%>
</td></tr>
<%next%>
</table>
So for the last couple of months this has been working perfectly for me, loading different numbers for both variables on the two separate executions. Then today, I duplicated a folder on my server, renamed it and now magically, the variables are the same number about 9 out of 10 times the browser is refreshed.
This happened to me with the same files on my second server a month ago, and I had to delete all the files off of the second server, and download them from my first server (the one duplicating now), then upload them back and that fixed it. Unfortunately, I didn't download the entire server contents of my first server so I'm unable to reverse the process. So I'm not sure if this issue is server-side, or if it's related with the code I'm writing? I just don't know why it would work for so long then just stop working out of nowhere.
I've tried using meta no-cache controls. I deleted the new folder I duplicated earlier from the server and that didn't work. I also tried deleting files from the last couple days that have been uploaded and that didn't work either. I've tried loading 'filename' as an array such as:
filename(1) = request.querystring("page")
filename(2) = request.querystring("page")
for j = 1 to 2
Server.Execute(filename(j))
next
I really hope someone knows what I'm doing wrong here.
-EDIT-
I'm also doing this and getting the same results.
<%
'rnd.asp'
pStr = "private, no-cache, must-revalidate"
Response.ExpiresAbsolute = #2000-01-01#
Response.AddHeader "pragma", "no-cache"
Response.AddHeader "cache-control", pStr
server.execute ("rndj.asp")
response.write ("<hr>")
randomize(3)
server.execute ("rndj.asp")
%>
<%
'rndj.asp'
pStr = "private, no-cache, must-revalidate"
Response.ExpiresAbsolute = #2000-01-01#
Response.AddHeader "pragma", "no-cache"
Response.AddHeader "cache-control", pStr
randomize
response.write rnd
response.write "<br>"
response.write rnd
%>
I started to use this code below which looks at the specified file as plain text and removes the asp tags from it then uses Execute to run it within the original file. The problem with this is all my pages that i call use in them for other resources and the replace script wont let me add asp tags around the include lines.
<%
Dim sTargetFile, sTargetFileContents
Dim oFSO, sContents
Function GetFileContentsForExecution(sTargetFile)
'Obtain a reference to the FileSystemObject
Set oFSO = Server.CreateObject("Scripting.FileSystemObject")
'Obtain the file contents
sContents = oFSO.OpenTextFile(Server.MapPath(".") & "\" & sTargetFile).ReadAll
Set oFSO = Nothing 'reference to the FileSystemObject
'Remove the ASP scripting tags
rand = int(rnd * 2)
sContents = Replace (sContents, "<" & "%", "")
sContents = Replace (sContents, "%" & ">", "")
GetFileContentsForExecution = sContents
End Function
sTargetFile = "rndj.asp"
for j = 1 to 6
'Get the contents of the file to execute
sTargetFileContents = GetFileContentsForExecution(sTargetFile)
Execute sTargetFileContents
next
if j < 3 then
response.write ("<br/><hr><br/>")
end if
%>
Link to working solution
<%
'rnd.asp'
randomize
application("randomseed") = rnd
server.execute ("rndj.asp")
application("randomseed") = rnd
server.execute ("rndj.asp")
%>
<%
'rndj.asp'
randomize application("randomseed")
response.write rnd
response.write("<br />")
response.write rnd
response.write("<br />")
response.write("<br />")
%>

Resources