Is it possible to define templates in yaml for Alice Fixtures, but creating the object themselves via PHP - nelmio-alice

I'm new to Alice, and I'm trying to find my way with it. If you think the paradigm I chose is wrong, I would love to hear a better approach.
Let's assume I have the following template
# temlpate.yaml
stdClass:
user (template):
userId: '<randomNumber()>'
username: <email()>
firstName: <firstName()>
I know I can create the template user by creating the following yaml (that is working)
# user_fixtrue.yaml
stdClass:
user1 (extends user):
But sometimes I would like to create a user and override one or any mix of the user properties. Which means I would need to create a file per scenario, and injecting params, something like
# user_fixtrue_params.yaml
stdClass:
user2 (extends user):
userId: <{userIdFromPhp}>
And using it via PHP with
$loader->loadFile("user_fixtrue_params.yaml", ["userIdFromPhp" => 1234]);
If I would like to override the username as well I'll need another yaml to define it.
And if on top of it if I would like different ranges (different amount of objects, feature request can be seen here) I would need to specify a yaml file for each combination of range and properties.
I would rather load the templates for yaml, and create the users using PHP, but I didn't find any way to do so. Any idea, or do I miss something?
As an alternative I thought having all the templates definitions on PHP, but I couldn't manage to create an object in one file, where the template defined on another file using PHP. If that can be done I would love to see an example.
Thank you

Related

Best practices regarding per-user settings and predefining options

I want to save settings for my users and some of them would be one out of a predefined list! Using https://github.com/ledermann/rails-settings ATM.
The setting for f.e. weight_unit would be out of [:kg, :lb].
I don't really want to hardcode that stuff into controller or view code.
It's kind of a common functionality, so I was wondering: Did anyone come up with some way of abstracting that business into class constants or the database in a DRY fashion?
Usually, when I have to store some not important information which I don't care to query individually, I store them on a serialized column.
In your case you could create a new column in your users table (for example call it "settings").
After that you add to user model
serialize :settings, Hash
from this moment you can put whatever you like into settings, for example
user.settings = {:weight_unit => :kg, :other_setting1 => 'foo', :other_setting2 => 'bar'}
and saving with user.save you will get, in settings column, the serialized data.
Rails does also de-serialize it so after fetching a user's record, calling user.settings, you will get all saved settings for the user.
To get more information on serialize() refer to docs: http://api.rubyonrails.org/classes/ActiveRecord/AttributeMethods/Serialization/ClassMethods.html#method-i-serialize
UPDATE1
To ensure that settings are in the predefined list you can use validations on your user model.
UPDATE2
Usually, if there are some pre-defined values it's a good habit to store them in a constant inside the related model, in this way you have access to them from model (inside and outside). Acceptable values does not change by instance so it makes sense to share them between all. An example which is more valuable than any word. Defining in your User model:
ALLOWED_SETTINGS = {:weight_unit => [:kg, :lb],
:eyes_color => [:green, :blue, :brows, :black],
:hair_length => [:short, :long]}
you can use it BOTH
outside the model itself, doing
User::ALLOWED_SETTINGS
inside your model (in validations, instance methods or wherever you want) using:
ALLOWED_SETTINGS
Based on your question, it sounds like these are more configuration options that a particular user will choose from that may be quite static, rather than dynamic in nature in that the options can change over time. For example, I doubt you'll be adding various other weight_units other than :kg and :lb, but it's possible I'm misreading your question.
If I am reading this correctly, I would recommend (and have used) a yml file in the config/ directory for values such as this. The yml file is accessible app wide and all your "settings" could live in one file. These could then be loaded into your models as constants, and serialized as #SDp suggests. However, I tend to err on the side of caution, especially when thinking that perhaps these "common values" may want to be queried some day, so I would prefer to have each of these as a column on a table rather than a single serialized value. The overhead isn't that much more, and you would gain a lot of additional built-in benefits from Rails having them be individual columns.
That said, I have personally used hstore with Postgres with great success, doing just what you are describing. However, the reason I chose to use an hstore over individual columns was because I was storing multiple different demographics, in which all of the demographics could change over time (e.g. some keys could be added, and more importantly, some keys could be removed.) It sounds like in your case it's highly unlikely you'll be removing keys as these are basic traits, but again, I could be wrong.
TL;DR - I feel that unless you have a compelling reason (such as regularly adding and/or removing keys/settings), these should be individual columns on a database table. If you strongly feel these should be stored in the database serialized, and you're using Postgres, check out hstore.
If you are using PostgreSQL, I think you can watch to HStore with Rails 4 + this gem https://github.com/devmynd/hstore_accessor

