How to validate/limit attachment file size - phoenix-framework

In an Ecto model with attachment using arc and arc_ecto:
use Arc.Ecto.Schema
schema "profiles" do
...
field :avatar, MyApp.AvatarUploader.Type
...
timestamps()
end
How can I validate/limit the size of the attachment?
I read about it in the guides with the configuration of Plug.Parsers but I would like to do this at a model level and not at the application level. For instance the user avatar should be small but other picture should be larger.
What's the best way to achieve this?

In case anyone is wondering, I believe can validate before storing the file in the module where you define your arc definitions: https://github.com/stavro/arc#file-validation
Something like the following:
def validate({%Arc.File{path: path}, _}) do
%{size: size} = File.stat!(path)
# less than 100 bytes
size < 100
end
This should work with arc_ecto

Related

I am trying to retrieve data from a Ruby cdn of the Pokemon API but I am struggling

Below is my Pokemon TCG API key
I have read the documentation but I cannot find a way to retrieve the data I need which is the images of each card in a set. If anyone can help with or give me any pointers on how to retrieve this I would greatly appreciate it.
https://github.com/PokemonTCG/pokemon-tcg-sdk-ruby/blob/master/README.md
This above is the link to the documentation on Github.
Pokemon.configure do |config|
config.api_key = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
end
sets = Pokemon::Set.where(q: 'legalities.standard:legal').first
p sets
I am expecting to retrieve specific data from the Pokemon TCG API which from above should be within these Ruby classes.
p sets.images.symbol will print out the link to:
"https://images.pokemontcg.io/swshp/symbol.png"
p sets.images.logo will print out the link to:
"https://images.pokemontcg.io/swshp/logo.png"
When you are unsure what is contained within the class you're getting, in this case a Pokemon::Set class, you may see all the methods of this resulting variable with sets.methods.sort.each{|m| p m}, there you'll find the images method and can dig deeper to symbol and logo.
In your example you are searching for sets. In case of cards:
cards = Pokemon::Card.where(page: 5, pageSize: 100)
cards.each{|card| p card.images.large}
This will print out all the links to large cards.
Update
Clarification based on comments
How to print out methods and how to know which class you are referring to.
Let's start with you code snippet:
sets = Pokemon::Set.where(q: 'legalities.standard:legal').first
puts sets.class
Output:
Pokemon::Set
It would be more clear if you name your variable as set because you're selecting the .first element of an array.
Back to my cards example:
cards = Pokemon::Card.where(page: 5, pageSize: 100)
puts cards.class
Output:
Array
As I did not select any item from the array cards naming makes perfect sense, and this array will contain a card:
card = cards.first
puts card.class
Output
Pokemon::Card
Printing methods
So, given we are now well aware of class each variable contains and what we are referring to, we are ready to print out the methods for both:
sets.methods.sort.each{|method| p method}
cards[0].methods.sort.each{|method| p method}
Output:
…
:hash
:hp
:hp=
:id
:id=
:images <== Here!
:images=
:inspect
:instance_eval
:instance_exec
:instance_of?
…
Once again, mind the [0] selection of the first item. When we want to know methods, we want to know it either for Pokemon::Set or Pokemon::Card.

rails string substitution or similar solution in controller

I'm building a site with users in all 50 states. We need to display information for each user that is specific to their situation, e.g., the number of events they completed in that state. Each state's view (a partial) displays state-specific information and, therefore, relies upon state-specific calculations in a state-specific model. We'd like to do something similar to this:
##{user.state} = #{user.state.capitalize}.new(current_user)
in the users_controller instead of
#illinois = Illinois.new(current_user) if (#user.state == 'illinois')
.... [and the remaining 49 states]
#wisconsin = Wisconsin.new(current_user) if (#user.state == 'wisconsin')
to trigger the Illinois.rb model and, in turn, drive the view defined in the users_controller by
def user_state_view
#user = current_user
#events = Event.all
#illinois = Illinois.new(current_user) if (#user.state == 'illinois')
end
I'm struggling to find a better way to do this / refactor it. Thanks!
I would avoid dynamically defining instance variables if you can help it. It can be done with instance_variable_set but it's unnecessary. There's no reason you need to define the variable as #illinois instead of just #user_state or something like that. Here is one way to do it.
First make a static list of states:
def states
%{wisconsin arkansas new_york etc}
end
then make a dictionary which maps those states to their classes:
def state_classes
states.reduce({}) do |memo, state|
memo[state] = state.camelize.constantize
memo
end
end
# = { 'illinois' => Illinois, 'wisconsin' => Wisconsin, 'new_york' => NewYork, etc }
It's important that you hard-code a list of state identifiers somewhere, because it's not a good practice to pass arbitrary values to contantize.
Then instantiating the correct class is a breeze:
#user_state = state_classes[#user.state].new(current_user)
there are definitely other ways to do this (for example, it could be added on the model layer instead)

Concept for recipe-based parsing of webpages needed

