Sinatra + SQLite + ActiveRecord (strings can not be saved) - sqlite

I have a problem with saving strings in database. Integers are going well. I have a model Paymentwith one field :command(String). This is from console:
p = Payment.new
p.command = 'test'
=> "test"
p.save
=> D, [2014-10-20T15:30:43.383504 #2229] DEBUG -- : (0.2ms) begin transaction
=> D, [2014-10-20T15:30:43.386985 #2229] DEBUG -- : (0.1ms) commit transaction
=> true
Payment.last
=> #<Payment id: 1, command: nil>
My app file
require 'sinatra'
require 'activerecord'
require 'sinatra/activerecord'
set :database, 'sqlite3:qiwi_exline_development.sqlite3'
get '/' do
#payments = Payment.all
haml :index
end
class Payment < ActiveRecord::Base
include ActiveModel::Model
attr_accessor :command
end
My schema
ActiveRecord::Schema.define(version: 20141020092721) do
create_table "payments", force: true do |t|
t.string "command"
end
end
Interesting moment: If i change string to integer in schema -> integer values are saved without any problems.

Remove attr_accessor from model. In the case of ActiveRecord models, getters and setters are already generated by ActiveRecord for your data columns. attr_accessor is not needed. attr_accessor — is a deprecated method of controlling mass assignment within ActiveRecord models.

Related

Extending Solidus to have file upload attached to an order

app/models/upload/graphic.rb
class Upload::Graphic < ApplicationRecord
belongs_to :order, class_name: "Spree::Order", optional: true
has_one_attached :image
def order
Spree::Order.find(spree_order_id)
end
end
migration
class CreateUploadGraphics < ActiveRecord::Migration[6.1]
def change
create_table :upload_graphics do |t|
t.references :spree_order, foreign_key: true
t.timestamps
end
end
end
This part works great i can do .order on an Upload::Graphic object and it returns the order.
Question: how do i do the inverse? Start with a Spree::Order and find the Upload::Graphic

Ada constraint error: Discriminant check failed. What does this mean?

I've tried searching the docs and the code, but I'm unable to find what this is and therefore how to correct it.
Scenario:
I'm using the Ada SPARK vectors library and I have the following code:
package MyPackage
with SPARK_Mode => On
is
package New_Vectors is new Formal_Vectors (Index_Type => test, Element_Type => My_Element.Object);
type Object is private;
private
type Object is
record
Data : New_Vectors.Vector (Block_Vectors.Last_Count);
Identifier : Identifier_Range;
end record;
I get the error when the code calls:
function Make (Identifier : Identifier_Range) return Object is
begin
return (
Data => New_Vectors.Empty_Vector,
Identifier => Identifier);
end Make;
Pointing to Empty_Vector. The difficulty is that Empty_Vector defines the Capacity as 0 which appears to be leading to the problem. Now I'm not sure then how to deal with that as Capacity seems to be in the type definition (having looked in a-cofove.ads).
So basically I'm stuck as to how to resolve this; or quite how to spot this happening in future.
Your analysis is correct. The error occurs because you attempt to assign an empty vector (i.e. a vector with capacity 0) to a vector with capacity Block_Vectors.Last_Count (which appears to be non-zero).
You actually do not need to initialize the vector explicitly in order to use it. A default initialization (using <>, see, for example, here) suffices as shown in de example below.
However, in order to prove the absence of runtime errors, you do need to explicitly clear the vector using Clear. The Empty_Vector function can then be used to in assertions that check if a vector is empty or not as shown in the example below. The example can be shown to be free of runtime errors using gnatprove. For example by opening the prove settings via menu SPARK > Prove in GNAT Studio, selecting "Report checks moved" in the "General" section (top left) and then running the analysis by selecting "Execute" (bottom right).
main.adb
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Containers.Formal_Vectors;
procedure Main with SPARK_Mode is
package My_Vectors is new Ada.Containers.Formal_Vectors
(Index_Type => Natural,
Element_Type => Integer);
use My_Vectors;
type Object is record
Data : Vector (Capacity => 10); -- Max. # of elements: 10
Value : Integer;
end record;
-- Initialize with default value (i.e. <>), no explicit initialization needed.
Obj : Object :=
(Data => <>,
Value => 42);
begin
-- Clear the vector, required for the assertions to be proven.
Clear (Obj.Data);
-- Assert that the vector is not empty.
pragma Assert (Obj.Data = Empty_Vector);
-- Populate the vector with some elements.
Append (Obj.Data, 4);
Append (Obj.Data, 5);
Append (Obj.Data, 6);
-- Assert that the vector is populated.
pragma Assert (Obj.Data /= Empty_Vector);
-- Show the contents of Obj.Data.
Put_Line ("Contents of Obj.Data:");
for I in Natural range 0 .. Natural (Length (Obj.Data)) - 1 loop
Put_Line ("[" & I'Image & "]" & Element (Obj.Data, I)'Image);
end loop;
New_Line;
-- or, alternatively using an iterator ...
declare
I : Extended_Index := Iter_First (Obj.Data);
begin
while Iter_Has_Element (Obj.Data, I) loop
Put_Line ("[" & I'Image & "]" & Element (Obj.Data, I)'Image);
I := Iter_Next (Obj.Data, I);
end loop;
end;
New_Line;
-- Show the contents of Obj.Value.
Put_Line ("Contents of Obj.Value:");
Put_Line (Obj.Value'Image);
New_Line;
end Main;
output
Contents of Obj.Data:
[ 0] 4
[ 1] 5
[ 2] 6
[ 0] 4
[ 1] 5
[ 2] 6
Contents of Obj.Value:
42

How to use a generic type?

I'm working through the example here: https://www.adahome.com/rm95/rm9x-12-08.html
I've written my generic_stack.ads:
generic
type Item_Type is private;
size : Positive;
package Generic_Stack is
procedure push( item : in Item_Type );
function pop return Item_Type;
function is_Empty return Boolean;
STACK_EMPTY : exception;
STACK_FULL : exception;
end Generic_Stack;
And my generic_stack.adb:
package body Generic_Stack
is
type Stack_Table is array (Positive range <>) of Item_Type;
nodes : Stack_Table( 1..size );
index : Natural := 0;
procedure push( item : in Item_Type )
is
begin
if ( index < size )
then
index := index + 1;
nodes(index) := item;
else
raise STACK_FULL;
end if;
end push;
function pop()
return
Item_Type
is
item : Item_Type;
begin
if ( index > 0 )
then
item := nodes( index );
index := index - 1;
else
raise STACK_EMPTY;
end if;
return item;
end pop;
-- function is_Empty() removed for the sake of brevity
end Generic_Stack;
I don't really understand how to actually use the Generic_Stack.
With the simple generic_stack_test.adb code:
with Generic_Stack;
package Stack_Int_Type is new Generic_Stack( Item_Type => Integer, Size => 32 );
procedure Generic_Stack_Test
is
stack : Stack_Int_Type;
begin
stack.push( 3 );
end Generic_Stack_Test;
Gnat gives me errors on compilation:
# gnat make -gnat95 generic_stack_test.adb -o generic_stack_test
x86_64-linux-gnu-gcc-8 -c -gnat95 generic_stack_test.adb
generic_stack_test.adb:9:08: keyword "body" expected here [see file name]
generic_stack_test.adb:20:24: missing "end Stack_Int_Type;"
x86_64-linux-gnu-gnatmake-8: "generic_stack_test.adb" compilation error
Do I have to declare the Stack_Int_Type or suchlike? I don't understand how to use a declare inside a procedure. If I pass a Stack_Int_Type to another procedure, does it have to declare the type too?
Is it possible to simply declare Stack_Int_Type once in an .ads, and use it as a regular type? My book and web-pages kind of suggest it has to be declared every time, which sounds onerous.
Your test code is actually two library items:
with Generic_Stack;
package Stack_Int_Type is new Generic_Stack( Item_Type => Integer, Size => 32 );
declares a library package Stack_Int_Type, and
procedure Generic_Stack_Test
is
stack : Stack_Int_Type;
begin
stack.push( 3 );
end Generic_Stack_Test;
declares a library procedure which, as it stands, knows nothing about Stack_Int_Type.
We can fix that by adding the necessary with, but (compiling with -gnatl)
1. with Stack_Int_Type;
2. procedure Generic_Stack_Test
3. is
4. stack : Stack_Int_Type;
|
>>> subtype mark required in this context
>>> found "Stack_Int_Type" declared at stack_int_type.ads:2
5. begin
6. stack.push( 3 );
1 2
>>> invalid prefix in selected component "stack"
>>> prefixed call is only allowed for objects of a tagged type
7. end Generic_Stack_Test;
What’s happening here is that Generic_Stack doesn’t declare a type, so you can’t declare an instance of it at line 4; it’s a sort of singleton. (Amongst other things, that means it’s confusingly named: I’d’ve called it Integer_Stack. Never call a package _Type; _Types, maybe.)
Fixing that,
with Generic_Stack;
package Integer_Stack is new Generic_Stack( Item_Type => Integer, Size => 32 );
and
with Integer_Stack;
procedure Generic_Stack_Test
is
begin
Integer_Stack.push( 3 );
end Generic_Stack_Test;
You could have made Integer_Stack local:
with Generic_Stack;
procedure Generic_Stack_Test
is
package Integer_Stack
is new Generic_Stack( Item_Type => Integer, Size => 32 );
begin
Integer_Stack.push( 3 );
end Generic_Stack_Test;
Your Generic_Stack package never defines a stack data type.
The procedure Push and Pop are operations on a stack. You must have a type upon which to operate. There are two general categories of stacks; bounded stacks and unbounded stacks. You must decide which kind of stack you wish to create.
A discussion of both kinds of stacks implemented in Ada can be found at https://sworthodoxy.blogspot.com/2019/02/stack-abstract-data-type-using-ada.html
In the examples referenced in the URL above you will see how to create stack types that can be used multiple times. The example from Adahome is an old and problematic example. You have identified the biggest problem.
As explained elsewhere, no type is defined by your package specification. Otherwise, you would have type ... is somewhere after the package keyword. It's that simple.
But as explained elsewhere too, it's not dramatic. Your package instantiation will define exactly one stack, and not a type to be used in multiple places. In some cases, it's exactly what you need. So, your could call your instantiated package My_Stack, which actually articulates around an object (My_Stack.nodes, accessible only through Push & Pop).
You need to do the instantiation of Generic_Stack from within a unit (procedure, package, ...). Outside of it, it is the "outer space" only with with and use clauses needed to connect with other units.
with Generic_Stack;
procedure Generic_Stack_Test
is
package My_Stack is new Generic_Stack( Item_Type => Integer, Size => 32 );
begin
My_Stack.push( 3 );
end Generic_Stack_Test;

Type variable as locale

In Isabelle is there a way to ensure that a type variable could be an interpretation of a locale?
I know that I can, for example, ensure that a type variable is of a particular class:
isValid :: 'a::ord =>: bool
However, I can't find how to extend this idea to a locale:
class address ....
<snip>
locale Message =
fixes
sender :: "'message => 'address::address" and
receiver :: "'message => 'address::address" and
isValid :: "'message => bool"
locale Filter =
fixes
fiterFunc :: "'filter => 'message::Message => filterResult"
The Filter locale gives errors such as Undefined class. Is there a way to write such an expression?
Locale interpretation is described in the tutorial on the locales and in the reference manual. One of my previous answers on SO contains relevant references: link.
From section 3.3.6 in the reference manual: "Sorts have a very simple inner syntax, which is either a single class name c or a list {c1, ..., cn} referring to the intersection of these classes". Therefore, it is not possible to use a locale as part of a sort of a type variable. The locale interpretation mechanism is different.

Ecto association to more than one schemes

Let's say I have these schemas:
defmodule Sample.Post do
use Ecto.Schema
schema "post" do
field :title
has_many :comments, Sample.Comment
end
end
defmodule Sample.User do
use Ecto.Schema
schema "user" do
field :name
has_many :comments, Sample.Comment
end
end
defmodule Sample.Comment do
use Ecto.Schema
schema "comment" do
field :text
belongs_to :post, Sample.Post
belongs_to :user, Sample.User
end
end
My questions is how can I use Ecto.build_assoc to save a comment?
iex> post = Repo.get(Post, 13)
%Post{id: 13, title: "Foo"}
iex> comment = Ecto.build_assoc(post, :comments)
%Comment{id: nil, post_id: 13, user_id: nil}
So far it's ok, all I need to do is use the same function to set the user_id in my Comment struct, however since the return value of build_assoc is Comment struct, I can not use the same function
iex> user = Repo.get(User, 1)
%User{id: 1, name: "Bar"}
iex> Ecto.build_assoc(user, :comment, comment)
** (UndefinedFunctionError) undefined function: Sample.Comment.delete/2
...
I have two options but neither of them looks good to me:
First one is to set user_id manually!
iex> comment = %{comment| user_id: user.id}
%Comment{id: nil, post_id: 13, user_id: 1}
Second one is to convert the struct to map and ... I don't even want to go there
Any suggestion?
Why don't you want convert struct to map? It is really easy.
build_assoc expects map of attributes as last value. Internally it tries to delete key :__meta__. Structs have compile time guarantees, that they will contain all defined fields, so you are getting:
** (UndefinedFunctionError) undefined function: Sample.Comment.delete/2
But you can just write:
comment = Ecto.build_assoc(user, :comment, Map.from_struct comment)
and everything will work fine.
Just pass it along with build_assoc
iex> comment = Ecto.build_assoc(post, :comments, user_id: 1)
%Comment{id: nil, post_id: 13, user_id: 1}
Check here for more details.

Resources