Viewing the contents of tables in schema.rb in rails - ruby-on-rails

I'm sorry if this is a stupid question, but in my schema.rb I have several tables like
create_table "messages", :force => true do |t|
t.integer "user_id", :null => false
t.string "message", :null => false
t.datetime "created_at", :null => false
t.string "photo_file_name"
t.string "photo_content_type"
t.integer "photo_file_size"
t.datetime "photo_updated_at"
end
Is it possible to view the contents of each table i.e view each message and associated user id, message content, time created at, linked image, etc?
Thanks

A database schema represents the structure of the database, not the content of it.
If you want to access the content in your database, you would query it to do so. You can do that via command line clients (running $ rails dbconsole will try to open one for the configured database) or graphical tools like Sequel Pro (for MySQL on Mac OS X).
You can also get this through your Rails application by running $ rails console and then using the methods available through ActiveRecord (e.g. Post.all or User.where(:name => 'Billy').limit(5)).

You can use gem "annotate". It is very helpful for me.

For viewing the table structure on the rails console only need to run the table name eg If there is a table with name country. only run the 'Country '
2.4.4 :004 > Country
=> Country(id: integer, name: string, percentage: string, created_at: datetime, updated_at: datetime, is_sync: boolean)
2.4.4 :005 >

Related

Active Storage public_url not returning key/filename.extension