I'm working on a web-scraping solution that grabs totally different webpages and lets the user define rules/scripts in order to extract information from the page.
I started scraping from a single domain and build a parser based on Nokogiri.
Basically everything works fine.
I could now add a ruby class each time somebody wants to add a webpage with a different layout/style.
Instead I thought about using an approach where the user specifies elements where content is stored using xpath and storing this as a sort of recipe for this webpage.
Example: The user wants to scrape a table-structure extracting the rows using a hash (column-name => cell-content)
I was thinking about writing a ruby function for extraction of this generic table information once:
# extracts a table's rows as an array of hashes (column_name => cell content)
# html - the html-file as a string
# xpath_table - specifies the html table as xpath which hold the data to be extracted
def basic_table(html, xpath_table)
xpath_headers = "#{xpath_table}/thead/tr/th"
html_doc = Nokogiri::HTML(html)
html_doc = Nokogiri::HTML(html)
row_headers = html_doc.xpath(xpath_headers)
row_headers = row_headers.map do |column|
column.inner_text
end
row_contents = Array.new
table_rows = html_doc.xpath('#{xpath_table}/tbody/tr')
table_rows.each do |table_row|
cells = table_row.xpath('td')
cells = cells.map do |cell|
cell.inner_text
end
row_content_hash = Hash.new
cells.each_with_index do |cell_string, column_index|
row_content_hash[row_headers[column_index]] = cell_string
end
row_contents << [row_content_hash]
end
return row_contents
end
The user could now specify a website-recipe-file like this:
<basic_table xpath='//div[#id="grid"]/table[#id="displayGrid"]'
The function basic_table is referenced here, so that by parsing the website-recipe-file I would know that I can use the function basic_table to extract the content from the table referenced by the xPath.
This way the user can specify simple recipe-scripts and only has to dive into writing actual code if he needs a new way of extracting information.
The code would not change every time a new webpage needs to be parsed.
Whenever the structure of a webpage changes only the recipe-script would need to be changed.
I was thinking that someone might be able to tell me how he would approach this. Rules/rule engines pop into my mind, but I'm not sure if that really is the solution to my problem.
Somehow I have the feeling that I don't want to "invent" my own solution to handle this problem.
Does anybody have a suggestion?
J.

Qt GUI Table / Spreadsheet type layout in Ruby

