Changing 'time' column to 'datetime' - mysql

in Rails 3 app I have table subscription_schedules, in which there is a column of 'time' type
example record lokks like this:
#<Subscription::Schedule id: 3504, subscription_id: 4961, scheduled_at: "2000-01-01 01:11:00", primary: true, created_at: "2015-09-28 01:13:34", updated_at: "2015-09-28 01:13:34", active: true>
What I want to do is to convert scheduled_at to datetime. I decided to add new column 'temp_scheduled_at', save all 'scheduled_at' to it, change 'scheduled_at' to datetime with change_column() method , and later move whats in 'temp_scheduled_at' to 'scheduled_at'.
It looks like this:
add_column :subscription_schedules, :temp_scheduled_at, :datetime
Subscription::Schedule.select {|s| s.subscription}.each do |schedule|
schedule.temp_scheduled_at = schedule.scheduled_at
schedule.scheduled_at = nil
begin
schedule.save!
rescue => e
puts schedule.id
end
end
change_column :subscription_schedules, :scheduled_at, :datetime
Unfortunately thats where the troubles start. After calling Subscription::Scheudule.all later on, I get
Invalid date in field 'scheduled_at': 2001-00-00 00:00:00
I really have no idea what is causing this error, before changing column type record with 'invalid date' looked like this:
#<Subscription::Schedule id: 2555, subscription_id: 4102, scheduled_at: "2000-01-01 05:00:00", primary: true, created_at: "2015-06-23 16:12:01", updated_at: "2015-06-23 16:12:01", active: true>

I suggest you to use it in mysql query. You can change time to datetime in mysql query and refered as new column name. Its very easy compare to progrmming way. for ex-
select schedule_at, now() as temp_scheduled_at from tablename;
You can read more date time function here

Related

Unable to save/update field with desired string value

I have a model called SystemState. Following is the migration that created this table:
create_table :system_states do |t|
t.string :code
t.timestamps
end
But, even if code column is of string type, when I do the following:
> SystemState.first
> #<SystemState id: 1, code: 0, created_at: "2017-03-14 10:19:45", updated_at: "2017-03-14 10:28:33">
> SystemState.find(1).update_attributes(code: "system_alert_notification")
> SystemState.first
> #<SystemState id: 1, code: 0, created_at: "2017-03-14 10:19:45", updated_at: "2017-03-14 10:29:43">
As can be seen, it always updates it as 0(integer).
Is the column name reserved or something? Keen to know the cause of above.
Here are some possibilities :
1) May be code is a reserved word in mysql
2) Also, I'm sure, the column in your db is of integer type. Change it to string and it should work.

Phoenix Ecto ** (Mariaex.Error) (1054): Unknown column 'inserted_at' in 'field list'

When inserting a model into MySQL database using Elixir + Phoenix I get:
** (Mariaex.Error) (1054): Unknown column 'inserted_at' in 'field list'
stacktrace:
(ecto) lib/ecto/adapters/mysql.ex:181: Ecto.Adapters.MySQL.insert/5
(ecto) lib/ecto/repo/schema.ex:381: Ecto.Repo.Schema.apply/4
(ecto) lib/ecto/repo/schema.ex:185: anonymous fn/11 in Ecto.Repo.Schema.do_insert/4
(ecto) lib/ecto/repo/schema.ex:595: anonymous fn/3 in Ecto.Repo.Schema.wrap_in_transaction/6
(ecto) lib/ecto/adapters/sql.ex:472: anonymous fn/3 in Ecto.Adapters.SQL.do_transaction/3
(db_connection) lib/db_connection.ex:973: DBConnection.transaction_run/4
(db_connection) lib/db_connection.ex:897: DBConnection.run_begin/3
(db_connection) lib/db_connection.ex:671: DBConnection.transaction/3
This is not happening with other models, which work ok.
Model schema is:
schema "accounts" do
field :key, :string, null: false
field :cypher_key, :string, null: false
field :another_key, :string, null: false
field :another_cypher_key, :string, null: false
belongs_to :user, MyApp.User
timestamps()
end
and when inserting I'm doing:
Repo.insert! %Account{key: "test",
cypher_key: "test",
another_key: "test",
another_cypher_key: "pk_test"
}
When manually inserting via MySQL cmd it works ok.
Does your table contain timestamps fields? Did you generate proper migration for that?
Use mix ecto.gen.migration and then open file, which will be created in /priv/repo/migrations.
Alter the change function into something similar this:
def change do
create table(:accounts) do
add :key, :string
# etc.
timestamps
end
create unique_index(:accounts, [:key])
end
Then apply this migration with mix ecto.migrate.
I hope it will help.
It is quite likely that you didn't add timestamps in your migration file. For both the Ecto.Schema and the migration file, the timestamps function references two fields: updated_at and inserted_at. If you happen to come from Ruby on Rails, you may notice the naming difference from created_at. See the docs here for more detail.

Is .create method adding nil value if it fails to recognize an integer in Rails 4