How do you structure i18n yaml files in Rails?

I started populating an en yaml file in Rails and I can already tell it will get messy and out of hand before too long. Is there a convention to keeping this file organized?
So far I have this structure:
language:
resource:
pages: # index, show, new, edit
page html elements: # h1, title
activerecord:
attributes:
model:
property:
Now I have the following things that I want to fit into this structure but I'm unsure how to:
Navigation
Button text (save changes, create account, etc)
Error messages from controller flash
How to add multi-word keys. Do I use a space or an underscore? For exmaple, t(".update button")) or t(".update_button")
Is there a convention to locale file structure?
I've found that the best overall strategy is to somewhat reproduce the file structure so that given any translation, I can immediately find where it was called from. This gives me some kind of context for making the translation.
The majority of application translations are found in views, so my biggest top level namespace is usually views.
I create sub namespaces for the controller name and the action name or partial being used ex :
views.users.index.title
views.articles._sidebar.header
Both of these examples should make it obvious what part of my app we're translating and which file to look in to find it.
You mention navigation and buttons, if they are to be generic, then they belong in the views.application namespace just as do their view counterparts :
views.application._main_nav.links.about_us - a link in our app's main navigation partial
views.application.buttons.save
views.application.buttons.create - I have a bunch of these buttons ready to be used when needed
Flash messages are generated from the controller, so their top level namespace is... controllers! :)
We apply the same logic as we do to views :
controllers.users.create.flash.success|alert|notice
Again if you wanted to provide generic flash messages like "Operation successful", you would write something like this :
controllers.application.create.flash.notice
Finally, keys can be anything that is valid YAML, but please stick to using periods . as separators and underscores _ between words as a matter of convention.
The only thing left to sort out now, is getting rails' translations into its own namespace to clean up our top level :)
I know that an answer has already been accepted, but this question provided me with some food for thought and I thought I'd share another structure for Rails i18n yml files for your consideration/criticism.
Given that I would like to
keep the default app structure so I can use shorthand "lazy" lookups like t('.some_translation') in my views,
avoid as much string repetition as possible, in particular with words that are not just the same, but also have identical contexts/meanings,
only have to change a key once to have it reflected everywhere it's referenced,
for a config/locales/en.yml file that looks something like this:
activerecord:
attributes:
user:
email: Email
name: Name
password: Password
password_confirmation: Confirmation
models:
user: User
users:
fields:
email: Email
name: Name
password: Password
confirmation: Confirmation
sessions:
new:
email: Email
password: Password
I can see that there is significant repetition, and that the context of words like "Email" and "Password" are unambiguous and have the same meaning in their respective views. It would be a bit annoying to have to go and change them all if I decide to change "Email" to "e-mail", so I'd like to refactor the strings to reference a dictionary of some sort. So, how about adding a dictionary hash to the top of the file with some & anchors like this:
dictionary:
email: &email Email
name: &name Name
password: &password Password
confirmation: &confirmation Confirmation
activerecord:
attributes:
user:
email: *email
name: *name
password: *password
password_confirmation: *confirmation
models:
user: User
users:
fields:
email: *email
name: *name
password: *password
confirmation: *confirmation
sessions:
new:
email: *email
password: *password
Whenever you get more than one instance of exactly the same word/phrase in your views, you could refactor it out to the dictionary. If the dictionary translation of a key in the base language doesn't make sense for a target language, then just change out the referenced value in the target language to a static string or add it as an extra entry to the target language's dictionary. I'm sure each language's dictionary could be refactored out into another file if they get too big and unwieldy.
This way of structuring i18n yaml files seemed to work well with some local test apps I tried it on. I'm hoping the wonderful Localeapp will provide support for this kind of anchoring/referencing in the future. But anyway, all this dictionary talk can't possibly be an original idea, so are there other issues with anchor referencing in YAML, or maybe just with the whole "dictionary" concept in general? Or is it just better to just rip out the default backend entirely and replace it with Redis or something?
Your question is not easy to answer, and there is not much material available on that topic. I have found the best resources are:
Rails Styleguide, section Internationalization
There are a lot of resources in the I18n wiki, but I don't have found there some that answer your questions.
So I will give it a try directly here:
Navigation
I think you mean here the navigation elements like breadcrumbs, tabs, ...
You have to define views for them, and stick then to the rule to move all view elements in separate files in the directory views (see the styleguide for the rule).
Button text (save changes, create account, etc)
View elements, go into the same files as well. If you use the same buttons in different views, define a common file, and use that then.
Error messages from controller flash
I would use the same rule as for views. Define a separate directory, include there the files for the controllers.
How to add multi-word keys. Do I use a space or an underscore? For exmaple, t(".update button")) or t(".update_button")
I personally would prefer to use .update_button, not .update button, because it makes more explicit that this is one key.
It's almost two years after I asked this question, and I want to share some insights. I believe the optimal structure is to namespace translations according to their MVC role (models, views, controllers). This keeps the locale file tidy, and prevents namespace collisions (for example, the scope en.users can represent a view or a controller).
en:
controllers:
users:
show:
welcome_flash: "Welcome back!"
mailers:
users_mailer:
welcome_email:
subject: "Good of you to join us"
views:
users:
show:
notice: "Oh no!
But using tidy namespaces like that breaks the lazy lookup feature in Rails. If you use lazy lookup, Rails will insert the namespace automatically for you, and it will not include the top level namespaces you created (views, controllers, etc...).
For example, the scope of t('.welcome_flash') resolves to en.users.show. Which stinks because users isn't clearly defined. What is it? A controller? A view? Something else?
To solve this problem I created the gem I18nLazyLookup. It allows you to use lazy lookup with your own custom namespaces.
Instead of using t, you can use t_scoped('welcome_flash'), and that would automatically resolve the scope to en.controllers.users.show. It also works for views and mailers, and you can customise the namespace the way you like.
Editing directly the yaml files leads to messy and unreadable files.
Moreover, it'll be difficult for you to provide access to translators if, someday, you want a non-developer to add a new language.
I would recommend using localeapp, which generates a single yaml file.
But allows you to easily see and manage your translations in a web interface.
And to create additional access to translators.
Coming several years after the battle, but here is a (somewhat totally) different answer.
To begin with, I do not like the standard t('.xxx') style with the default namespace based on the file structure. I also don't really like the categorisation of translations depending on the DOM structure. While this is a nice approach for very structured translations, it is often repetitive, and not very intuitive.
I'd rather regroup my translations into more useful categories, so as to make it easier for my translators, because they can work on concrete themes, rather than some weird styles (some translators do not even know what MVC means)
so my translation file is structured like this
fr:
theme1:
theme11:
translationxxx: blabla
theme2:
translationyyy: blabla
Depending on the needs, the "themes" can be a model, a more abstract context, etc. that is the most intuitive for the translators.
Because this would be a hassle to write everytime the scope in my views, I have added some convenience methods in my helpers to have a stack based translation context.
I push/pop translation scopes on a stack in my views by calling t_scope([new_scope] and pop_t
I override the t helper to use the last scope of the stack
The code for the translation scoping methods is available in that answer

Specifying and Executing Rules in Ruby

I am looking for a Ruby/Rails tool that will help me accomplish the following:
I would like to store the following string, and ones similar to it, in my database. When an object is created, updated, deleted, etc., I want to run through all the strings, check to see if the CRUD event matches the conditions of the string, and if so, run the actions specified.
When a new ticket is created and it's category=6 then notify user 1234 via email
I am planning to create an interface that builds these strings, so it doesn't need to be a human-readable string. If a JSONish structure is better, or a tool has an existing language, that would be fantastic. I'm kinda thinking something along the lines of:
{
object_types: ['ticket'],
events: ['created', 'updated'],
conditions:'ticket.category=6',
actions: 'notify user',
parameters: {
user:1234,
type:'email'
}
}
So basically, I need the following:
Monitor CRUD events - It would be nice if the tool had a way to do this, but Ican use Rails' ModelObservers here if the tool doesn't natively provide it
Find all matching "rules" - This is my major unknown...
Execute the requested method/parameters - Ideally, this would be defined in my Ruby code as classes/methods
Are there any existing tools that I should investigate?
Edit:
Thanks for the responses so far guys! I really appreciate you pointing me down the right paths.
The use case here is that we have many different clients, with many different business rules. For the rules that apply to all clients, I can easily create those in code (using something like Ruleby), but for all of the client-specific ones, I'd like to store them in the database. Ideally, the rule could be written once, stored either in the code, or in the DB, and then run (using something Resque for performance).
At this point, it looks like I'm going to have to roll my own, so any thoughts as to the best way to do that, or any tools I should investigate, would be greatly appreciated.
Thanks again!
I don't think it would be a major thing to write something yourself to do this, I don't know of any gems which would do this (but it would be good if someone wrote one!)
I would tackle the project in the following way, the way I am thinking is that you don't want to do the rule matching at the point the user saves as it may take a while and could interrupt the user experience and/or slow up the server, so...
Use observers to store a record each time a CRUD event happens, or to make things simpler use the Acts as Audited gem which does this for you.
1.5. Use a rake task, running from your crontab to run through the latest changes, perhaps every minute, or you could use Resque which does a good job of handling lots of jobs
Create a set of tables which define the possible rules a user could select from, perhaps something like
Table: Rule
Name
ForEvent (eg. CRUD)
TableInQuestion
FieldOneName
FieldOneCondition etc.
MethodToExecute
You can use a bit of metaprogramming to execute your method and since your method knows your table name and record id then this can be picked up.
Additional Notes
The best way to get going with this is to start simple then work upwards. To get the simple version working first I'd do the following ...
Install acts as audited
Add an additional field to the created audit table, :when_processed
Create yourself a module in your /lib folder called something like processrules which roughly does this
3.1 Grabs all unprocessed audit entries
3.2 Marks them as processed (perhaps make another small audit table at this point to record events happening)
Now create a rules table which simply has a name and condition statement, perhaps add a few sample ones to get going
Name: First | Rule Statement: 'SELECT 1 WHERE table.value = something'
Adapt your new processrules method to execute that sql for each changed entry (perhaps you want to restrict it to just the tables you are working with)
If the rule matched, add it to your log file.
From here you can extrapolate out the additional functionality you need and perhaps ask another question about the metaprogramaming side of dynamically calling methods as this question is quite broad, am more than happy to help further.
I tend to think the best way to go about task processing is to setup the process nicely first so it will work with any server load and situation then plug in the custom bits.
You could make this abstract enough so that you can specify arbitrary conditions and rules, but then you'd be developing a framework/engine as opposed to solving the specific problems of your app.
There's a good chance that using ActiveRecord::Observer will solve your needs, since you can hardcode all the different types of conditions you expect, and then only put the unknowns in the database. For example, say you know that you'll have people watching categories, then create an association like category_watchers, and use the following Observer:
class TicketObserver < ActiveRecord::Observer
# observe :ticket # not needed here, since it's inferred by the class name
def after_create(ticket)
ticket.category.watchers.each{ |user| notify_user(ticket, user) }
end
# def after_update ... (similar)
private
def notify_user(ticket, user)
# lookup the user's stored email preferences
# send an email if appropriate
end
end
If you want to store the email preference along with the fact that the user is watching the category, then use a join model with a flag indicating that.
If you then want to abstract it a step further, I'd suggest using something like treetop to generate the observers themselves, but I'm not convinced that this adds more value than abstracting similar observers in code.
There's a Ruby & Rules Engines SO post that might have some info that you might find useful. There's another Ruby-based rules engine that you may want to explore that as well - Ruleby.
Hope that this helps you start your investigation.

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.

Where is the best place to store application parameters : database, file, code...?

I am developing a Ruby on Rails website and I have an "architectural" question : my application needs some parameters and I'm wondering where to store them.
In concrete terms, my application receive some requests which are evaluated and then sent. So, the Request model must have attributes concerning these treatments : a validation status and a sending status. For instance, validation status can be "accepted", "rejected" or "waiting". Sending status can be "sent", "waiting", "error during sending" or stuff like that. I have to store those status codes parameters somewhere, but I don't know what is the best solution.
I could create a model for each one and store them in the database (and having an active record model ValidationStatus for instance) but : wouldn't it be a bite excessive to create a database/model for storing data like that?
I could also just use them in the code without "storing" them, I could store them in a YAML file...
So, a more simpler question: how do you deal with your application parameters in RoR?
There are lots of global configuration plugins, most of them revolve around the idea of loading a YAML file at some point. Check this page, this plugin and even this Railscast.
I put them in the database. I have a lot of these, and they are all pretty straightforward lists of strings. The tables are all the same - id, name, description.
I generate models for them rather than having an actual model file for each one. In app/models I have a file called active_record_enums.rb, which in your case would look something like this:
ACTIVE_RECORD_ENUMS = %w{
ValidationStatus
SendingStatus
}
ACTIVE_RECORD_ENUMS.each do |classname|
eval "class #{classname} < ActiveRecord::Base; end"
classname.constantsize.class_eval do
# Add useful methods - id_for(name) and value_for(id) are handy
end
end
This file has to be required in a config file somewhere; other than that it's pretty straightforward.
(Have since viewed that rails cast mentioned above [episode 85] - it looks like a bit more 'the rails way' than below)
Another approach is to build on the existing configuration mechanism in Rails.
Lets presume there are two types of configs:
App wide configs common to dev/test/prod environments
Configs specific to envrionments dev/test/prod
For the first scenario, items in "RAILS_ROOT + '/config/environment.rb'" work. Just see that the names are captialised so they are Ruby constants. A variation to this is have a reference to another file in that environment.rb file ...
require RAILS_ROOT + '/config/appConfigCommon.rb'
and place relevant config items in that file. This has the advantage of being able to be referenced independant of Rails.
For scenario 2, a similar approach can be taken. Place items for development in "RAILS_ROOT + '/config/environments/development.rb'" or something like
require RAILS_ROOT + '/config/environments/appConfigDev.rb'
and place environment specific items in that required file, making sure they start with caps. And follow the same pattern for test/prod (and others if need be).
The config items are directly accessible in views and controllers (not sure about models) by simply using the constant name.
I am not using Ruby but I will tell you that I started out (in ASP.NET) placing lots of settings in a Web.Config file (similar to a YAML). As time went on, though, the system evolved to the point where different instances needed different settings. So, almost all of them have migrated to the database. So...if you'll be deploying multiple instances of your site, I'd strongly recommend keeping settings in a table of your database (mine has just one record, with fields for various settings). If I had done this to start, I'd have saved a significant amount of time.
I tend to just make a string column for each, and use validates_inclusion_of to set what's acceptable for them.
class Request < ActiveRecord::Base
validates_inclusion_of :validation_status, :in => ['accepted','rejected','waiting']
validates_inclusion_of :sending_status, :in => ['sent','waiting','...']
end
If you need to have things happen (ie. emails sent) when the status changes, look into using the Acts As State Machine plugin to manage it.

Resources