How to create a 'file' model in Rails? - ruby-on-rails

So I have built an API using Ruby/Sinatra and MondoDB. I'm now writing an Admin panel using Rails that connects to the same database. One of our collections is named 'files' since we need to model an object of such kind in our API. Now, when I wanted to create the File model in the Admin Panel, I came across the fact that I can't create a class called 'File'. Doing so results in the error attached
Even 'File1' is an acceptable class name. How do I now create the File model in my Rails app? I'm using Rails 5.0.0.1.

I believe that is happening because File is a reserve Rails word. I would probably rename the model to something like FileResource .
List of Reserved words: http://www.rubymagic.org/posts/ruby-and-rails-reserved-words

The file is ruby's class, you can't and should't use the name in model. Or you will replace the original File .
FileResource is a good name!

Related

Where to store text files in a Ruby on Rails directory?

I have a text file in my Ruby on Rails application that I would like to call in a model. The problem is, I want to follow rails conventions in terms of placing files.
The reason I'm using a .txt file is because I have a very large array of words I have to iterate over. This is for a model validation and I need to ensure that the input does not contain any of these words.
I could just declare an array, but it would make my models to fat. Therefore, I'd like to read from a file where I place my comma separated array elements.
There are several ideas I have
Root Directory: I could add the .txt file to my root directory directly
Public Directory: Could store it in /public
Temp Directory: Could store it in /tmp
Lib Directory: Could store it in /lib
Inside Model: Could just store it inside /app/models/mymodel.rb
Tried to find a similar answer here, but couldn't find a consensus. Anyways, this is a two part question. How would I read from the file inside the model. Would I do something like
file = File.read("#{Rails.root}/public/textfile.txt")
Thanks for your help
There are no conventions for storing files. All files can be stored in the public folder. This can vary if you're using Heroku or hostings that do not allow write access on the file system, and obviously you need to write.
Otherwise, you must take into account what is the purpose of this file. It might be a better idea to store files in a database or using rails store systems that are explained here: session store guides and here you can find more information about security
I hope you are not opening and reading this txt file each time you do a validation. I would suggest writing a rake task that would read the file once, parse the words and store them in a an indexed database column. You could create a model ForbiddenWord with an attribute called 'name' of type string(with index of course). Then you could write a custom validator and use it in MyModel, something like this:
class WordConstraintValidator < ActiveModel::Validator
def validate(record)
if ForbiddenWord.exists?(name: record.name)
record.errors[:base] << "You can not use the word #{record.name}"
end
end
end
class MyModel < ActiveRecord::Base
validates_with WordConstraintValidator
end
You can put your custom validator inside /app/models/, I am also assuming you have a name attribute on MyModel class, otherwise change this accordingly. There could be other possible solutions to this problem, this is the first thing that comes to mind.

Storing and retrieving static data in rails

In a Ruby on Rails 3.2.12 project I want to store data for a model in static files.
I don't need to be able to write to the data through the app, and want to handle updating and adding new objects by changing the static file(s).
Is there a way to set up a model, and then say "look at this file (or folder) to find the records", rather than the database (the app also has a database)?
I can imagine the data being stored in two main ways:
all the records are kept in a .json or .yml file
each record is kept in an individual .yml or .markdown file, inside a specific folder (as in jekyll).
Examples: a glossary
My application has a glossary. Each entry in the glossary should be an individual record.
There will be a glossary index page (/glossary) that is just like your standard glossary, listing all the terms and definitions. Each individual record(term + definition) also needs to be individually retrievable for use in footnotes on other pages.
I want people to be able to edit the glossary by editing files through github. They could be pointed to a single file with all the records, or (preferably) an individual file with just the record they want to edit (less syntax to handle, less risk).
Key questions
How do you point the model to the static data file, rather than the database?
Where should the source directory be?
What would be the best storage format?
Thanks very much for your help!
ActiveHash would be a good solution for this. You could use the ActiveYaml configuration if you would like to store the data in a separate yaml file instead of directly in the model.
Unless someone comes up with a better solution or with a gem which can do this out of the box I would recommend building your own model with own find and save methods. Something like (untested):
class Term
attr_accessor :name, :definition
def self.find(name)
YAML.load(File.read("#{name}.yaml"))
end
def save
File.open("#{name}.yaml", 'w'){ |f| f.write(YAML.dump(self)) }
end
end
The format for saving is up to you, see here or here for more info. Since you want the users to change the files I would go with whichever you find the most user friendly.

Steps to simply Change the Name of my Model