I am trying to design a GUI that will output data in a spreadsheet type of format, rows and columns.
The cells will be populated with data that will be fetched by another object at predefined intervals. Being able to change individual cell color would be ideal to highlight any cells that have changed.
After some research it seems like QtBindings gem for ruby is the most powerful GUI choice for this but I can't seem to find any documentation or examples that would help me with what I am trying to accomplish. Any advice in the form of code or examples would be more than helpful. Thank you.
Update:: after some research and brute force, I came up with this code:
class PositionModel < Qt::AbstractTableModel
slots 'timerhit()'
def initialize(risk)
super()
#timer = Qt::Timer.new(self)
connect(#timer, SIGNAL('timeout()'), self, SLOT('timerhit()'))
#timer.start(1000)
#risk = risk
#risk_a = #risk.to_a
#pp #risk_a
end
def timerhit()
emit dataChanged(createIndex(0,0), createIndex(0,0))
#emit dataChanged()
end
def rowCount(parent)
#risk_a.size
end
def columnCount(parent)
1
end
def data(index, role)
col = index.column
row = index.row
if role == Qt::DisplayRole
return Qt::Variant.new( #risk_a[row] )
else
return Qt::Variant.new()
end
end
end
app = Qt::Application.new(ARGV)
model = PositionModel.new(##risk)
table = Qt::TableView.new
table.model = model
table.setSortingEnabled(true)
table.show
It seems to be working well, and more importantly is a solid foundation for what I ultimately want to accomplish. However, I I tried to enable sorting by clicking on a column header, but it doesnt seem to be working. Does anyone know why?
Two words: Use QTableView or QTableWidget.
Populating Table Widget from Text File in Qt
How change row color with Null items?
Converting the c++ code to ruby qt should be trivial. Also the C++ Qt docs are awesome! Good luck.
Hope that helps.

How to use Koala Facebook Graph API?

I am a Rails newbie. I want to use Koala's Graph API.
In my controller
#graph = Koala::Facebook::API.new('myFacebookAccessToken')
#hello = #graph.get_object("my.Name")
When I do this, I get something like this
{
"id"=>"123456",
"name"=>"First Middle Last",
"first_name"=>"First",
"middle_name"=>"Middle",
"last_name"=>"Last",
"link"=>"http://www.facebook.com/MyName",
"username"=>"my.name",
"birthday"=>"12/12/1212",
"hometown"=>{"id"=>"115200305133358163", "name"=>"City, State"}, "location"=>{"id"=>"1054648928202133335", "name"=>"City, State"},
"bio"=>"This is my awesome Bio.",
"quotes"=>"I am the master of my fate; I am the captain of my soul. - William Ernest Henley\r\n\r\n"Don't go around saying the world owes you a living. The world owes you nothing. It was here first.\" - Mark Twain",
"work"=>[{"employer"=>{"id"=>"100751133333", "name"=>"Company1"}, "position"=>{"id"=>"105763693332790962", "name"=>"Position1"}, "start_date"=>"2010-08", "end_date"=>"2011-07"}],
"sports"=>[{"id"=>"104019549633137", "name"=>"Sport1"}, {"id"=>"103992339636529", "name"=>"Sport2"}],
"favorite_teams"=>[{"id"=>"105467226133353743", "name"=>"Fav1"}, {"id"=>"19031343444432369133", "name"=>"Fav2"}, {"id"=>"98027790139333", "name"=>"Fav3"}, {"id"=>"104055132963393331", "name"=>"Fav4"}, {"id"=>"191744431437533310", "name"=>"Fav5"}],
"favorite_athletes"=>[{"id"=>"10836600585799922", "name"=>"Fava1"}, {"id"=>"18995689436787722", "name"=>"Fava2"}, {"id"=>"11156342219404022", "name"=>"Fava4"}, {"id"=>"11169998212279347", "name"=>"Fava5"}, {"id"=>"122326564475039", "name"=>"Fava6"}],
"inspirational_people"=>[{"id"=>"16383141733798", "name"=>"Fava7"}, {"id"=>"113529011990793335", "name"=>"fava8"}, {"id"=>"112032333138809855566", "name"=>"Fava9"}, {"id"=>"10810367588423324", "name"=>"Fava10"}],
"education"=>[{"school"=>{"id"=>"13478880321332322233663", "name"=>"School1"}, "type"=>"High School", "with"=>[{"id"=>"1401052755", "name"=>"Friend1"}]}, {"school"=>{"id"=>"11482777188037224", "name"=>"School2"}, "year"=>{"id"=>"138383069535219", "name"=>"2005"}, "type"=>"High School"}, {"school"=>{"id"=>"10604484633093514", "name"=>"School3"}, "year"=>{"id"=>"142963519060927", "name"=>"2010"}, "concentration"=>[{"id"=>"10407695629335773", "name"=>"c1"}], "type"=>"College"}, {"school"=>{"id"=>"22030497466330708", "name"=>"School4"}, "degree"=>{"id"=>"19233130157477979", "name"=>"c3"}, "year"=>{"id"=>"201638419856163", "name"=>"2011"}, "type"=>"Graduate School"}],
"gender"=>"male",
"interested_in"=>["female"],
"relationship_status"=>"Single",
"religion"=>"Religion1",
"political"=>"Political1",
"email"=>"somename#somecompany.com",
"timezone"=>-8,
"locale"=>"en_US",
"languages"=>[{"id"=>"10605952233759137", "name"=>"English"}, {"id"=>"10337617475934611", "name"=>"L2"}, {"id"=>"11296944428713061", "name"=>"L3"}],
"verified"=>true,
"updated_time"=>"2012-02-24T04:18:05+0000"
}
How do I show this entire hash in the view in a good format?
This is what I did from what ever I learnt..
In my view
<% #hello.each do |key, value| %>
<li><%=h "#{key.to_s} : #{value.to_s}" %></li>
<% end %>
This will get the entire thing converted to a list... It works awesome if its just one key.. but how to work with multiple keys and show only the information... something like
when it outputs hometown : City, State rather than something like
hometown : {"id"=>"115200305133358163", "name"=>"City, State"}
Also for education if I just say education[school][name] to display list of schools attended?
The error i get is can't convert String into Integer
I also tried to do this in my controller, but I get the same error..
#fav_teams = #hello["favorite_teams"]["name"]
Also, how can I save all these to the database.. something like just the list of all schools.. not their id no's?
Update:
The way I plan to save to my database is.. lets say for a user model, i want to save to database as :facebook_id, :facebook_name, :facebook_firstname, ...., :facebook_hometown .. here I only want to save name... when it comes to education.. I want to save.. school, concentration and type.. I have no idea on how to achieve this..
Looking forward for help! thanks!
To show the hash in a pretty-printed way, use the gem 'awesome_print'.
Add this to your Gemfile:
gem 'awesome_print'
And then run:
bundle install
And then, in your view, you can add:
<%= ap #hello %>
The question of how to store in the database requires a little more information on what you plan to do with it, but at minimum you could create a model, add a 'facebook_data' (type would be 'text') on that model, and then serialize it (add this line near the top of your model file: serialize :facebook_data). Then you could assign the hash (#hello in this case) to the model's 'facebook_data' property, and then save the model. But you won't be able to query your database for individual attributes of this facebook data very easily this way.
you can just do #hello["name"] then it will give you the value of the name
Your #hello object should be of the class Koala::Facebook::API::GraphCollection or something similar. You should be able to loop through this object, like your question demonstrates. As for what code to put inside your loop that will help you save records to the database, assuming your rails user model class name is User, try something like this:
#hello.each do |h|
u = User.where(:facebook_id => h["id"]).first_or_initialize
u.update_attributes(
:name => h["name"],
:first_name => h["first_name"],
:hometown_city => h["hometown"]["name"].split(",").first,
:hometown_state => h["hometown"]["name"].split(",").last.strip
# ETC, ETC
)
end
In the case of the hometown and education fields, you're just going to have to traverse the ruby hash the proper way. See the docs for more info.

Resources