The public option is added to Active Storage in this PR: https://github.com/rails/rails/pull/36729
In it he clearly says: "In the public bucket, the directory structure is /[key]/[filename]"
Which makes sense and is exactly what I want. I want to be able (for example) to email the link to someone and allow them to download the file. So I need the filename.extension. But when I spin up a Rails 6.1 app the uploads to my bucket do not have the filename after them.
The files do appear in my bucket, but only as their key. Not key/filename.
amazon:
service: S3
access_key_id: <%= Rails.application.credentials.dig(:aws, :access_key_id) %>
secret_access_key: <%= Rails.application.credentials.dig(:aws, :secret_access_key) %>
region: us-east-1
bucket: mybucket
public: true
The uploading works fine. The files are uploaded and appear in my bucket. But in the view <%= #user.avatar.url %> returns https://s3.amazonaws.com/mybucket/g3ci2umbfj6wkxyggx7arhekxfib I want it to return https://s3.amazonaws.com/mybucket/g3ci2umbfj6wkxyggx7arhekxfib/myfile.png
This is really annoying me because in the PR the author clearly states that the public files are saved as key/filename.extension
So the question: In Rails 6.1 does the url method return the filename as part of the path or not. And if not why does the author say that it does? And if not is there a better way than patching key?
TLDR:
= link_to #user.avatar.filename, rails_blob_path(#user.avatar, disposition: "course.avatar"), target: :_blank
will give you a download link like https://corsego-production.s3.eu-central-1.amazonaws.com/3gbpl68kckpkyrbjoslsl254th0u?response-content-disposition=inline&X-Amz-Security-Token=IQoJb3JpZ2luX2VjEGgaCmV1LBuuKkri8zL3ohM4h9STzhTsnavAgulrcpBavL0POXg%3D%3D&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Date=20201002T170820Z&X-Amz-SignedHeaders=host&X-Amz-Expires=300&X-Amz-Credential=ASIA5RINJ20201002%2Feu-central-1%2Fs3%2Faws4_request&X-Amz-Signature=0a205d713ebaa9d3ca9d62
#user.avatar.url is not supposed to return anything!
#user.avatar is supposed to return something like #<ActiveStorage::Attached::One:0x00007f15986ee4c0>
When creating an attachment with Active Storage, the following fields about the attachment are automatically populated and saved as active_storage_blobs:
create_table "active_storage_blobs", force: :cascade do |t|
t.string "key", null: false
t.string "filename", null: false
t.string "content_type"
t.text "metadata"
t.bigint "byte_size", null: false
t.string "checksum", null: false
t.datetime "created_at", null: false
t.index ["key"], name: "index_active_storage_blobs_on_key", unique: true
end
Let's say you upload an image with active storage. The above Table will be populated in a following way:
Id: 1
Key: sy2y1ytw7zob6mwtnwc1552cdp5l
Filename: Screenshot 2020-10-02 125405.png
Content_type: image/png
Metadata: {"identified"=>true, "analyzed"=>true}
Byte_size: 1550
Checksum: mGPerbRMj6LXbPKhqKd4bA
To display the user avatar as an image, you must call = image_tag #user.avatar
= rails_blob_url(#user.avatar) will give you something like https://example.com/rails/active_storage/blobs/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBCZz09IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--5fb10a9c8e9f2c4e7099eee21c1dc2ff0343c210/Screenshot%202020-10-02%20125405.png
= #user.avatar will give you something like #<ActiveStorage::Attached::One:0x00007f1589293dd0>
= url_for(#user.avatar) will give you something like /rails/active_storage/blobs/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBCZz09IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--5fb10a9c8e9f2c4e7099eee21c1dc2ff0343c210/Screenshot%202020-10-02%20125405.png
The second table in the migrations created by active_storage is this:
create_table "active_storage_attachments", force: :cascade do |t|
t.string "name", null: false
t.string "record_type", null: false
t.bigint "record_id", null: false
t.bigint "blob_id", null: false
t.datetime "created_at", null: false
t.index ["blob_id"], name: "index_active_storage_attachments_on_blob_id"
t.index ["record_type", "record_id", "name", "blob_id"], name: "index_active_storage_attachments_uniqueness", unique: true
end
basically it connects the blob with a specific record in your application (basically the avatar is a blob, the #user is the record, and they are associated via the active_storage_attachments table.
So you can also run the following commands on the #user.avatar method:
#user.avatar.name #Avatar
#user.avatar.record_type #User
#user.avatar.record_id #2 (user id)
#user.avatar.blob_id #1 (blob id)
Now, below is an example url to the above file stored on AWS S3:
https://corsego-production.s3.eu-central-1.amazonaws.com/3gbpl68kckpkyrbjoslsl254th0u?response-content-disposition=inline&X-Amz-Security-Token=IQoJb3JpZ2luX2VjEGgaCmRzBFAiBSJ2QIEqs1opj%2BuCR74CDMt67ueDTTQIhAOJGGy2wfmxmGUwpQe9cyc84ZhUhuWKHdVgTUctbtGrVKdinkpg0w7OikcyNYpnbq%2FefcTmEgRvIlPO%2B0itFxUr8mKUvnDYSuKkri8zL3ohM4h9STzhTsnavAgulrcpBavL0POXg%3D%3D&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Date=20201002T170820Z&X-Amz-SignedHeaders=host&X-Amz-Expires=300&X-Amz-Credential=ASIA5RINJLY2F20201002%2Feu-central-2%2Fs3%2Faws4_request&X-Amz-Signature=0a205d713ebaaa339ad4ee09db9dfe16986e69d3ca9d62
See how the url contains a secret token and an expiry time? It is advised not to have permanent urls to files.
P.S. When connecting AWS S3 to your application, don't forget to add CORS configuration:

Ruby on Rails Testing - ActiveRecord::StatementInvalid: PG::InvalidTextRepresentation: ERROR: malformed array literal:

I have a project that is running ok on production and development and mostly on many tests, but with one model there's no way to run the tests.
Model:
create_table "cities", force: :cascade do |t|
t.string "city"
t.string "cp", array: true
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "name"
t.string "primary_cp"
end
(Note that "cp" attribute is an Array and I'm using Postgres on the project)
(I'm NOT setting "serialize: cp, Array" on the model)
But when I run rails test/models/city_test.rb what I get is
Error:
CityTest#test_the_truth:
ActiveRecord::StatementInvalid: PG::InvalidTextRepresentation: ERROR:
malformed array literal: "MyString"
LINE 28: ...d_at") VALUES (980190962, 'MyString', 'MyString',
'MyString'...
^
DETAIL: Array value must start with "{" or dimension information.
: DELETE FROM "homes";
DELETE FROM "categories";
DELETE FROM "volunteers";
DELETE FROM "donations";
I've already searched for other solutions here but it doesn't fix the problem. What I'm guessing is that it is something related to the YAML serialization that the test environment does, but I'm not quite sure.
I have no problem with development and production environments at all, it only happens on test env.
For those who came up with same situation. the problem was with the declaration of the test fixtures. An array in YAML must be declared this way:
one:
city: Premià de Mar
cp:
- 08400
- 08401
two:
city: Mataró
cp:
- 08300
- 08301
Where "cp" is the array. Setting up the array properly fixes the issue.

Weird Rails migration / schema.rb issue

A while back I ran the following migration:
class CreatePipelineSpecs < ActiveRecord::Migration
def change
create_table :pipeline_specs do |t|
t.integer :id_no
t.string :od
t.string :wt
t.string :material
t.string :spec_type
t.string :spec_grade
t.string :mop
t.string :stress_level
t.string :joints
t.text :notes
t.string :ip
t.references :pipeline, index: true, foreign_key: false
t.timestamps null: false
end
add_index :pipeline_specs, :id_no
end
end
I am not sure what has happened now but every time I run rake db:migrate the scheme.rb file gets updated with:
create_table "pipeline_specs", force: :cascade do |t|
t.integer "id_no"
t.string "od"
t.string "wt"
t.string "material"
t.string "spec_type"
t.string "spec_grade"
t.string "mop"
t.string "stress_level"
t.string "joints"
t.text "notes"
t.string "ip"
t.integer "pipelines_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "pipeline_specs", ["id_no"], name: "index_pipeline_specs_on_id_no", using: :btree
add_index "pipeline_specs", ["pipelines_id"], name: "index_pipeline_specs_on_pipelines_id", using: :btree
Note the plural pipelines_id. The actual database tables (dev, production etc.) are all pipeline_id which is correct as the reference table is Pipeline. So I add a new unrelated migration and the schema.rb gets updated and these get changed back to plural again after I change them back. If I forget to change them when I run tests everything breaks as the wrong schema gets loaded into the test environment.
I am at a loss here. I am I missing something obvious here or is there some hidden migration schema table etc.
The only think I can this of is when I made the original migration I used pipelines:references vs pipeline:references, then fixed my mistake, and then cleaned up the migrations before committing this and deploying it.
Any ideas here one why this is happening and how to fix it once and for all?
UPDATE
Here are my three related models:
irb(main):031:0> Pipeline
=> Pipeline(id: integer, licence: string, company: string, company_id: integer, ba_code: string, substance_code: string, substance: string, h2s: string, partial_pressure: string, notes: text, created_at: datetime, updated_at: datetime, slug: string)
irb(main):032:0> PipelineSpec
=> PipelineSpec(id: integer, id_no: integer, od: string, wt: string, material: string, spec_type: string, spec_grade: string, mop: string, stress_level: string, joints: string, notes: text, ip: string, pipeline_id: integer, created_at: datetime, updated_at: datetime, slug: string)
irb(main):033:0> PipelineSegment
=> PipelineSegment(id: integer, line: integer, lsd_from: integer, sec_from: integer, twp_from: integer, rge_from: integer, m_from: integer, fc_from: string, lsd_to: integer, sec_to: integer, twp_to: integer, rge_to: integer, m_to: integer, fc_to: string, length: string, aasm_state: string, state_comment: string, state_user_id: integer, aasm_date: datetime, env: string, volume: string, notes: text, pipeline_id: integer, pipeline_spec_id: integer, created_at: datetime, updated_at: datetime, slug: string)
Pipeline has_many PipelineSpec and PipelineSegment. PipelineSegment has_one PipelineSpec.
UPDATE 2
Checked my test environment schema - it's fine. Ran rake db:migrate and again the schema.rb gets updated. Run the tests again and get gobs of:
ActiveRecord::StatementInvalid: ActiveRecord::StatementInvalid: PG::UndefinedColumn: ERROR: column "pipeline_id" of relation "pipeline_specs" does not exist
LINE 1: ..., "mop", "stress_level", "joints", "notes", "ip", "pipeline_...
^
: INSERT INTO "pipeline_specs" ("id", "id_no", "od", "wt", "material", "spec_type", "spec_grade", "mop", "stress_level", "joints", "notes", "ip", "pipeline_id", "created_at", "updated_at") VALUES (1, 1, '88.9', '3.18', 'S', 'Z245.1', '359 2', '9930', '25', 'W', 'MyText', 'U', 1, '2017-04-24 03:47:26', '2017-04-24 03:47:26')
as the fixtures try to load into the incorrect test schema that was just loaded at test time.
The schema is recreated from the actual state of your database after each migrations run. So I guess the pipelines_id must indeed exist somewhere in your db or at least Rails must think it exists in the db. I would do the following to narrow the issue down:
Run rake db:schema:dump SCHEMA=myschema.rb - this will generate a differently-named schema file manually. This is the same rake task that is also run after the migrations. I expect that the new schema will contain the plural pipelines_id column, too.
Then I'd take a look in the log/development.log (or whatever environment you are experiencing the issue in). You should see SELECT schema_migrations.* FROM schema_migrations and a bunch of further queries for showing structure of each table in your database there. Find the query that deals with the pipeline_specs table and run it manually in the db console to see what you precisely get. My expectation is that you'll either:
see the plural pipelines_ids there too - that would prove the column indeed exists in the db
or not - in which case I would restart everything I could in rails just to be sure there is no caching involved anywhere - specifically I'd restart spring with spring stop. Also I'd check (don't know Postgres that well to tell for sure) whether there might be any caching involved on the Postgres side. Then I'd try again.
I think that because the migration you deleted did't run on test environment, try reset the test database by:
RAILS_ENV=test rake db:migrate:reset
Try to specify a foregein_key in model PipelineSpec to pipelines_id
class PipelineSpec < ActiveRecord::Base
belongs_to :pipeline, foreign_key: :pipelines_id
end

"PG::Error - numeric field overflow" on Heroku

I have built an app that queries Google Analytics for the last 7 days of data. Everything works locally. On Heroku, the process runs smoothly until it tries to get data for today's date. I then get the following error:
2012-10-29T02:32:02+00:00 app[web.1]: ActiveRecord::StatementInvalid (PG::Error: ERROR: numeric field overflow
2012-10-29T02:32:02+00:00 app[web.1]: DETAIL: A field with precision 8, scale 2 must round to an absolute value less than 10^6.
I have tried to figure out which variable it's not happy with but I don't know right now. I am assuming it's something related to date or time.
Any thoughts or ideas would be great :)
-- update ---
ActiveRecord::Schema.define(:version => 20121014153338) do
create_table "analytics", :force => true do |t|
t.string "site"
t.integer "visits"
t.date "start_date"
t.date "end_date"
t.decimal "revenue_per_transaction", :precision => 8, :scale => 2
t.integer "transactions"
t.decimal "item_quantity", :precision => 8, :scale => 2
t.integer "goal_starts"
t.integer "goal_completes"
t.decimal "goal_conversion", :precision => 8, :scale => 2
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.decimal "goal_abandon", :precision => 8, :scale => 2
t.decimal "revenue", :precision => 8, :scale => 2
t.string "source"
end
end
You have a numeric field with typmod numeric(8,2) and you're trying to store a value greater than 999999.99 in it. See the PostgreSQL manual on NUMERIC for information on numeric scale and precision, which are the qualifiers shown after the type in parentheses.
This earlier question appears to cover the same issue with Rails, showing the Rails model and how the scale and precision are assigned.
NUMERIC isn't a date/time field, it's a number field.
Demo of the issue:
regress=> SELECT NUMERIC(8,2) '999999.99';
numeric
-----------
999999.99
(1 row)
regress=> SELECT NUMERIC(8,2) '1000000.00';
ERROR: numeric field overflow
DETAIL: A field with precision 8, scale 2 must round to an absolute value less than 10^6.
It's a pity that Pg doesn't tell you what field this is when it is a field. It's difficult for it to do so, though, because it doesn't usually know which value is going to go into which field when it's parsing string literals. Enable log_statement = 'all' in postgresql.conf, ALTER USER ... SET, ALTER DATABASE ... SET, or per-session with SET log_statement = 'all' then re-test and examine the query logs.
Also look at the table definitions with \dt in psql to see what might have the type numeric(8,2) and could be causing the problem.
As for why it works locally: Is the local DB PostgreSQL? Some Rails users seem to have a very odd setup where they use SQLite locally, and PostgreSQL on Heroku. This is a recipe for chaos and deployment problems. Use the same database in development and testing. If it is PostgreSQL locally, is it the same version?

Unset operation failing for MongoMapper model, cannot delete / remove key from model

We're on mongodb 2.0.0, mongo gem 1.4.1, mongo_mapper 0.9.2, rails 3.0.6.
We love MongoMapper, but we need helping resolving one nasty issue: we have a key carried over from some testing, but invoking obj.unset fails to do anything.
Specifically, we are trying to remove an "id" key (not "_id") because it's causing MM to treat obj.id as different from obj._id, which we don't want.
After clearing out the database, we ran these commands from a controller which does nothing else: (We also tried running the same code from the rails console, but it also fails.)
logger.info "#{Game.keys.keys.inspect}"
Game.unset({}, :id)
logger.info "#{Game.keys.keys.inspect}"
Game.unset(:id)
logger.info "#{Game.keys.keys.inspect}"
Output:
["jackpot", "players", "created_at", "puzzles", "ended_at", "player_index", "updated_at", "log", "_id", "id", "join_code", "puzzle_index"]
["jackpot", "players", "created_at", "puzzles", "ended_at", "player_index", "updated_at", "log", "_id", "id", "join_code", "puzzle_index"]
["jackpot", "players", "created_at", "puzzles", "ended_at", "player_index", "updated_at", "log", "_id", "id", "join_code", "puzzle_index"]
Current keys defined in our Game model:
key :players, Array, :default => []
key :player_index, Integer, :default => 0
key :puzzles, Array, :default => []
key :puzzle_index, Integer, :default => 0
key :join_code, String, :default => nil
key :jackpot, Integer, :default => 0
key :log, Array, :default => []
key :created_at, Time
key :updated_at, Time
key :ended_at, Time, :default => nil
Help?
Thanks!
It pains us to post the answer since this solidifies our status as "morons, idiots, fools, noobs, Jay Leno fans," but in case anyone else bumps into the same issue: while our model directory was clean in the dev environment, the model dir in the production environment contained old test files ... which contained an old model with the "id" key.
Obviously, removing the old files and the old models solved everything, though we're left with staggering bruises to our egos and to our heads (from excessive banging against the walls).

Resources