So I think I jacked up my naming conventions (or rather realized I want to do it a different way). I initially created a "Persons" model (which created person.rb). I also created a persons_controller, but apparently rails looks for "People" so I changed the controller name to people_controller.rb (in the files...not in the command line).
I'm new to rails so I really just need to scrap all this and change my names because this setup (having to using Person, Persons, People) throughout the model/controller/views is just a bit confusing for a beginner. All I want to do is change the "Persons" or "People" to the word "Players". So if I were starting from scratch I'd do "rails generate model Player" in the command line, and "rails generate controller Players". But I have no idea how to go about changing my existing controller and model names to this...and I couldn't fully understand some of the older questions related to this topic.
Any help would be greatly appreciated here. Step by Step instruction like your talking to a 12 year old is also highly encouraged given my novice status.
thanks guys,
The basic conventions that will explain everything
About class name and file name
Class name must correspond to file path. In English, if you have a Thing model, it must be in models/thing.rb file ; if you have a ThingsController it must be in controllers/things_controller.rb
Class name with camel case (i.e SomeThing) must be declared in a file with underscore (i.e some_thing.rb). The file name is written in small letters and underscore is used to "separate" the words. Other example: ThisIsEasyToUnderstand will give this_is_easy_to_understand
About model name, table name and controller name
A model name is singular, a table name is plural and a controller is plural. For example a Thing model will have a things table, and will work with a ThingsController controller
Rails try at most to use correct English syntax, so a Person model will work with a people table and a PeopleController controller
You may have trouble when the model name is, in English, the same in its singular and plural form. Ex: aircraft, eyeglasses, scissors etc.. I won't details the solution to keep my answer clear, but know it can append and you can find solutions on those a bit everywhere on internet.
As an overview:
When you create a model, create a name in its singular form
When you create a controller create a name in its plural form
if you need to rename models or controller you already created you must rename in your code but also rename the file name
If you need to rename a model you will also need to rename its table, and you need a migration for that (search google for "rails migration rename table" )
Hope it help for your first steps in Rails
You can quickly scrap a model (and its associated files) by calling
rails destroy model [modelname]
Same with controllers, scaffolds, etc.
rails destroy scaffold [modelname]
rails destroy controller [controllername]
Of course, there's no undoing this after you've deleted them, so I'd create the new controllers/models/scaffolds first, migrate any relevant code, and then destroy the useless files.

What command can I use to create this Ruby on Rails model?

I'm creating a model in Ruby on Rails that will act like a file system. You'll have assets (like files) that could either be folders or files themselves. How can I create a command for this?
Asset
id (unique auto-incrementing number)
name
is_directory (bool)
user_id (id of the owner)
parent_asset_id (id of parent directory, or null if under the root)
access_token (randomly generated token, used to send shareable links)
contents
I'm thinking something like:
rails generate model Asset
name:string
is_directory:boolean
user_id:integer
parent_asset_id:integer
access_token:string contents:??
Some questions I have:
What's the difference betweeen blob vs longblob vs mediumblob vs longtext vs etc, and which would I want to use? (The assets are essentially text... not sure what the max size will be yet)
Is the parent_asset_id a good naming convention, or is there something else that would make Rails give me some secret sauce, similar to why I picked the name user_id (to match the User model)?
Is there a way to declare a default random string value for the access_token? (The access token will be used for a shareable link to the asset)
Anything else I'm overlooking?
This is a detailed question, so I hope it serves as a case study for anyone looking to implement something like a file system in RoR.
Obviously if you really wanted to implement a file system you'd use an actual file system or Amazon S3... but if you want a light-weight file-like system in RoR, this seems like the best approach.
First off, I strongly recommend you consider an existing gem like Paperclip, which will handle a lot of these details for you.
Answers in order:
You would use the binary field type to store general data, but if you use Paperclip there are some specific fields you would need to use instead, which are explained in Paperclip's docs.
If by parent_asset_id you really mean the asset can 'belong' to many other models, then look into setting up a polymorphic relationship, with an id and type field. If instead you mean storing the path to the stored file, then Paperclip handles this for you. See #3 for details...
You can access a stored file on Paperclip by calling something as simple as asset.url in your view. If you wish to go manual and insert a random code, you can insert a callback into your Asset.rb model that does something like:
before_create :generate_key
def generate_key
self.key = ActiveSupport::SecureRandom.hex
end
S3 is not a complex system to set up on Rails, and it is far more flexible and scaleable than storing the files elsewhere - however, if you want to, then use the 'assets' path.

custom properties in Rails

I have just started Rails and have a basic question.
I need to add customer properties(like email id etc) so that the Rails app can read them at runtime. How can I do this ?
Can I add them to development.rb and if so how can I read it ?
In java I would have created a properties file and read it from my app.
thank you,
firemonkey
Are you trying to do store and load configuration settings?
It's easy to store configuration settings in a yaml file and load them with initializers - loads better than littering your environment files.
This Railscast: http://railscasts.com/episodes/85-yaml-configuration-file shows you how.
I'm not sure exactly what you are asking. I'm guessing you want an initial set of data in the database that you can access when you actually run the app? If that is so check out this other SO question How (and whether) to populate rails application with initial data
It's a little unclear exactly what you're trying to do, but it sounds like maybe you have a model called Customer and you would like to add some attributes to it, such as email address, id, and so on?
Basically, with Active Record you don't need to do anything special to add a simple attribute (like a string or an integer). Just add a field called "email_address" to your customers table in the database, and all of your Customer objects will automagically get "email_address" and "email_address=" methods (not to mention the Customer class itself getting "find_by_email_address" and other useful methods as well). If you are adding a field containing another model, it's a bit more complicated - add a "something_id" field to the table, and an association to the class definition (eg, "has_one :something"). For more information, see the ActiveRecord api documentation.
You don't have to use any particular means to add the field to your database, but you might want to consider Migrations. Migrations are a convenient way to keep your schema versioned and synchronized across multiple machines.
If you are building your model right now, there's a short cut built in to the generator to add fields. Instead of just saying...
script/generate scaffold customer
...you can say...
script/generate scaffold customer email:string name:string badge_number:integer
...and it will generate all the appropriate fields in your migration, as well as adding them to your generated views.

Resources