In my controller, I need to pluck a single, matching integer value and then create a record with that value in another table. In action, it looks like this:
if Participation.where(ranking: "1")
first = PointsAllocation.where(game_id: params[:game_id]).where(place: "1").pluck(:points)
Stack.create(game_id: params[:game_id], user_id: current_user.id, chips: first)
else
end
I have tested in the console that the first variable is definable. If I run PointsAllocation.where(game_id: "1").where(place: "1").pluck(:points), it will return:
SELECT "points_allocations"."points" FROM "points_allocations" WHERE "points_allocations"."game_id" = 1 AND "points_allocations"."place" = 1
=> [10]
Ok, so it is correctly plucking what looks like an integer value for Points. I then want to use this points value and send it to the Chips column in the Stack table. When I run this, it will add a nil record even though first is defined, like so:
<Stack id: 1, game_id: 1, user_id: 1, chips: nil>
In troubleshooting, I thought maybe the issue here is that even though it looks like an integer (and Chips, I should add, is a t.integer attribute), maybe it's accidentally a string or something from pluck. So let's map this to an integer to be safe by adding map(&:to_i) after the pluck.
When I do that, it gets weirder, as it now returns:
<Stack id: 9, game_id: 1, user_id: 1, chips: 0>
So when I convert it to an integer, it changes 10 to a 0 and adds it to the table.
Where am I going wrong?
You may resolve it loading only one object instead ActiveRecord::Association:
first = PointsAllocation.where(game_id: params[:game_id]).where(place: "1").first
points = first.points
Stack.create(game_id: params[:game_id], user_id: current_user.id, chips: points)
Problem is that AR trying convert incorrect values if they type different with column type:
Stack.create(chips: 10)
#=> <Stack id: ..., chips: 10>
Stack.create(chips: [10])
#=> <Stack id: ..., chips: nil>
Stack.create(chips: "10")
#=> <Stack id: ..., chips: 10>
Stack.create(chips: "first")
#=> <Stack id: ..., chips: 0>

Seeding Phoenix Repo from json response

I'm trying to seed the database for my Phoenix application using the response from another api. I don't understand how to parse the response to create new object from it. I'm using HTTPoisin and Poison as of right now
seed.ex
alias NewsApplication.Article
HTTPoison.start
url = "rails_application.com/articles/index"
case HTTPoison.get(url) do
{:ok, %HTTPoison.Response{status_code: 200, body: body}} ->
articles = Poison.decode!(body["articles"])
Enum.fetch(articles, 1, fn(a) -> IO.puts a end)
{:ok, %HTTPoison.Response{status_code: 404}} ->
IO.puts "Not found :("
{:error, %HTTPoison.Error{reason: reason}} ->
IO.inspect reason
end
web/model/article.ex
updated
defmodule NewsApplication.Article do
use Ecto.Model
schema "articles" do
field :label, :string
field :slug, :string
field :full_path, :string
field :content_cache, :string
field :position, :integer, default: 0
field :children_count, :integer, default: 0
field :is_published, :boolean, default: false
field :is_shared, :boolean, default: false
field :featured, :boolean, default: false
field :score, :integer
timestamps
end
end
sample response
{"articles":
[{
"article":{
"id":436,
"updated":"2015-08-14T11:51:21.931Z",
"title":"Celebrating It's 50th Issue",
"numberOfViews":0,
"numberOfFavorites":2,
"imageURLs":["http://.../images/1549/original/axye.png"],
"tags":["Company News"],
"isFeatured":false,
"isPublished":true,
"published":"2015-07-28T17:00:00.000Z"
}
}]
}
It looks like you're almost there, but are missing a couple of things.
You'll want to iterate through each of the article responses using Enum.each and save these to the database like this:
Article.changeset(%Article{}, json)
|> Repo.insert
putting it all together, it'd be something like this:
Enum.each articles_json, fn(article) ->
Article.changeset(%Article{}, json)
|> Repo.insert
end
This won't handle any errors on Repo.insert if the changeset is invalid, but it'll work otherwise.
I'd recommend having a read through the Phoenix docs for models for further reference – specifically have a look at how they're structuring create actions.

Ruby on Rails mysql migrate use Timezone instead of Datetime

I am keeping in my mysql table a column called
starts_at
my column can be with a different timezone each time.
I have tried creating a migration:
def self.up
create_table :meetings, id: false, force: true do |t|
t.string :id
t.timestamp :starts_at
end
end
but i always end up with a
datetime
column type
i want to force rails to use timestamp, and tried all of these with with no success:
def up
change_column :meetings, :starts_at, :timestamp
end
this:
def up
change_column :meetings, :starts_at, 'timestamp'
end
and this:
def self.up
create_table :meetings, id: false, force: true do |t|
t.string :id
t.column :starts_at, 'timestamp'
end
end
any ideas?
update:
i want to save the timezone on the database record and not on the
application configuration
Rails actually makes some of decisions for you. Both :timestamp and :datetime will default to DATETIME, while :date and :time corresponds to DATE and TIME, respectively.
Using Rails, you only have to decide whether you need to store date, time or both.
So you can use type :datetime in your :starts_at column.
Look at this example in config/application.rb
class Application < Rails::Application
config.time_zone = 'Sydney'
config.time_zone = 'Kuala Lumpur'
config.active_record.default_timezone = 'Kuala Lumpur'
end
You can set your Time zone according to requirement and you can make it dynamic.
Here is all timezone ActiveSupport::TimeZone.all.map(&:name)